first commit
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
Base_Autoloader::Register();
|
||||
|
||||
// ================
|
||||
// Autoloader Class
|
||||
// ================
|
||||
|
||||
class Base_Autoloader {
|
||||
|
||||
public static function Register() {
|
||||
|
||||
if (function_exists("__autoload")) {
|
||||
spl_autoload_register("__autoload");
|
||||
}
|
||||
|
||||
return spl_autoload_register(array("Base_Autoloader", "Load"), true, true);
|
||||
|
||||
}
|
||||
|
||||
public static function Load($pClassName) {
|
||||
|
||||
if (class_exists($pClassName, false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Try for a "classes" Class first, then a "reports" Class.
|
||||
|
||||
$pClassFilePath = "classes/{$pClassName}.php";
|
||||
|
||||
if ((file_exists($pClassFilePath) === false) || (is_readable($pClassFilePath) === false)) {
|
||||
|
||||
$pClassFilePath = "reports/{$pClassName}.php";
|
||||
|
||||
if ((file_exists($pClassFilePath) === false) || (is_readable($pClassFilePath) === false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
require($pClassFilePath);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,803 @@
|
||||
<?php
|
||||
|
||||
// ==========
|
||||
// Base Class
|
||||
// ==========
|
||||
|
||||
require_once "vendor/autoload.php";
|
||||
require_once "classes/Autoloader.php";
|
||||
|
||||
class Base {
|
||||
|
||||
// =========
|
||||
// Constants
|
||||
// =========
|
||||
|
||||
const APPLICATION_NAME = "VoterVue";
|
||||
const APPLICATION_MNEMONIC = "VOTERVUE";
|
||||
const VERSION = "2.00";
|
||||
const TIMEZONE = "America/New_York";
|
||||
// =================
|
||||
// Session Variables
|
||||
// =================
|
||||
|
||||
const ENVIRONMENT = "VOTERVUE_ENVIRONMENT";
|
||||
const ACTIVE_SESSION = "VOTERVUE_ACTIVE_SESSION";
|
||||
const USER_ID = "VOTERVUE_USER_ID";
|
||||
const USER_SERIAL = "VOTERVUE_USER_SERIAL";
|
||||
const USER_NAME = "VOTERVUE_USER_NAME";
|
||||
const USER_CLIENT_NAME = "VOTERVUE_USER_CLIENT_NAME";
|
||||
const USER_EMAIL = "VOTERVUE_USER_EMAIL";
|
||||
const USER_ROLE = "VOTERVUE_USER_ROLE";
|
||||
const USER_AUTHENTICATED = "VOTERVUE_USER_AUTHENTICATED";
|
||||
const REPORTS_GET = "VOTERVUE_REPORTS_GET";
|
||||
const REPORTS_POST = "VOTERVUE_REPORTS_POST";
|
||||
const THEME = "VOTERVUE_THEME";
|
||||
const AJAX = "VOTERVUE_AJAX";
|
||||
const TODAY = "VOTERVUE_TODAY";
|
||||
const COPYRIGHT = "VOTERVUE_COPYRIGHT";
|
||||
const PAGE = "VOTERVUE_PAGE";
|
||||
const PAGINATION_PAGE = "VOTERVUE_PAGINATION_PAGE";
|
||||
|
||||
// =================
|
||||
// Class Constructor
|
||||
// =================
|
||||
|
||||
public function __construct() {
|
||||
|
||||
set_error_handler(array($this, "displayError"));
|
||||
|
||||
date_default_timezone_set(self::TIMEZONE);
|
||||
}
|
||||
|
||||
// ===============================================
|
||||
// Append a SimpleXMLElement to a SimpleXMLElememt
|
||||
// ===============================================
|
||||
|
||||
public function appendSXE(SimpleXMLElement $from, SimpleXMLElement $to) {
|
||||
|
||||
$toDOM = dom_import_simplexml($to);
|
||||
$fromDOM = dom_import_simplexml($from);
|
||||
|
||||
$toDOM->appendChild($toDOM->ownerDocument->importNode($fromDOM, true));
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// Apply an XSL Stylesheet to an XML Document
|
||||
// ==========================================
|
||||
|
||||
public function applyXSL($XMLString = "", $XSLString = "", $XSLParms = "") {
|
||||
|
||||
if ($XMLString instanceof SimpleXMLElement) {
|
||||
$XMLString = $XMLString->asXML();
|
||||
}
|
||||
|
||||
if (empty($XSLString)) {
|
||||
trigger_error("No XSL Stylesheet provided.");
|
||||
}
|
||||
|
||||
if (!is_array($XSLParms)) {
|
||||
$XSLParms = array();
|
||||
}
|
||||
|
||||
$XSLParms["APPLICATION_NAME"] = self::APPLICATION_NAME;
|
||||
$XSLParms["APPLICATION_MNEMONIC"] = self::APPLICATION_MNEMONIC;
|
||||
$XSLParms["VERSION"] = self::VERSION;
|
||||
$XSLParms["THEME"] = $_SESSION[self::THEME] ?? self::THEME;
|
||||
$XSLParms["ENVIRONMENT"] = $_SESSION[self::ENVIRONMENT] ?? "Production";
|
||||
$XSLParms["USER_NAME"] = $_SESSION[self::USER_NAME] ?? "";
|
||||
$XSLParms["USER_CLIENT_NAME"] = $_SESSION[self::USER_CLIENT_NAME] ?? "";
|
||||
$XSLParms["USER_ROLE"] = $_SESSION[self::USER_ROLE] ?? "Guest";
|
||||
$XSLParms["RANDOM_NUMBER"] = rand();
|
||||
$XSLParms["TODAY_YYYYMMDD"] = date("Y-m-d");
|
||||
$XSLParms["TODAY_MMDDYYYY"] = date("m/d/Y");
|
||||
$XSLParms["COPYRIGHT"] = date("Y");
|
||||
|
||||
$XML = new DOMDocument();
|
||||
$XSL = new DOMDocument();
|
||||
$XSLT = new XSLTProcessor();
|
||||
|
||||
if ($XMLString) {
|
||||
$XML->loadXML($XMLString);
|
||||
}
|
||||
|
||||
if ($XSLString) {
|
||||
$XSL->loadXML($XSLString);
|
||||
}
|
||||
|
||||
$XSLT->importStylesheet($XSL);
|
||||
|
||||
if ($XSLParms) {
|
||||
$XSLT->setParameter("", $XSLParms);
|
||||
}
|
||||
|
||||
$document = $XSLT->transformToXml($XML);
|
||||
|
||||
return $document;
|
||||
}
|
||||
|
||||
// ============================
|
||||
// Return a Database Connection
|
||||
// ============================
|
||||
|
||||
public function connect() {
|
||||
|
||||
$Settings = $this->getSettings();
|
||||
|
||||
try {
|
||||
|
||||
$host = (string) $Settings->DatabaseServer;
|
||||
$database = (string) $Settings->DatabaseName;
|
||||
$user = (string) $Settings->DatabaseUser;
|
||||
$password = (string) $Settings->DatabasePassword;
|
||||
|
||||
$connection = new PDO("mysql:host={$host};dbname={$database};charset=utf8", $user, $password);
|
||||
|
||||
$connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
|
||||
$connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
} catch (PDOException | Exception $e) {
|
||||
|
||||
trigger_error($e->getMessage());
|
||||
}
|
||||
|
||||
return $connection;
|
||||
}
|
||||
|
||||
// ===============
|
||||
// Debug an Object
|
||||
// ===============
|
||||
|
||||
public function debug($object = "") {
|
||||
|
||||
if ($_SESSION[self::AJAX]) {
|
||||
error_log(print_r($object, true));
|
||||
} else {
|
||||
echo "<pre>";
|
||||
print_r($object);
|
||||
}
|
||||
|
||||
exit();
|
||||
}
|
||||
|
||||
// =========================
|
||||
// Return a decrypted string
|
||||
// =========================
|
||||
|
||||
protected function decrypt($encrypted = "", $key = "") {
|
||||
|
||||
$key = (empty($key)) ? __CLASS__ : $key;
|
||||
|
||||
$decoded = base64_decode($encrypted);
|
||||
$ivlen = openssl_cipher_iv_length($cipher = "AES-128-CBC");
|
||||
$iv = substr($decoded, 0, $ivlen);
|
||||
$hmac = substr($decoded, $ivlen, $sha2len = 32);
|
||||
$raw = substr($decoded, $ivlen + $sha2len);
|
||||
$decrypted = openssl_decrypt($raw, $cipher, $key, $options = OPENSSL_RAW_DATA, $iv);
|
||||
$calcmac = hash_hmac("sha256", $raw, $key, $as_binary = true);
|
||||
|
||||
if (($hmac === false) or ($calcmac === false)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return (hash_equals($hmac, $calcmac)) ? $decrypted : "";
|
||||
}
|
||||
|
||||
// ======================
|
||||
// Display a Content Page
|
||||
// ======================
|
||||
|
||||
public function displayContent($content = "") {
|
||||
|
||||
$html = $this->applyXSL("", $this->getXSL("./system/content"));
|
||||
$html = str_replace("$$$-CONTENT-$$$", $content, $html);
|
||||
|
||||
echo $html;
|
||||
|
||||
exit();
|
||||
}
|
||||
|
||||
// =====================
|
||||
// Display a Notice Page
|
||||
// =====================
|
||||
|
||||
public function displayNotice($messgae = "") {
|
||||
|
||||
$XSLParms["MESSAGE"] = $messgae;
|
||||
|
||||
$content = $this->applyXSL("", $this->getXSL("system/notice"), $XSLParms);
|
||||
|
||||
$this->displayContent($content);
|
||||
|
||||
exit();
|
||||
}
|
||||
|
||||
// ======================================================
|
||||
// Custom error handler to display informative error page
|
||||
// ======================================================
|
||||
|
||||
public function displayError($error_number = "", $error_message = "", $error_file = "", $error_line = "") {
|
||||
|
||||
if (error_reporting() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$error_file = explode("/", $error_file);
|
||||
$error_file = end($error_file);
|
||||
$error_message = str_replace("'", '"', $error_message);
|
||||
|
||||
(new Journal())->journalEntry("{$error_file} | {$error_line} | {$error_message}");
|
||||
|
||||
if (($_SESSION[self::ENVIRONMENT] ?? "Production") == "Production") {
|
||||
(new Email())->sendErrorEmail($error_message, $error_file, $error_line);
|
||||
}
|
||||
|
||||
$XSLParms["FILE_NAME"] = $error_file;
|
||||
$XSLParms["LINE_NUMBER"] = $error_line;
|
||||
$XSLParms["ERROR_MESSAGE"] = $error_message;
|
||||
$XSLParms["ERROR_NUMBER"] = $error_number;
|
||||
|
||||
$content = $this->applyXSL("", $this->getXSL("./system/error"), $XSLParms);
|
||||
|
||||
$this->displayContent($content);
|
||||
|
||||
exit(); // Exit so that only one error is presented.
|
||||
}
|
||||
|
||||
// =====================
|
||||
// Display the Home Page
|
||||
// =====================
|
||||
|
||||
public function displayHome() {
|
||||
|
||||
$content = $this->applyXSL("", $this->getXSL("./system/home"));
|
||||
$this->displayContent($content);
|
||||
}
|
||||
|
||||
// =======================
|
||||
// Do the requested Action
|
||||
// =======================
|
||||
|
||||
public function do() {
|
||||
|
||||
$_SESSION[self::TODAY] = date("Y-m-d");
|
||||
|
||||
// Login
|
||||
|
||||
if (($_SESSION[self::USER_AUTHENTICATED] ?? false) === false) {
|
||||
|
||||
(new Users())->login();
|
||||
}
|
||||
|
||||
// Determine if user needs a password change
|
||||
if ($this->userChangePassword() === true) {
|
||||
(new Users())->changePassword();
|
||||
exit();
|
||||
}
|
||||
|
||||
// Determine if this is an AJAX request.
|
||||
|
||||
$_SESSION[self::AJAX] = (isset($_SERVER["HTTP_X_REQUESTED_WITH"]) and strtolower($_SERVER["HTTP_X_REQUESTED_WITH"]) === "xmlhttprequest");
|
||||
|
||||
// Get the requested Action
|
||||
|
||||
$action = filter_input(INPUT_POST, "action") ?: "";
|
||||
$Xaction = filter_input(INPUT_GET, "Xaction") ?: "";
|
||||
|
||||
$action = (empty($Xaction) ? $action : $Xaction);
|
||||
|
||||
// Sign Out if requested.
|
||||
|
||||
if (strtolower(trim($action)) === "signout") {
|
||||
$this->initializeSession();
|
||||
}
|
||||
|
||||
// Process the requested Action.
|
||||
|
||||
list($class, $method) = array_pad(explode('.', $action), 2, "");
|
||||
|
||||
if (empty($method)) {
|
||||
|
||||
$method = $class;
|
||||
|
||||
if (method_exists(__CLASS__, $method)) {
|
||||
$this->$method();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
||||
if (method_exists($class, $method)) {
|
||||
(new $class())->$method();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Default to the Home Page.
|
||||
$this->displayHome();
|
||||
}
|
||||
|
||||
// ==========================
|
||||
// Return an encrypted string
|
||||
// ==========================
|
||||
|
||||
protected function encrypt($string = "", $key = "") {
|
||||
|
||||
$key = (empty($key)) ? __CLASS__ : $key;
|
||||
|
||||
$ivlen = openssl_cipher_iv_length($cipher = "AES-128-CBC");
|
||||
$iv = openssl_random_pseudo_bytes($ivlen);
|
||||
$raw = openssl_encrypt($string, $cipher, $key, $options = OPENSSL_RAW_DATA, $iv);
|
||||
$hmac = hash_hmac("sha256", $raw, $key, $as_binary = true);
|
||||
$encrypted = base64_encode($iv . $hmac . $raw);
|
||||
|
||||
return $encrypted;
|
||||
}
|
||||
|
||||
// ========================
|
||||
// Execute an SQL Statement
|
||||
// ========================
|
||||
|
||||
public function executeSQL($SQL = "") {
|
||||
|
||||
if (trim($SQL) == "") {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->connect()->query($SQL);
|
||||
}
|
||||
|
||||
// ======================
|
||||
// Format an XML document
|
||||
// ======================
|
||||
|
||||
public function formatXML($XML = "") {
|
||||
|
||||
if (!$XML) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($XML instanceof SimpleXMLElement) {
|
||||
$XML = $XML->asXML();
|
||||
}
|
||||
|
||||
$dom = new DOMDocument("1.0");
|
||||
$dom->preserveWhiteSpace = false;
|
||||
$dom->formatOutput = true;
|
||||
$dom->loadXML($XML);
|
||||
|
||||
return $dom->saveXML();
|
||||
}
|
||||
|
||||
// =====================================
|
||||
// Return an Application Settings Object
|
||||
// =====================================
|
||||
|
||||
public function getSettings() {
|
||||
|
||||
$settings = new SimpleXMLElement($this->getXML("settings"));
|
||||
|
||||
return $settings;
|
||||
}
|
||||
|
||||
// ==================================================================
|
||||
// Return Age in Years based on given Birthdate ("yyyy-mm-dd" format)
|
||||
// ==================================================================
|
||||
|
||||
public function getAge($birthdate = "", $date = "") {
|
||||
|
||||
$birthdate = filter_input(INPUT_POST, "birthdate", FILTER_UNSAFE_RAW) ?: $birthdate;
|
||||
$date = filter_input(INPUT_POST, "date", FILTER_UNSAFE_RAW) ?: $date;
|
||||
|
||||
$age = 0;
|
||||
|
||||
$date = (empty($date)) ? new Datetime() : new DateTime($date);
|
||||
$birthdate = (empty($birthdate)) ? new Datetime() : new DateTime($birthdate);
|
||||
|
||||
$age = $birthdate->diff($date)->format("%y");
|
||||
|
||||
if ($_SESSION[self::AJAX]) {
|
||||
echo json_encode($age);
|
||||
} else {
|
||||
return $age;
|
||||
}
|
||||
}
|
||||
|
||||
// =========================
|
||||
// Return a Constants Object
|
||||
// =========================
|
||||
|
||||
public function getConstants() {
|
||||
|
||||
$Constants = new SimpleXMLElement($this->getXML("constants"));
|
||||
|
||||
return $Constants;
|
||||
}
|
||||
|
||||
// ==================
|
||||
// Return a Recordset
|
||||
// ==================
|
||||
|
||||
public function getRecordset($SQL = "") {
|
||||
|
||||
if (empty($SQL)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$recordSet = $this->connect()->query($SQL);
|
||||
|
||||
return $recordSet;
|
||||
}
|
||||
|
||||
// =======================================
|
||||
// Return Table Data as a SimpleXMLElement
|
||||
// =======================================
|
||||
|
||||
public function getTable($table = "", $SQL = "") {
|
||||
|
||||
if (empty($table)) {
|
||||
return new SimpleXMLElement("<unknown/>");
|
||||
}
|
||||
|
||||
$SXE = new SimpleXMLElement("<{$table}/>");
|
||||
|
||||
$recordset = $this->getRecordset(empty($SQL) ? "select * from {$table}" : $SQL);
|
||||
|
||||
if ($recordset) {
|
||||
|
||||
while ($row = $recordset->fetch(PDO::FETCH_ASSOC)) {
|
||||
|
||||
$record = $SXE->addChild("record");
|
||||
|
||||
foreach ($row as $name => $value) {
|
||||
$record->$name = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $SXE;
|
||||
}
|
||||
|
||||
// =======================================
|
||||
// Return Table Data as a SimpleXMLElement
|
||||
// =======================================
|
||||
|
||||
public function getTableXML($table = "", $statement = "") {
|
||||
|
||||
if (empty($table)) {
|
||||
return new SimpleXMLElement("<unknown/>");
|
||||
}
|
||||
|
||||
$SXE = new SimpleXMLElement("<{$table}/>");
|
||||
|
||||
while ($row = $statement->fetch(PDO::FETCH_ASSOC)) {
|
||||
|
||||
$record = $SXE->addChild("record");
|
||||
|
||||
foreach ($row as $name => $value) {
|
||||
$record->$name = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $SXE;
|
||||
}
|
||||
|
||||
// =================================
|
||||
// Return the Time Elapsed since now
|
||||
// =================================
|
||||
|
||||
public function getTimeElapsed($timestamp = "") {
|
||||
|
||||
$now = new DateTime;
|
||||
$then = new DateTime($timestamp);
|
||||
$diff = (array) $now->diff($then);
|
||||
|
||||
$diff["w"] = floor($diff["d"] / 7);
|
||||
$diff["d"] -= $diff["w"] * 7;
|
||||
|
||||
$string = array(
|
||||
"y" => "year",
|
||||
"m" => "month",
|
||||
"w" => "week",
|
||||
"d" => "day",
|
||||
"h" => "hour",
|
||||
"i" => "minute",
|
||||
"s" => "second",
|
||||
);
|
||||
|
||||
foreach ($string as $k => & $v) {
|
||||
|
||||
if ($diff[$k]) {
|
||||
$v = $diff[$k] . " " . $v . ($diff[$k] > 1 ? "s" : "");
|
||||
} else {
|
||||
unset($string[$k]);
|
||||
}
|
||||
}
|
||||
|
||||
$string = array_slice($string, 0, 1);
|
||||
|
||||
return $string ? implode(", ", $string) . " ago" : "just now";
|
||||
}
|
||||
|
||||
// ===================
|
||||
// Return a Time Stamp
|
||||
// ===================
|
||||
|
||||
public function getTimestamp() {
|
||||
|
||||
return date("Y-m-d H:i:s");
|
||||
}
|
||||
|
||||
// ======================
|
||||
// Return an XML Document
|
||||
// ======================
|
||||
|
||||
public function getXML($document = "") {
|
||||
|
||||
if (trim($document) == "") {
|
||||
return "";
|
||||
}
|
||||
|
||||
$document = "xml/" . trim($document) . ".xml";
|
||||
$XML = (file_exists($document) ? file_get_contents($document) : "");
|
||||
|
||||
return $XML;
|
||||
}
|
||||
|
||||
// ========================
|
||||
// Return an XSL Stylesheet
|
||||
// ========================
|
||||
|
||||
public function getXSL($document = "") {
|
||||
|
||||
if (trim($document) == "") {
|
||||
return "";
|
||||
}
|
||||
|
||||
$document = "xsl/" . trim($document) . ".xsl";
|
||||
$XSL = (file_exists($document) ? file_get_contents($document) : "");
|
||||
|
||||
return $XSL;
|
||||
}
|
||||
|
||||
// =======================================
|
||||
// Return a Zip Code Detail Object (Array)
|
||||
// =======================================
|
||||
|
||||
public function getZipcode($zip_code = 0) {
|
||||
|
||||
$zip_code = filter_input(INPUT_POST, "zip_code", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$zip_code = (integer) substr((string) $zip_code, 0, 5);
|
||||
|
||||
$zipCodeDetail = null;
|
||||
|
||||
$SQL = "select *
|
||||
from zipcodes
|
||||
where zipcode_code = {$zip_code}";
|
||||
|
||||
$zipcodes = $this->getTable("zipcodes", $SQL);
|
||||
|
||||
if ($zipcodes->count() > 0) {
|
||||
|
||||
$zipCodeDetail["ZipCode"] = $zip_code;
|
||||
$zipCodeDetail["City"] = (string) $zipcodes->record->zipcode_city;
|
||||
$zipCodeDetail["State"] = (string) $zipcodes->record->zipcode_state;
|
||||
$zipCodeDetail["County"] = (string) $zipcodes->record->zipcode_county;
|
||||
$zipCodeDetail["Country"] = (string) $zipcodes->record->zipcode_country;
|
||||
}
|
||||
|
||||
if ($_SESSION[self::AJAX]) {
|
||||
echo json_encode($zipCodeDetail);
|
||||
} else {
|
||||
return $zipCodeDetail;
|
||||
}
|
||||
}
|
||||
|
||||
// ======================
|
||||
// Initialize the Session
|
||||
// ======================
|
||||
|
||||
public function initializeSession() {
|
||||
|
||||
$settings = $this->getSettings();
|
||||
|
||||
$_SESSION[self::ACTIVE_SESSION] = true;
|
||||
$_SESSION[self::THEME] = "light";
|
||||
$_SESSION[self::ENVIRONMENT] = (string) ($settings->Environment ?? "Production");
|
||||
$_SESSION[self::USER_AUTHENTICATED] = false;
|
||||
$_SESSION[self::USER_SERIAL] = 0;
|
||||
$_SESSION[self::USER_ID] = "";
|
||||
$_SESSION[self::USER_NAME] = "";
|
||||
$_SESSION[self::USER_CLIENT_NAME] = "";
|
||||
$_SESSION[self::USER_EMAIL] = "";
|
||||
$_SESSION[self::USER_ROLE] = "Guest";
|
||||
$_SESSION[self::REPORTS_GET] = "";
|
||||
$_SESSION[self::REPORTS_POST] = "";
|
||||
$_SESSION[self::AJAX] = false;
|
||||
}
|
||||
|
||||
// ============
|
||||
// Log an Error
|
||||
// ============
|
||||
|
||||
public function logError($error_message = "") {
|
||||
|
||||
(new Journal())->journalEntry($error_message);
|
||||
|
||||
$this->displayHome();
|
||||
|
||||
exit();
|
||||
}
|
||||
|
||||
// ==========================
|
||||
// Merge thisXML with thatXML
|
||||
// ==========================
|
||||
|
||||
public function mergeXML($thisXML = "", $thatXML = "") {
|
||||
|
||||
if ($thisXML instanceof SimpleXMLElement) {
|
||||
$thisXML = $thisXML->asXML();
|
||||
}
|
||||
|
||||
if ($thatXML instanceof SimpleXMLElement) {
|
||||
$thatXML = $thatXML->asXML();
|
||||
}
|
||||
|
||||
if (trim($thisXML) == "") {
|
||||
return $thatXML;
|
||||
}
|
||||
|
||||
if (trim($thatXML) == "") {
|
||||
return $thisXML;
|
||||
}
|
||||
|
||||
$thisDOM = new DOMDocument();
|
||||
$thisDOM->loadXML($thisXML);
|
||||
|
||||
$thatDOM = new DOMDocument();
|
||||
$thatDOM->loadXML($thatXML);
|
||||
|
||||
$xpath = new DOMXpath($thisDOM);
|
||||
$xpathQuery = $xpath->query("/*");
|
||||
|
||||
for ($i = 0; $i < $xpathQuery->length; $i++) {
|
||||
$thatDOM->documentElement->appendChild($thatDOM->importNode($xpathQuery->item($i), true));
|
||||
}
|
||||
|
||||
$thatSXE = simplexml_import_dom($thatDOM);
|
||||
|
||||
return $thatSXE->asXML();
|
||||
}
|
||||
|
||||
// ==============
|
||||
// Print a Report
|
||||
// ==============
|
||||
|
||||
public function print() {
|
||||
|
||||
$_SESSION[self::REPORTS_GET] = $_GET;
|
||||
$_SESSION[self::REPORTS_POST] = $_POST;
|
||||
|
||||
$report = filter_input(INPUT_POST, "report") ?: "";
|
||||
|
||||
(new $report())->print();
|
||||
}
|
||||
|
||||
// =================
|
||||
// Sanitize a string
|
||||
// =================
|
||||
|
||||
public function sanitizeString($string = "") {
|
||||
|
||||
return trim(preg_replace("/\s+/", " ", htmlspecialchars($string, ENT_NOQUOTES | ENT_HTML5)));
|
||||
}
|
||||
|
||||
// ========================
|
||||
// Toggle the current Theme
|
||||
// ========================
|
||||
|
||||
public function toggleTheme() {
|
||||
|
||||
$_SESSION[self::THEME] = (($_SESSION[self::THEME] ?? "light") === "dark") ? "light" : "dark";
|
||||
}
|
||||
|
||||
// ===============================
|
||||
// Validate a Date (local or AJAX)
|
||||
// ===============================
|
||||
|
||||
public function validateDate($date = "", $format = "Y-m-d") {
|
||||
|
||||
$date = filter_input(INPUT_POST, "date") ?: $date;
|
||||
|
||||
$datetime = DateTime::createFromFormat($format, $date);
|
||||
|
||||
$valid = $datetime && $datetime->format($format) === $date;
|
||||
|
||||
if ($_SESSION[self::AJAX]) {
|
||||
echo json_encode($valid);
|
||||
} else {
|
||||
return $valid;
|
||||
}
|
||||
}
|
||||
|
||||
// ========================
|
||||
// Generate Random Password
|
||||
// ========================
|
||||
|
||||
public function generateRandomPassword($length = 12) {
|
||||
|
||||
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()-_+=';
|
||||
$password = '';
|
||||
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
$index = rand(0, strlen($characters) - 1);
|
||||
$password .= $characters[$index];
|
||||
}
|
||||
|
||||
return $password;
|
||||
}
|
||||
|
||||
// ====================
|
||||
// User Change Password
|
||||
// ====================
|
||||
|
||||
public function userChangePassword() {
|
||||
|
||||
$user = (new Users())->getUserByUserName($_SESSION[self::USER_NAME]);
|
||||
|
||||
if ($user->record->user_change_password == 1) {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// ==============================
|
||||
// Alter Sting to Parahgraph Case
|
||||
// ==============================
|
||||
|
||||
public function toParagraphCase($text) {
|
||||
|
||||
$text = ucwords(strtolower($text));
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
// =======================
|
||||
// Format Raw Phone Number
|
||||
// =======================
|
||||
|
||||
public function formatPhoneNumber(string $phonenumber): string {
|
||||
|
||||
// Remove everything except digits
|
||||
$digits = preg_replace('/\D+/', '', $phonenumber);
|
||||
|
||||
// Handle leading country code (US)
|
||||
if (strlen($digits) === 11 && str_starts_with($digits, '1')) {
|
||||
$digits = substr($digits, 1);
|
||||
}
|
||||
|
||||
return substr($digits, 0, 3) . '-' .
|
||||
substr($digits, 3, 3) . '-' .
|
||||
substr($digits, 6, 4);
|
||||
}
|
||||
|
||||
// ==========================
|
||||
// Developer Testing Function
|
||||
// ==========================
|
||||
|
||||
public function testing() {
|
||||
|
||||
$SQL = "select count(*) as notify
|
||||
from view_exportjobs
|
||||
where view_exportjobs.exportjob_creator = 19
|
||||
and view_exportjobs.exportjob_status = 'complete'
|
||||
and view_exportjobs.exportjob_notified = 0";
|
||||
|
||||
$exportjobs = $this->getTable("exportjobs", $SQL);
|
||||
|
||||
$this->debug($exportjobs->asXML());
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,461 @@
|
||||
<?php
|
||||
|
||||
class Budgets 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;
|
||||
}
|
||||
|
||||
// ============
|
||||
// View Budgets
|
||||
// ============
|
||||
|
||||
public function viewBudgets() {
|
||||
|
||||
$budgets = $this->getBudgetsPage();
|
||||
$popovers = (new Popovers())->getPopovers();
|
||||
|
||||
$XML = $this->mergeXML($budgets, "<XML/>");
|
||||
$XML = $this->mergeXML($popovers, $XML);
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("viewBudgets"));
|
||||
|
||||
$this->displayContent($content);
|
||||
}
|
||||
|
||||
// ==================
|
||||
// View Budget Months
|
||||
// ==================
|
||||
|
||||
public function viewBudgetMonths() {
|
||||
|
||||
$budget_serial = filter_input(INPUT_POST, "budget_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$budgetmonths = $this->getBudgetMonths($budget_serial);
|
||||
|
||||
$content = $this->applyXSL($budgetmonths, $this->getXSL("viewBudgetMonths"));
|
||||
|
||||
$this->displayContent($content);
|
||||
}
|
||||
|
||||
// ==============
|
||||
// Budget Details
|
||||
// ==============
|
||||
|
||||
public function budgetDetails() {
|
||||
|
||||
$budgetmonth_serial = filter_input(INPUT_POST, "budgetmonth_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$budgetdetails = $this->getBudgetDetails($budgetmonth_serial);
|
||||
|
||||
$content = $this->applyXSL($budgetdetails, $this->getXSL("budgetDetails"));
|
||||
|
||||
$this->displayContent($content);
|
||||
}
|
||||
|
||||
// ==========
|
||||
// Add Budget
|
||||
// ==========
|
||||
|
||||
public function addBudget() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$content = $this->applyXSL("", $this->getXSL("addBudget"));
|
||||
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "add":
|
||||
|
||||
$budget_year = filter_input(INPUT_POST, "budget_year", FILTER_SANITIZE_NUMBER_INT);
|
||||
$budget_year = ($budget_year !== null && $budget_year !== false && $budget_year !== '') ? (int) $budget_year : null;
|
||||
|
||||
$connection = $this->connect();
|
||||
|
||||
try {
|
||||
$connection->beginTransaction();
|
||||
|
||||
// -------------------
|
||||
// Insert into budgets
|
||||
// -------------------
|
||||
|
||||
$sql = "INSERT INTO budgets
|
||||
( budget_year,
|
||||
budget_creator,
|
||||
budget_created )
|
||||
VALUES
|
||||
( :budget_year,
|
||||
:budget_creator,
|
||||
:budget_created )";
|
||||
|
||||
$statement = $connection->prepare($sql);
|
||||
|
||||
$statement->bindValue(':budget_year', $budget_year, PDO::PARAM_INT);
|
||||
$statement->bindValue(':budget_creator', $this->current_user_name);
|
||||
$statement->bindValue(':budget_created', $this->getTimestamp());
|
||||
$statement->execute();
|
||||
|
||||
$budget_id = (int) $connection->lastInsertId();
|
||||
|
||||
// -------------------------
|
||||
// Insert 12 months records
|
||||
// -------------------------
|
||||
|
||||
$monthlist = (new Dropdowns())->getDropdownsByDropdownType(1);
|
||||
|
||||
$sql = "INSERT INTO budgetmonths
|
||||
( budgetmonth_budget,
|
||||
budgetmonth_month,
|
||||
budgetmonth_creator,
|
||||
budgetmonth_created )
|
||||
VALUES
|
||||
( :budgetmonth_budget,
|
||||
:budgetmonth_month,
|
||||
:budgetmonth_creator,
|
||||
:budgetmonth_created )";
|
||||
|
||||
$statement = $connection->prepare($sql);
|
||||
|
||||
foreach ($monthlist as $month) {
|
||||
$statement->bindValue(':budgetmonth_budget', $budget_id, PDO::PARAM_INT);
|
||||
$statement->bindValue(':budgetmonth_month', (int) $month->dropdown_serial, PDO::PARAM_INT);
|
||||
$statement->bindValue(':budgetmonth_creator', $this->current_user_name);
|
||||
$statement->bindValue(':budgetmonth_created', $this->getTimestamp());
|
||||
$statement->execute();
|
||||
}
|
||||
|
||||
$connection->commit();
|
||||
} catch (Throwable $e) {
|
||||
if ($connection->inTransaction()) {
|
||||
$connection->rollBack();
|
||||
}
|
||||
throw $e; // or handle/log and return a friendly error
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// =============
|
||||
// Delete Budget
|
||||
// =============
|
||||
|
||||
public function deleteBudget() {
|
||||
|
||||
$budget_serial = filter_input(INPUT_POST, "budget_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$budget = $this->getBudget($budget_serial);
|
||||
|
||||
if ($budget->count() == 0) {
|
||||
$this->logError("Invalid Budget ({$budget_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$SQL = "delete from budgets
|
||||
where budget_serial = {$budget_serial}";
|
||||
|
||||
$this->executeSQL($SQL);
|
||||
}
|
||||
|
||||
// ============================
|
||||
// Determine if a Budget exists
|
||||
// ============================
|
||||
|
||||
public function budgetExists() {
|
||||
|
||||
$budget_serial = filter_input(INPUT_POST, "budget_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$budget_year = filter_input(INPUT_POST, "budget_year") ?: "";
|
||||
|
||||
$SQL = "select budget_serial
|
||||
from view_budgets
|
||||
where budget_serial != :budget_serial
|
||||
and lower(budget_year) = :budget_year";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":budget_serial", $budget_serial);
|
||||
$statement->bindValue(":budget_year", strtolower($budget_year));
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$recordset = $statement->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$exists = (count($recordset) > 0) ? true : false;
|
||||
|
||||
echo json_encode($exists);
|
||||
}
|
||||
|
||||
// ======================================
|
||||
// Determine if a Budget is Active (AJAX)
|
||||
// ======================================
|
||||
|
||||
public function budgetActive() {
|
||||
|
||||
$budget_serial = filter_input(INPUT_POST, "budget_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$active = false;
|
||||
|
||||
$SQL = "select workorder_budget
|
||||
from workorders
|
||||
where workorder_budget = {$budget_serial}
|
||||
limit 1";
|
||||
|
||||
$workorders = $this->getTable("workorders", $SQL);
|
||||
|
||||
$active = ($workorders->count() > 0) ? true : false;
|
||||
|
||||
echo json_encode($active);
|
||||
}
|
||||
|
||||
// =============
|
||||
// Edit a Budget
|
||||
// =============
|
||||
|
||||
public function editBudget() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$budget_serial = filter_input(INPUT_POST, "budget_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$budget = $this->getBudget($budget_serial);
|
||||
|
||||
if ($budget->count() == 0) {
|
||||
$this->logError("Invalid Budget ({$budget_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$XML = $this->mergeXML($budget, "<XML/>");
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("editBudget"));
|
||||
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "update":
|
||||
|
||||
$budget_serial = filter_input(INPUT_POST, "budget_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$budget_name = filter_input(INPUT_POST, "budget_name") ?: "";
|
||||
$budget_classes = filter_input(INPUT_POST, "budget_classes") ?: "";
|
||||
$budget_active = filter_input(INPUT_POST, "budget_active", FILTER_VALIDATE_BOOLEAN) ?: false;
|
||||
$budget_default = filter_input(INPUT_POST, "budget_default", FILTER_VALIDATE_BOOLEAN) ?: false;
|
||||
|
||||
// Verify the Budget
|
||||
|
||||
$budget = $this->getBudget($budget_serial);
|
||||
|
||||
if ($budget->count() == 0) {
|
||||
$this->logError("Invalid Budget ({$budget_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$SQL = "update budgets
|
||||
set budget_name = :budget_name,
|
||||
budget_classes = :budget_classes,
|
||||
budget_active = :budget_active,
|
||||
budget_default = :budget_default,
|
||||
budget_changer = :budget_changer,
|
||||
budget_changed = :budget_changed
|
||||
where budget_serial = :budget_serial";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":budget_serial", $budget_serial);
|
||||
$statement->bindValue(":budget_name", $budget_name);
|
||||
$statement->bindValue(":budget_classes", $budget_classes);
|
||||
$statement->bindValue(":budget_active", $budget_active, PDO::PARAM_BOOL);
|
||||
$statement->bindValue(":budget_default", $budget_default, PDO::PARAM_BOOL);
|
||||
$statement->bindValue(":budget_changer", $this->current_user_name);
|
||||
$statement->bindValue(":budget_changed", $this->getTimestamp());
|
||||
|
||||
$statement->execute();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// ================================
|
||||
// Return an Active Budgets Object
|
||||
// ================================
|
||||
|
||||
public function getActiveBudgets() {
|
||||
|
||||
$SQL = "select view_budgets.*
|
||||
from view_budgets
|
||||
where budget_active is true";
|
||||
|
||||
return $this->getTable("budgets", $SQL);
|
||||
}
|
||||
|
||||
// -------------------------
|
||||
// Return the Default Budget
|
||||
// -------------------------
|
||||
|
||||
public function getDefaultBudget() {
|
||||
|
||||
$SQL = "select budget_serial
|
||||
from view_budgets
|
||||
where budget_default is true";
|
||||
|
||||
return $this->getTable("budgets", $SQL);
|
||||
}
|
||||
|
||||
// =======================
|
||||
// Return an Budget Object
|
||||
// =======================
|
||||
|
||||
public function getBudget($budget_serial = 0) {
|
||||
|
||||
$SQL = "select view_budgets.*
|
||||
from view_budgets
|
||||
where budget_serial = {$budget_serial}";
|
||||
|
||||
return $this->getTable("budgets", $SQL);
|
||||
}
|
||||
|
||||
// =======================
|
||||
// Return an Budget Object
|
||||
// =======================
|
||||
|
||||
public function getBudgetMonths($budget_serial = 0) {
|
||||
|
||||
$SQL = "select view_budgetmonths.*
|
||||
from view_budgetmonths
|
||||
where view_budgetmonths.budgetmonth_budget = {$budget_serial}";
|
||||
|
||||
return $this->getTable("budgetmonths", $SQL);
|
||||
}
|
||||
|
||||
// ===========================
|
||||
// Return a Budgets Object
|
||||
// ===========================
|
||||
|
||||
public function getBudgets() {
|
||||
|
||||
$SQL = "select view_budgets.*
|
||||
from view_budgets";
|
||||
|
||||
return $this->getTable("budgets", $SQL);
|
||||
}
|
||||
|
||||
// ============================
|
||||
// Return a Budgets Page Object
|
||||
// ============================
|
||||
|
||||
public function getBudgetsPage() {
|
||||
|
||||
// Find Criteria
|
||||
|
||||
$find_budget = filter_input(INPUT_POST, "find_budget") ?: "";
|
||||
$find_budget = $this->sanitizeString($find_budget);
|
||||
|
||||
$find_words = implode("|", explode(" ", $find_budget));
|
||||
|
||||
// Record Count
|
||||
|
||||
$connection = $this->connect();
|
||||
|
||||
$SQL = "select count(*) as count
|
||||
from view_budgets
|
||||
where budget_year regexp :budget_year";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":budget_year", $find_words);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$recordset = $statement->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$count = (count($recordset) > 0) ? (integer) $recordset["count"] : (integer) 0;
|
||||
|
||||
// Pagination
|
||||
|
||||
$pagination = filter_input(INPUT_POST, "pagination") ?: "";
|
||||
|
||||
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 = ($count / $this->pagination_size);
|
||||
break;
|
||||
}
|
||||
|
||||
$offset = (($this->pagination_page * $this->pagination_size) - $this->pagination_size);
|
||||
$start = ($offset + 1);
|
||||
$end = min($count, (($start + $this->pagination_size) - 1));
|
||||
|
||||
// Data
|
||||
|
||||
$SQL = "select view_budgets.*
|
||||
from view_budgets
|
||||
where budget_year regexp :budget_year
|
||||
order by budget_year
|
||||
limit {$this->pagination_size}
|
||||
offset {$offset}";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":budget_year", $find_words);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$budgets = $this->getTableXML("budgets", $statement);
|
||||
|
||||
// Insert Pagination Attributes
|
||||
|
||||
$budgets->addAttribute("count", $count);
|
||||
$budgets->addAttribute("start", $start);
|
||||
$budgets->addAttribute("end", $end);
|
||||
$budgets->addAttribute("page", $this->pagination_page);
|
||||
|
||||
$_SESSION[self::PAGINATION_PAGE] = $this->pagination_page;
|
||||
|
||||
return $budgets;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,303 @@
|
||||
<?php
|
||||
|
||||
class Cities 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;
|
||||
}
|
||||
|
||||
// ============
|
||||
// Setup Cities
|
||||
// ============
|
||||
|
||||
public function setupCities() {
|
||||
|
||||
$cities = $this->getCitiesPage();
|
||||
$popovers = (new Popovers())->getPopovers();
|
||||
|
||||
$XML = $this->mergeXML($cities, "<XML/>");
|
||||
$XML = $this->mergeXML($popovers, $XML);
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("setupCities"));
|
||||
|
||||
$this->displayContent($content);
|
||||
}
|
||||
|
||||
// ========
|
||||
// Add City
|
||||
// ========
|
||||
|
||||
public function addCity() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$constants = $this->getConstants();
|
||||
|
||||
$content = $this->applyXSL($constants, $this->getXSL("addCity"));
|
||||
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "add":
|
||||
|
||||
$city_name = filter_input(INPUT_POST, "city_name") ?: "";
|
||||
$city_state = filter_input(INPUT_POST, "city_state") ?: "";
|
||||
|
||||
$SQL = "insert into cities
|
||||
|
||||
( city_name,
|
||||
city_state,
|
||||
city_creator,
|
||||
city_created )
|
||||
|
||||
VALUES ( :city_name,
|
||||
:city_state,
|
||||
:city_creator,
|
||||
:city_created )";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":city_name", $city_name);
|
||||
$statement->bindValue(":city_state", $city_state);
|
||||
$statement->bindValue(":city_creator", $this->current_user_name);
|
||||
$statement->bindValue(":city_created", $this->getTimestamp());
|
||||
|
||||
$statement->execute();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// ===========
|
||||
// Edit a City
|
||||
// ===========
|
||||
|
||||
public function editCity() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$city_serial = filter_input(INPUT_POST, "city_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$city = $this->getCity($city_serial);
|
||||
|
||||
if ($city->count() == 0) {
|
||||
$this->logError("Invalid City ({$city_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$constants = $this->getConstants();
|
||||
|
||||
$XML = $this->mergeXML($city, "<XML/>");
|
||||
$XML = $this->mergeXML($constants, $XML);
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("editCity"));
|
||||
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "update":
|
||||
|
||||
$city_serial = filter_input(INPUT_POST, "city_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$city_name = filter_input(INPUT_POST, "city_name") ?: "";
|
||||
$city_state = filter_input(INPUT_POST, "city_state") ?: "";
|
||||
|
||||
// Verify the Cities
|
||||
|
||||
$city = $this->getCity($city_serial);
|
||||
|
||||
if ($city->count() == 0) {
|
||||
$this->logError("Invalid Cities ({$city_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$SQL = "update cities
|
||||
set city_name = :city_name,
|
||||
city_state = :city_state,
|
||||
city_changer = :city_changer,
|
||||
city_changed = :city_changed
|
||||
where city_serial = :city_serial";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":city_serial", $city_serial);
|
||||
$statement->bindValue(":city_state", $city_state);
|
||||
$statement->bindValue(":city_name", $city_name);
|
||||
$statement->bindValue(":city_changer", $this->current_user_name);
|
||||
$statement->bindValue(":city_changed", $this->getTimestamp());
|
||||
|
||||
$statement->execute();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// ===========
|
||||
// Delete City
|
||||
// ===========
|
||||
|
||||
public function deleteCity() {
|
||||
|
||||
$city_serial = filter_input(INPUT_POST, "city_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$city = $this->getCity($city_serial);
|
||||
|
||||
if ($city->count() == 0) {
|
||||
$this->logError("Invalid City ({$city_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$SQL = "delete from cities where city_serial = {$city_serial}";
|
||||
|
||||
$this->executeSQL($SQL);
|
||||
}
|
||||
|
||||
// =======================
|
||||
// Return an Cities Object
|
||||
// =======================
|
||||
|
||||
public function getCity($city_serial = 0) {
|
||||
|
||||
$SQL = "select view_cities.*
|
||||
from view_cities
|
||||
where city_serial = {$city_serial}";
|
||||
|
||||
return $this->getTable("cities", $SQL);
|
||||
}
|
||||
|
||||
// ======================
|
||||
// Return a Cities Object
|
||||
// ======================
|
||||
|
||||
public function getCities() {
|
||||
|
||||
$SQL = "select view_cities.*
|
||||
from view_cities
|
||||
order by view_cities.city_name";
|
||||
|
||||
return $this->getTable("cities", $SQL);
|
||||
}
|
||||
|
||||
// ===========================
|
||||
// Return a Cities Page Object
|
||||
// ===========================
|
||||
|
||||
public function getCitiesPage() {
|
||||
|
||||
// Find Criteria
|
||||
|
||||
$find_city = filter_input(INPUT_POST, "find_city") ?: "";
|
||||
$find_city = $this->sanitizeString($find_city);
|
||||
|
||||
$find_words = implode("|", explode(" ", $find_city));
|
||||
|
||||
// Record Count
|
||||
|
||||
$connection = $this->connect();
|
||||
|
||||
$SQL = "select count(*) as count
|
||||
from view_cities
|
||||
where city_name regexp :city_name
|
||||
or city_state regexp :city_state";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":city_name", $find_words);
|
||||
$statement->bindValue(":city_state", $find_words);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$recordset = $statement->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$count = (count($recordset) > 0) ? (integer) $recordset["count"] : (integer) 0;
|
||||
|
||||
// Pagination
|
||||
|
||||
$pagination = filter_input(INPUT_POST, "pagination") ?: "";
|
||||
|
||||
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 = ($count / $this->pagination_size);
|
||||
break;
|
||||
}
|
||||
|
||||
$offset = (($this->pagination_page * $this->pagination_size) - $this->pagination_size);
|
||||
$start = ($offset + 1);
|
||||
$end = min($count, (($start + $this->pagination_size) - 1));
|
||||
|
||||
// Data
|
||||
|
||||
$SQL = "select view_cities.*
|
||||
from view_cities
|
||||
where city_name regexp :city_name
|
||||
or city_state regexp :city_state
|
||||
order by city_code
|
||||
limit {$this->pagination_size}
|
||||
offset {$offset}";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":city_name", $find_words);
|
||||
$statement->bindValue(":city_state", $find_words);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$cities = $this->getTableXML("cities", $statement);
|
||||
|
||||
// Insert Pagination Attributes
|
||||
|
||||
$cities->addAttribute("count", $count);
|
||||
$cities->addAttribute("start", $start);
|
||||
$cities->addAttribute("end", $end);
|
||||
$cities->addAttribute("page", $this->pagination_page);
|
||||
|
||||
$_SESSION[self::PAGINATION_PAGE] = $this->pagination_page;
|
||||
|
||||
return $cities;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,332 @@
|
||||
<?php
|
||||
|
||||
class CountyCodes 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;
|
||||
}
|
||||
|
||||
// ==================
|
||||
// Setup County Codes
|
||||
// ==================
|
||||
|
||||
public function setupCountyCodes() {
|
||||
|
||||
$countycodes = $this->getCountyCodesPage();
|
||||
$popovers = (new Popovers())->getPopovers();
|
||||
|
||||
$XML = $this->mergeXML($countycodes, "<XML/>");
|
||||
$XML = $this->mergeXML($popovers, $XML);
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("setupCountyCodes"));
|
||||
|
||||
$this->displayContent($content);
|
||||
}
|
||||
|
||||
// ================
|
||||
// Add County Code
|
||||
// ================
|
||||
|
||||
public function addCountyCode() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$constants = $this->getConstants();
|
||||
|
||||
$content = $this->applyXSL($constants, $this->getXSL("addCountyCode"));
|
||||
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "add":
|
||||
|
||||
$countycode_code = filter_input(INPUT_POST, "countycode_code") ?: "";
|
||||
$countycode_name = filter_input(INPUT_POST, "countycode_name") ?: "";
|
||||
$countycode_state = filter_input(INPUT_POST, "countycode_state") ?: "";
|
||||
|
||||
$SQL = "insert into countycodes
|
||||
|
||||
( countycode_code,
|
||||
countycode_name,
|
||||
countycode_state,
|
||||
countycode_active,
|
||||
countycode_creator,
|
||||
countycode_created )
|
||||
|
||||
VALUES ( :countycode_code,
|
||||
:countycode_name,
|
||||
:countycode_state,
|
||||
:countycode_active,
|
||||
:countycode_creator,
|
||||
:countycode_created )";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":countycode_code", strtoupper($countycode_code));
|
||||
$statement->bindValue(":countycode_name", $countycode_name);
|
||||
$statement->bindValue(":countycode_state", $countycode_state);
|
||||
$statement->bindValue(":countycode_active", true, PDO::PARAM_BOOL);
|
||||
$statement->bindValue(":countycode_creator", $this->current_user_name);
|
||||
$statement->bindValue(":countycode_created", $this->getTimestamp());
|
||||
|
||||
$statement->execute();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// ===================
|
||||
// Edit a County Code
|
||||
// ===================
|
||||
|
||||
public function editCountyCode() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$countycode_serial = filter_input(INPUT_POST, "countycode_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$countycode = $this->getCountyCode($countycode_serial);
|
||||
|
||||
if ($countycode->count() == 0) {
|
||||
$this->logError("Invalid County Code ({$countycode_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$constants = $this->getConstants();
|
||||
|
||||
$XML = $this->mergeXML($countycode, "<XML/>");
|
||||
$XML = $this->mergeXML($constants, $XML);
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("editCountyCode"));
|
||||
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "update":
|
||||
|
||||
$countycode_serial = filter_input(INPUT_POST, "countycode_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$countycode_code = filter_input(INPUT_POST, "countycode_code") ?: "";
|
||||
$countycode_name = filter_input(INPUT_POST, "countycode_name") ?: "";
|
||||
$countycode_state = filter_input(INPUT_POST, "countycode_state") ?: "";
|
||||
$countycode_active = filter_input(INPUT_POST, "countycode_active", FILTER_VALIDATE_BOOLEAN) ?: false;
|
||||
|
||||
// Verify the CountyCodes
|
||||
|
||||
$countycode = $this->getCountyCode($countycode_serial);
|
||||
|
||||
if ($countycode->count() == 0) {
|
||||
$this->logError("Invalid CountyCodes ({$countycode_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$SQL = "update countycodes
|
||||
set countycode_code = :countycode_code,
|
||||
countycode_name = :countycode_name,
|
||||
countycode_state = :countycode_state,
|
||||
countycode_active = :countycode_active,
|
||||
countycode_changer = :countycode_changer,
|
||||
countycode_changed = :countycode_changed
|
||||
where countycode_serial = :countycode_serial";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":countycode_serial", $countycode_serial);
|
||||
$statement->bindValue(":countycode_code", strtoupper($countycode_code));
|
||||
$statement->bindValue(":countycode_state", $countycode_state);
|
||||
$statement->bindValue(":countycode_name", $countycode_name);
|
||||
$statement->bindValue(":countycode_active", $countycode_active, PDO::PARAM_BOOL);
|
||||
$statement->bindValue(":countycode_changer", $this->current_user_name);
|
||||
$statement->bindValue(":countycode_changed", $this->getTimestamp());
|
||||
|
||||
$statement->execute();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// ===================
|
||||
// Delete County Code
|
||||
// ===================
|
||||
|
||||
public function deleteCountyCode() {
|
||||
|
||||
$countycode_serial = filter_input(INPUT_POST, "countycode_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$countycode = $this->getCountyCode($countycode_serial);
|
||||
|
||||
if ($countycode->count() == 0) {
|
||||
$this->logError("Invalid County Code ({$countycode_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$SQL = "delete from countycodes where countycode_serial = {$countycode_serial}";
|
||||
|
||||
$this->executeSQL($SQL);
|
||||
}
|
||||
|
||||
// =====================================
|
||||
// Return an Active County Codes Object
|
||||
// =====================================
|
||||
|
||||
public function getActiveCountyCodes() {
|
||||
|
||||
$SQL = "select view_countycodes.*
|
||||
from view_countycodes
|
||||
where countycode_active is true";
|
||||
|
||||
return $this->getTable("countycodes", $SQL);
|
||||
}
|
||||
|
||||
// ==============================
|
||||
// Return an County Codes Object
|
||||
// ==============================
|
||||
|
||||
public function getCountyCode($countycode_serial = 0) {
|
||||
|
||||
$SQL = "select view_countycodes.*
|
||||
from view_countycodes
|
||||
where countycode_serial = {$countycode_serial}";
|
||||
|
||||
return $this->getTable("countycodes", $SQL);
|
||||
}
|
||||
|
||||
// =============================
|
||||
// Return a County Codes Object
|
||||
// =============================
|
||||
|
||||
public function getCountyCodes() {
|
||||
|
||||
$SQL = "select view_countycodes.*
|
||||
from view_countycodes";
|
||||
|
||||
return $this->getTable("countycodes", $SQL);
|
||||
}
|
||||
|
||||
// ==================================
|
||||
// Return a County Codes Page Object
|
||||
// ==================================
|
||||
|
||||
public function getCountyCodesPage() {
|
||||
|
||||
// Find Criteria
|
||||
|
||||
$find_countycode = filter_input(INPUT_POST, "find_countycode") ?: "";
|
||||
$find_countycode = $this->sanitizeString($find_countycode);
|
||||
|
||||
$find_words = implode("|", explode(" ", $find_countycode));
|
||||
|
||||
// Record Count
|
||||
|
||||
$connection = $this->connect();
|
||||
|
||||
$SQL = "select count(*) as count
|
||||
from view_countycodes
|
||||
where countycode_code regexp :countycode_code
|
||||
or countycode_name regexp :countycode_name
|
||||
or countycode_state regexp :countycode_state";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":countycode_code", $find_words);
|
||||
$statement->bindValue(":countycode_name", $find_words);
|
||||
$statement->bindValue(":countycode_state", $find_words);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$recordset = $statement->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$count = (count($recordset) > 0) ? (integer) $recordset["count"] : (integer) 0;
|
||||
|
||||
// Pagination
|
||||
|
||||
$pagination = filter_input(INPUT_POST, "pagination") ?: "";
|
||||
|
||||
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 = ($count / $this->pagination_size);
|
||||
break;
|
||||
}
|
||||
|
||||
$offset = (($this->pagination_page * $this->pagination_size) - $this->pagination_size);
|
||||
$start = ($offset + 1);
|
||||
$end = min($count, (($start + $this->pagination_size) - 1));
|
||||
|
||||
// Data
|
||||
|
||||
$SQL = "select view_countycodes.*
|
||||
from view_countycodes
|
||||
where countycode_code regexp :countycode_code
|
||||
or countycode_name regexp :countycode_name
|
||||
or countycode_state regexp :countycode_state
|
||||
order by countycode_code
|
||||
limit {$this->pagination_size}
|
||||
offset {$offset}";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":countycode_code", $find_words);
|
||||
$statement->bindValue(":countycode_name", $find_words);
|
||||
$statement->bindValue(":countycode_state", $find_words);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$countycodes = $this->getTableXML("countycodes", $statement);
|
||||
|
||||
// Insert Pagination Attributes
|
||||
|
||||
$countycodes->addAttribute("count", $count);
|
||||
$countycodes->addAttribute("start", $start);
|
||||
$countycodes->addAttribute("end", $end);
|
||||
$countycodes->addAttribute("page", $this->pagination_page);
|
||||
|
||||
$_SESSION[self::PAGINATION_PAGE] = $this->pagination_page;
|
||||
|
||||
return $countycodes;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,746 @@
|
||||
<?php
|
||||
|
||||
// ===============
|
||||
// Dropdowns Class
|
||||
// ===============
|
||||
|
||||
class Dropdowns extends Base {
|
||||
|
||||
// Variables.
|
||||
|
||||
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_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;
|
||||
}
|
||||
|
||||
// ============
|
||||
// Add Dropdown
|
||||
// ============
|
||||
|
||||
public function addDropdown() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$dropdowntype_serial = filter_input(INPUT_POST, "dropdowntype_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$dropdowntype = $this->getDropdowntype($dropdowntype_serial);
|
||||
|
||||
if ($dropdowntype->count() == 0) {
|
||||
$this->logError("Invalid Dropdowntype ({$dropdowntype_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$XML = $this->mergeXML($dropdowntype, "<XML/>");
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("./system/addDropdown"));
|
||||
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "add":
|
||||
|
||||
$dropdowntype_serial = filter_input(INPUT_POST, "dropdowntype_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$dropdown_value = filter_input(INPUT_POST, "dropdown_value") ?: "";
|
||||
|
||||
$SQL = "insert into dropdowns
|
||||
|
||||
( dropdown_dropdowntype,
|
||||
dropdown_value,
|
||||
dropdown_creator,
|
||||
dropdown_created )
|
||||
|
||||
VALUES ( :dropdown_dropdowntype,
|
||||
:dropdown_value,
|
||||
:dropdown_creator,
|
||||
:dropdown_created )";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":dropdown_dropdowntype", $dropdowntype_serial);
|
||||
$statement->bindValue(":dropdown_value", $dropdown_value);
|
||||
$statement->bindValue(":dropdown_creator", $this->current_user_name);
|
||||
$statement->bindValue(":dropdown_created", $this->getTimestamp());
|
||||
|
||||
$statement->execute();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// ================
|
||||
// Add Dropdowntype
|
||||
// ================
|
||||
|
||||
public function addDropdowntype() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$content = $this->applyXSL("", $this->getXSL("./system/addDropdowntype"));
|
||||
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "add":
|
||||
|
||||
$dropdowntype_name = filter_input(INPUT_POST, "dropdowntype_name") ?: "";
|
||||
$dropdowntype_title = filter_input(INPUT_POST, "dropdowntype_title") ?: "";
|
||||
$dropdowntype_table = filter_input(INPUT_POST, "dropdowntype_table") ?: "";
|
||||
$dropdowntype_column = filter_input(INPUT_POST, "dropdowntype_column") ?: "";
|
||||
|
||||
$SQL = "insert into dropdowntypes
|
||||
|
||||
( dropdowntype_name,
|
||||
dropdowntype_title,
|
||||
dropdowntype_table,
|
||||
dropdowntype_column,
|
||||
dropdowntype_creator,
|
||||
dropdowntype_created )
|
||||
|
||||
VALUES ( :dropdowntype_name,
|
||||
:dropdowntype_title,
|
||||
:dropdowntype_table,
|
||||
:dropdowntype_column,
|
||||
:dropdowntype_creator,
|
||||
:dropdowntype_created )";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":dropdowntype_name", $dropdowntype_name);
|
||||
$statement->bindValue(":dropdowntype_title", $dropdowntype_title);
|
||||
$statement->bindValue(":dropdowntype_table", $dropdowntype_table);
|
||||
$statement->bindValue(":dropdowntype_column", $dropdowntype_column);
|
||||
$statement->bindValue(":dropdowntype_creator", $this->current_user_name);
|
||||
$statement->bindValue(":dropdowntype_created", $this->getTimestamp());
|
||||
|
||||
$statement->execute();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// ===============
|
||||
// Delete Dropdown
|
||||
// ===============
|
||||
|
||||
public function deleteDropdown() {
|
||||
|
||||
$dropdown_serial = filter_input(INPUT_POST, "dropdown_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$dropdown = $this->getDropdown($dropdown_serial);
|
||||
|
||||
if ($dropdown->count() == 0) {
|
||||
$this->logError("Invalid Dropdown ({$dropdown_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$SQL = "delete from dropdowns
|
||||
where dropdown_serial = {$dropdown_serial}";
|
||||
|
||||
$this->executeSQL($SQL);
|
||||
}
|
||||
|
||||
// ===================
|
||||
// Delete Dropdowntype
|
||||
// ===================
|
||||
|
||||
public function deleteDropdowntype() {
|
||||
|
||||
$dropdowntype_serial = filter_input(INPUT_POST, "dropdowntype_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$dropdowntype = $this->getDropdowntype($dropdowntype_serial);
|
||||
|
||||
if ($dropdowntype->count() == 0) {
|
||||
$this->logError("Invalid Dropdowntype ({$dropdowntype_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$SQL = "delete from dropdowntypes
|
||||
where dropdowntype_serial = {$dropdowntype_serial}";
|
||||
|
||||
$this->executeSQL($SQL);
|
||||
}
|
||||
|
||||
// ==============================
|
||||
// Determine if a Dropdown exists
|
||||
// ==============================
|
||||
|
||||
public function dropdownExists() {
|
||||
|
||||
$dropdowntype_serial = filter_input(INPUT_POST, "dropdowntype_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$dropdown_serial = filter_input(INPUT_POST, "dropdown_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$dropdown_value = filter_input(INPUT_POST, "dropdown_value") ?: "";
|
||||
|
||||
$dropdown_value = strtolower($dropdown_value);
|
||||
|
||||
$SQL = "select dropdown_serial
|
||||
from view_dropdowns
|
||||
where dropdown_serial != :dropdown_serial
|
||||
and dropdown_dropdowntype = :dropdown_dropdowntype
|
||||
and lower(dropdown_value) = :dropdown_value";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":dropdown_serial", $dropdown_serial);
|
||||
$statement->bindValue(":dropdown_dropdowntype", $dropdowntype_serial);
|
||||
$statement->bindValue(":dropdown_value", $dropdown_value);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$recordset = $statement->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$exists = (count($recordset) > 0) ? true : false;
|
||||
|
||||
echo json_encode($exists);
|
||||
}
|
||||
|
||||
// ==================================
|
||||
// Determine if a Dropdowntype exists
|
||||
// ==================================
|
||||
|
||||
public function dropdowntypeExists() {
|
||||
|
||||
$dropdowntype_serial = filter_input(INPUT_POST, "dropdowntype_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$dropdowntype_name = filter_input(INPUT_POST, "dropdowntype_name") ?: "";
|
||||
|
||||
$dropdowntype_name = strtolower($dropdowntype_name);
|
||||
|
||||
$SQL = "select dropdowntype_serial
|
||||
from view_dropdowntypes
|
||||
where dropdowntype_serial != :dropdowntype_serial
|
||||
and lower(dropdowntype_name) = :dropdowntype_name";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":dropdowntype_serial", $dropdowntype_serial);
|
||||
$statement->bindValue(":dropdowntype_name", $dropdowntype_name);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$recordset = $statement->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$exists = (count($recordset) > 0) ? true : false;
|
||||
|
||||
echo json_encode($exists);
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// Determine if a Dropdowntype Title exists
|
||||
// ========================================
|
||||
|
||||
public function dropdowntypetitleExists() {
|
||||
|
||||
$dropdowntype_serial = filter_input(INPUT_POST, "dropdowntype_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$dropdowntype_title = filter_input(INPUT_POST, "dropdowntype_title") ?: "";
|
||||
|
||||
$dropdowntype_title = strtolower($dropdowntype_title);
|
||||
|
||||
$SQL = "select dropdowntype_serial
|
||||
from view_dropdowntypes
|
||||
where dropdowntype_serial != :dropdowntype_serial
|
||||
and lower(dropdowntype_title) = :dropdowntype_title";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":dropdowntype_serial", $dropdowntype_serial);
|
||||
$statement->bindValue(":dropdowntype_title", $dropdowntype_title);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$recordset = $statement->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$exists = (count($recordset) > 0) ? true : false;
|
||||
|
||||
echo json_encode($exists);
|
||||
}
|
||||
|
||||
// =================================
|
||||
// Determine if a Dropdown is Active
|
||||
// =================================
|
||||
|
||||
public function dropdownActive() {
|
||||
|
||||
$dropdown_serial = filter_input(INPUT_POST, "dropdown_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$dropdown = $this->getDropdown($dropdown_serial);
|
||||
|
||||
if ($dropdown->count() == 0) {
|
||||
$this->logError("Invalid Dropdown ({$dropdown_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$table = (string) $dropdown->record->dropdowntype_table;
|
||||
$column = (string) $dropdown->record->dropdowntype_column;
|
||||
|
||||
$active = false;
|
||||
|
||||
switch ($table) {
|
||||
|
||||
case "*none": // No table, never Active.
|
||||
|
||||
break;
|
||||
|
||||
case "*function": // Requires it's own function to determine if Active.
|
||||
|
||||
if (method_exists(__CLASS__, $column)) {
|
||||
$active = $this->$column($dropdown_serial);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default: // All others, test the Column in the Table.
|
||||
|
||||
$SQL = "select {$column}
|
||||
from {$table}
|
||||
where {$column} = {$dropdown_serial}";
|
||||
|
||||
$results = $this->getTable("results", $SQL);
|
||||
|
||||
$active = ($results->count() > 0) ? true : false;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
echo json_encode($active);
|
||||
}
|
||||
|
||||
// =====================================
|
||||
// Determine if a Dropdowntype is Active
|
||||
// =====================================
|
||||
|
||||
public function dropdowntypeActive() {
|
||||
|
||||
$dropdowntype_serial = (integer) filter_input(INPUT_POST, "dropdowntype_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$SQL = "select dropdown_serial
|
||||
from view_dropdowns
|
||||
where dropdown_dropdowntype = {$dropdowntype_serial}";
|
||||
|
||||
$dropdowns = $this->getTable("dropdowns", $SQL);
|
||||
|
||||
$active = ($dropdowns->count() > 0) ? true : false;
|
||||
|
||||
echo json_encode($active);
|
||||
}
|
||||
|
||||
// ===============
|
||||
// Edit a Dropdown
|
||||
// ===============
|
||||
|
||||
public function editDropdown() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$dropdown_serial = filter_input(INPUT_POST, "dropdown_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$dropdown = $this->getDropdown($dropdown_serial);
|
||||
|
||||
if ($dropdown->count() == 0) {
|
||||
$this->logError("Invalid Dropdown ({$dropdown_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$XML = $this->mergeXML($dropdown, "<XML/>");
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("./system/editDropdown"));
|
||||
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "update":
|
||||
|
||||
$dropdown_serial = filter_input(INPUT_POST, "dropdown_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$dropdown_value = filter_input(INPUT_POST, "dropdown_value") ?: "";
|
||||
|
||||
$dropdown = $this->getDropdown($dropdown_serial);
|
||||
|
||||
if ($dropdown->count() == 0) {
|
||||
$this->logError("Invalid Dropdown ({$dropdown_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$SQL = "update dropdowns
|
||||
set dropdown_value = :dropdown_value,
|
||||
dropdown_changer = :dropdown_changer,
|
||||
dropdown_changed = :dropdown_changed
|
||||
where dropdown_serial = :dropdown_serial";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":dropdown_serial", $dropdown_serial);
|
||||
$statement->bindValue(":dropdown_value", $dropdown_value);
|
||||
$statement->bindValue(":dropdown_changer", $this->current_user_name);
|
||||
$statement->bindValue(":dropdown_changed", $this->getTimestamp());
|
||||
|
||||
$statement->execute();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// ===================
|
||||
// Edit a Dropdowntype
|
||||
// ===================
|
||||
|
||||
public function editDropdowntype() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$dropdowntype_serial = filter_input(INPUT_POST, "dropdowntype_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$dropdowntype = $this->getDropdowntype($dropdowntype_serial);
|
||||
|
||||
if ($dropdowntype->count() == 0) {
|
||||
$this->logError("Invalid Dropdowntype ({$dropdowntype_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$XML = $this->mergeXML($dropdowntype, "<XML/>");
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("./system/editDropdowntype"));
|
||||
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "update":
|
||||
|
||||
$dropdowntype_serial = filter_input(INPUT_POST, "dropdowntype_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$dropdowntype_name = filter_input(INPUT_POST, "dropdowntype_name") ?: "";
|
||||
$dropdowntype_title = filter_input(INPUT_POST, "dropdowntype_title") ?: "";
|
||||
$dropdowntype_table = filter_input(INPUT_POST, "dropdowntype_table") ?: "";
|
||||
$dropdowntype_column = filter_input(INPUT_POST, "dropdowntype_column") ?: "";
|
||||
|
||||
$dropdowntype = $this->getDropdowntype($dropdowntype_serial);
|
||||
|
||||
if ($dropdowntype->count() == 0) {
|
||||
$this->logError("Invalid Dropdowntype ({$dropdowntype_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$SQL = "update dropdowntypes
|
||||
set dropdowntype_name = :dropdowntype_name,
|
||||
dropdowntype_title = :dropdowntype_title,
|
||||
dropdowntype_table = :dropdowntype_table,
|
||||
dropdowntype_column = :dropdowntype_column,
|
||||
dropdowntype_changer = :dropdowntype_changer,
|
||||
dropdowntype_changed = :dropdowntype_changed
|
||||
where dropdowntype_serial = :dropdowntype_serial";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":dropdowntype_serial", $dropdowntype_serial);
|
||||
$statement->bindValue(":dropdowntype_name", $dropdowntype_name);
|
||||
$statement->bindValue(":dropdowntype_title", $dropdowntype_title);
|
||||
$statement->bindValue(":dropdowntype_table", $dropdowntype_table);
|
||||
$statement->bindValue(":dropdowntype_column", $dropdowntype_column);
|
||||
$statement->bindValue(":dropdowntype_changer", $this->current_user_name);
|
||||
$statement->bindValue(":dropdowntype_changed", $this->getTimestamp());
|
||||
|
||||
$statement->execute();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// =================================
|
||||
// Return an Active Dropdowns Object
|
||||
// =================================
|
||||
|
||||
public function getActiveDropdowns() {
|
||||
|
||||
$SQL = "select view_dropdowns.*
|
||||
from view_dropdowns
|
||||
where dropdown_active is true";
|
||||
|
||||
return $this->getTable("dropdowns", $SQL);
|
||||
}
|
||||
|
||||
// ========================
|
||||
// Return a Dropdown Object
|
||||
// ========================
|
||||
|
||||
public function getDropdown($dropdown_serial = 0) {
|
||||
|
||||
$SQL = "select view_dropdowns.*
|
||||
from view_dropdowns
|
||||
where dropdown_serial = {$dropdown_serial}";
|
||||
|
||||
return $this->getTable("dropdowns", $SQL);
|
||||
}
|
||||
|
||||
// =========================
|
||||
// Return a Dropdowns Object
|
||||
// =========================
|
||||
|
||||
public function getDropdowns() {
|
||||
|
||||
$SQL = "select view_dropdowns.*
|
||||
from view_dropdowns";
|
||||
|
||||
return $this->getTable("dropdowns", $SQL);
|
||||
}
|
||||
|
||||
// ============================
|
||||
// Return a Dropdowntype Object
|
||||
// ============================
|
||||
|
||||
public function getDropdowntype($dropdowntype_serial = 0) {
|
||||
|
||||
$SQL = "select view_dropdowntypes.*
|
||||
from view_dropdowntypes
|
||||
where dropdowntype_serial = {$dropdowntype_serial}";
|
||||
|
||||
return $this->getTable("dropdowntypes", $SQL);
|
||||
}
|
||||
|
||||
// ============================
|
||||
// Return a Dropdowntype Object
|
||||
// ============================
|
||||
|
||||
public function getDropdownsByDropdownType($dropdowntype = 0) {
|
||||
|
||||
$SQL = "select view_dropdowns.*
|
||||
from view_dropdowns
|
||||
where dropdown_dropdowntype = {$dropdowntype}";
|
||||
|
||||
return $this->getTable("dropdowns", $SQL);
|
||||
}
|
||||
|
||||
// =============================
|
||||
// Return a Dropdowntypes Object
|
||||
// =============================
|
||||
|
||||
public function getDropdowntypes() {
|
||||
|
||||
$SQL = "select view_dropdowntypes.*
|
||||
from view_dropdowntypes";
|
||||
|
||||
return $this->getTable("dropdowntypes", $SQL);
|
||||
}
|
||||
|
||||
// ==================================
|
||||
// Return a Dropdowntypes Page Object
|
||||
// ==================================
|
||||
|
||||
public function getDropdowntypesPage() {
|
||||
|
||||
// Find Criteria
|
||||
|
||||
$find_dropdowntype = filter_input(INPUT_POST, "find_dropdowntype") ?: "";
|
||||
$find_words = $this->sanitizeString($find_dropdowntype);
|
||||
|
||||
// Show Per Page
|
||||
|
||||
$this->pagination_size = filter_input(INPUT_POST, "users_per_page", FILTER_SANITIZE_NUMBER_INT) ?: $this->pagination_size;
|
||||
|
||||
// Record Count
|
||||
|
||||
$connection = $this->connect();
|
||||
|
||||
$SQL = "select count(*) as count
|
||||
from view_dropdowntypes
|
||||
where (dropdowntype_name regexp :dropdowntype_name
|
||||
or dropdowntype_title regexp :dropdowntype_title
|
||||
or dropdowntype_table regexp :dropdowntype_table
|
||||
or dropdowntype_column regexp :dropdowntype_column)";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":dropdowntype_name", $find_words);
|
||||
$statement->bindValue(":dropdowntype_title", $find_words);
|
||||
$statement->bindValue(":dropdowntype_table", $find_words);
|
||||
$statement->bindValue(":dropdowntype_column", $find_words);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$recordset = $statement->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$count = (count($recordset) > 0) ? (integer) $recordset["count"] : (integer) 0;
|
||||
|
||||
// Pagination
|
||||
|
||||
$pagination = filter_input(INPUT_POST, "pagination") ?: "";
|
||||
|
||||
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 = ($count / $this->pagination_size);
|
||||
break;
|
||||
}
|
||||
|
||||
$offset = (($this->pagination_page * $this->pagination_size) - $this->pagination_size);
|
||||
$start = ($offset + 1);
|
||||
$end = min($count, (($start + $this->pagination_size) - 1));
|
||||
|
||||
// Data
|
||||
|
||||
$SQL = "select view_dropdowntypes.*
|
||||
from view_dropdowntypes
|
||||
where (dropdowntype_name regexp :dropdowntype_name
|
||||
or dropdowntype_title regexp :dropdowntype_title
|
||||
or dropdowntype_table regexp :dropdowntype_table
|
||||
or dropdowntype_column regexp :dropdowntype_column)
|
||||
limit {$this->pagination_size}
|
||||
offset {$offset}";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":dropdowntype_name", $find_words);
|
||||
$statement->bindValue(":dropdowntype_title", $find_words);
|
||||
$statement->bindValue(":dropdowntype_table", $find_words);
|
||||
$statement->bindValue(":dropdowntype_column", $find_words);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$dropdowntypes = $this->getTableXML("dropdowntypes", $statement);
|
||||
|
||||
// Insert Pagination Attributes
|
||||
|
||||
$dropdowntypes->addAttribute("count", $count);
|
||||
$dropdowntypes->addAttribute("start", $start);
|
||||
$dropdowntypes->addAttribute("end", $end);
|
||||
$dropdowntypes->addAttribute("page", $this->pagination_page);
|
||||
|
||||
$_SESSION[self::PAGINATION_PAGE] = $this->pagination_page;
|
||||
|
||||
return $dropdowntypes;
|
||||
}
|
||||
|
||||
// ===============
|
||||
// Setup Dropdowns
|
||||
// ===============
|
||||
|
||||
public function setupDropdowns() {
|
||||
|
||||
$dropdowntypes = $this->getDropdowntypes();
|
||||
$dropdowns = $this->getDropdowns();
|
||||
|
||||
$XML = $this->mergeXML($dropdowntypes, "<XML/>");
|
||||
$XML = $this->mergeXML($dropdowns, $XML);
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("./system/setupDropdowns"));
|
||||
|
||||
$this->displayContent($content);
|
||||
}
|
||||
|
||||
// ===================
|
||||
// Setup Dropdowntypes
|
||||
// ===================
|
||||
|
||||
public function setupDropdowntypes() {
|
||||
|
||||
$dropdowntypes = $this->getDropdowntypesPage();
|
||||
$popovers = (new Popovers())->getPopovers();
|
||||
|
||||
$XML = $this->mergeXML($dropdowntypes, "<XML/>");
|
||||
$XML = $this->mergeXML($popovers, $XML);
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("./system/setupDropdowntypes"));
|
||||
|
||||
$this->displayContent($content);
|
||||
}
|
||||
|
||||
// ======================
|
||||
// Update Dropdown Active
|
||||
// ======================
|
||||
|
||||
public function updateDropdownActive() {
|
||||
|
||||
$dropdown_serial = filter_input(INPUT_POST, "dropdown_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$dropdown_checked = filter_input(INPUT_POST, "dropdown_checked", FILTER_VALIDATE_BOOLEAN) ?: false;
|
||||
|
||||
$SQL = "update dropdowns
|
||||
set dropdown_active = :dropdown_active,
|
||||
dropdown_changer = :dropdown_changer,
|
||||
dropdown_changed = :dropdown_changed
|
||||
where dropdown_serial = :dropdown_serial";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":dropdown_serial", $dropdown_serial);
|
||||
$statement->bindValue(":dropdown_active", $dropdown_checked, PDO::PARAM_BOOL);
|
||||
$statement->bindValue(":dropdown_changer", $this->current_user_name);
|
||||
$statement->bindValue(":dropdown_changed", $this->getTimestamp());
|
||||
|
||||
$statement->execute();
|
||||
}
|
||||
|
||||
// =======================
|
||||
// Update Dropdown Default
|
||||
// =======================
|
||||
|
||||
public function updateDropdownDefault() {
|
||||
|
||||
$dropdown_serial = filter_input(INPUT_POST, "dropdown_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$dropdown_dropdowntype = filter_input(INPUT_POST, "dropdown_dropdowntype", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$dropdown_checked = filter_input(INPUT_POST, "dropdown_checked") ?: "false";
|
||||
|
||||
// Unset the Default for the Dropdown Type.
|
||||
|
||||
$SQL = "update dropdowns
|
||||
set dropdown_default = false
|
||||
where dropdown_dropdowntype = {$dropdown_dropdowntype}";
|
||||
|
||||
$this->executeSQL($SQL);
|
||||
|
||||
// Set the Default for the clicked Dropdown.
|
||||
|
||||
$SQL = "update dropdowns
|
||||
set dropdown_default = {$dropdown_checked}
|
||||
where dropdown_serial = {$dropdown_serial}";
|
||||
|
||||
$this->executeSQL($SQL);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,186 @@
|
||||
<?php
|
||||
|
||||
// ===========
|
||||
// Email Class
|
||||
// ===========
|
||||
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
|
||||
class Email extends Base {
|
||||
|
||||
// Variables.
|
||||
|
||||
private $current_user_name = "";
|
||||
private $current_user_email = "";
|
||||
|
||||
// ==================
|
||||
// Class Constructor.
|
||||
// ==================
|
||||
|
||||
public function __construct() {
|
||||
|
||||
set_error_handler(array($this, "displayError"));
|
||||
|
||||
date_default_timezone_set(self::TIMEZONE);
|
||||
|
||||
$this->current_user_name = $_SESSION[self::USER_NAME] ?? "";
|
||||
$this->current_user_email = $_SESSION[self::USER_EMAIL] ?? "";
|
||||
}
|
||||
|
||||
// =============================
|
||||
// Email a new users credentials
|
||||
// =============================
|
||||
|
||||
public function emailNewUserCredentials($user, $password) {
|
||||
|
||||
if (!$user instanceof SimpleXMLElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Prepare the email
|
||||
|
||||
$to = (string) $user->record->user_email;
|
||||
|
||||
$XSLParms['USER-TEMP-PASSWORD'] = $password;
|
||||
|
||||
$subject = "DEC International DMS - New User Credentials";
|
||||
$message = $this->applyXSL($user, $this->getXSL("emailNewUserCredentials"), $XSLParms);
|
||||
|
||||
// Send the Email
|
||||
$this->sendEmail($to, $subject, $message);
|
||||
}
|
||||
|
||||
// =================================
|
||||
// Email a users Password Reset Link
|
||||
// =================================
|
||||
|
||||
public function emailUserPasswordResetLink($user, $password) {
|
||||
|
||||
if (!$user instanceof SimpleXMLElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Prepare the email.
|
||||
|
||||
$XSLParms['USER-TEMP-PASSWORD'] = $password;
|
||||
|
||||
$to = (string) $user->record->user_email;
|
||||
$subject = "DEC International DMS - Password Reset Request";
|
||||
$message = $this->applyXSL($user, $this->getXSL("emailPasswordResetLink"), $XSLParms);
|
||||
|
||||
// Send the Email
|
||||
$this->sendEmail($to, $subject, $message);
|
||||
}
|
||||
|
||||
// =======================================
|
||||
// Send an email with optional attachments
|
||||
// =======================================
|
||||
|
||||
public function sendEmail($to = "", $subject = "", $message = "", $attachments = "", $attachment_names = "unknown") {
|
||||
|
||||
if (empty($to) or empty($subject) or empty($message)) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$settings = $this->getSettings();
|
||||
|
||||
$SmtpHost = $settings->SmtpServer;
|
||||
$SmtpUsername = $settings->SmtpUserName;
|
||||
$SmtpPassword = $settings->SmtpPassword;
|
||||
$SmtpPort = $settings->SmtpPort;
|
||||
|
||||
$email = new PHPMailer(true);
|
||||
|
||||
// Only for development
|
||||
|
||||
$message = "<span style='font-family: Calibri, Arial, sans-serif;'>" . $message . "</span>";
|
||||
|
||||
try {
|
||||
|
||||
//Server settings
|
||||
$email->isSMTP();
|
||||
$email->Host = $SmtpHost;
|
||||
$email->SMTPAuth = true;
|
||||
$email->Username = $SmtpUsername; // Your Gmail address
|
||||
$email->Password = $SmtpPassword; // App password from Google
|
||||
// $email->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // or 'tls'
|
||||
$email->Port = $SmtpPort;
|
||||
|
||||
$email->isHTML(true);
|
||||
$email->SetFrom("info@onesourceits.com", "OneSource IT Solutions LLC");
|
||||
|
||||
if (is_array($to)) {
|
||||
foreach ($to as $address) {
|
||||
$address = trim(str_replace(" ", "", $address));
|
||||
if (empty($address)) {
|
||||
continue;
|
||||
}
|
||||
$email->addAddress($address);
|
||||
}
|
||||
} else {
|
||||
$email->addAddress($to);
|
||||
}
|
||||
|
||||
$email->Subject = $subject;
|
||||
$email->Body = $message;
|
||||
|
||||
if (is_array($attachments)) {
|
||||
foreach ($attachments as $index => $item) {
|
||||
if (!empty($item)) {
|
||||
$email->addStringAttachment($item, ($attachment_names[$index] ?? "unknown"));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!empty($attachments)) {
|
||||
$email->addStringAttachment($attachments, $attachment_names);
|
||||
}
|
||||
}
|
||||
|
||||
$success = $email->Send();
|
||||
} catch (phpMailerException $e) {
|
||||
|
||||
(new Journal())->journalEntry($e->errorMessage());
|
||||
$success = false;
|
||||
} catch (Exception $e) {
|
||||
|
||||
(new Journal())->journalEntry($e->getMessage());
|
||||
$success = false;
|
||||
}
|
||||
|
||||
return $success;
|
||||
}
|
||||
|
||||
// ==============================
|
||||
// Send an Error Email to Support
|
||||
// ==============================
|
||||
|
||||
public function sendErrorEmail($error_message = "", $error_file = "", $error_line = "") {
|
||||
|
||||
$settings = $this->getSettings();
|
||||
|
||||
$Environment = (string) $settings->Environment;
|
||||
$SupportEmail = (string) $settings->SupportEmail;
|
||||
|
||||
if ($Environment == "Development") {
|
||||
return;
|
||||
}
|
||||
|
||||
$application_name = self::APPLICATION_NAME;
|
||||
|
||||
$message = "";
|
||||
|
||||
$message .= "<p>An application error has occurred in the {$application_name} application.<br/><br/></p>";
|
||||
$message .= "<p>File: {$error_file}</p>";
|
||||
$message .= "<p>Line: {$error_line}</p>";
|
||||
$message .= "<p>Error: {$error_message}</p>";
|
||||
|
||||
$to = $SupportEmail;
|
||||
$subject = "{$application_name} Application Error";
|
||||
|
||||
$this->sendEmail($to, $subject, $message);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,267 @@
|
||||
<?php
|
||||
|
||||
// ============
|
||||
// Export Class
|
||||
// ============
|
||||
|
||||
class Export 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;
|
||||
}
|
||||
|
||||
// =====================
|
||||
// Create Export Request
|
||||
// =====================
|
||||
|
||||
public function createExportRequest() {
|
||||
|
||||
$report_type = filter_input(INPUT_POST, "report_type") ?: "";
|
||||
$export_license_type = filter_input(INPUT_POST, "export_license_type") ?: "";
|
||||
|
||||
$exportjob_file_name = "searchresults_records.{$report_type}";
|
||||
|
||||
$searchcriteria = $this->getLicenseSearchCriteria($_POST);
|
||||
|
||||
$SQL = "insert into exportjobs
|
||||
|
||||
( exportjob_license_type,
|
||||
exportjob_file_name,
|
||||
exportjob_file_type,
|
||||
exportjob_searchcriteria,
|
||||
exportjob_creator,
|
||||
exportjob_created )
|
||||
|
||||
VALUES ( :exportjob_license_type,
|
||||
:exportjob_file_name,
|
||||
:exportjob_file_type,
|
||||
:exportjob_searchcriteria,
|
||||
:exportjob_creator,
|
||||
:exportjob_created )";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":exportjob_license_type", $export_license_type);
|
||||
$statement->bindValue(":exportjob_file_name", $exportjob_file_name);
|
||||
$statement->bindValue(":exportjob_file_type", strtoupper($report_type));
|
||||
$statement->bindValue(":exportjob_searchcriteria", $searchcriteria);
|
||||
$statement->bindValue(":exportjob_creator", $this->current_user_serial);
|
||||
$statement->bindValue(":exportjob_created", $this->getTimestamp());
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$this->displayNotice("Your export has been queued. You will receive an notification when it is ready.");
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// Return License Search Criteria json Object
|
||||
// ==========================================
|
||||
|
||||
private function getLicenseSearchCriteria(): string {
|
||||
$criteria = array_filter(
|
||||
$_POST,
|
||||
function ($key) {
|
||||
return strpos($key, 'license_') === 0;
|
||||
},
|
||||
ARRAY_FILTER_USE_KEY
|
||||
);
|
||||
|
||||
$criteria = array_filter($criteria, function ($value) {
|
||||
return trim($value) !== '';
|
||||
});
|
||||
|
||||
return json_encode($criteria);
|
||||
}
|
||||
|
||||
// ============
|
||||
// User Exports
|
||||
// ============
|
||||
|
||||
public function usersExports() {
|
||||
|
||||
$exports = $this->getUsersExports();
|
||||
$popovers = (new Popovers())->getPopovers();
|
||||
|
||||
$this->markExportsAsSeen();
|
||||
|
||||
$XML = $this->mergeXML($exports, "<XML/>");
|
||||
$XML = $this->mergeXML($popovers, $XML);
|
||||
|
||||
$html = $this->applyXSL($XML, $this->getXSL("viewExports"));
|
||||
|
||||
$this->displayContent($html);
|
||||
}
|
||||
|
||||
// =========================
|
||||
// Mark User Exports as Seen
|
||||
// =========================
|
||||
|
||||
public function markExportsAsSeen() {
|
||||
|
||||
$SQL = "update exportjobs
|
||||
set exportjob_notified = true
|
||||
where exportjobs.exportjob_creator = {$this->current_user_serial}";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->execute();
|
||||
}
|
||||
|
||||
// =======================
|
||||
// Return a Exports Object
|
||||
// =======================
|
||||
|
||||
public function getUsersExports() {
|
||||
|
||||
// Find Criteria
|
||||
|
||||
$find_exportjob = filter_input(INPUT_POST, "find_exportjob") ?: "";
|
||||
$find_words = $this->sanitizeString($find_exportjob);
|
||||
|
||||
// Show Per Page
|
||||
$this->pagination_size = filter_input(INPUT_POST, "exportjobs_per_page", FILTER_SANITIZE_NUMBER_INT) ?: $this->pagination_size;
|
||||
|
||||
// Record Count
|
||||
|
||||
$connection = $this->connect();
|
||||
|
||||
$SQL = "select count(*) as count
|
||||
from view_exportjobs
|
||||
where view_exportjobs.exportjob_creator = {$this->current_user_serial}
|
||||
and view_exportjobs.subscription_full_title regexp :subscription_full_title";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":subscription_full_title", $find_words);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$recordset = $statement->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$count = (count($recordset) > 0) ? (integer) $recordset["count"] : (integer) 0;
|
||||
|
||||
// Pagination
|
||||
|
||||
$pagination = filter_input(INPUT_POST, "pagination") ?: "";
|
||||
|
||||
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 = ($count / $this->pagination_size);
|
||||
break;
|
||||
}
|
||||
|
||||
$offset = (($this->pagination_page * $this->pagination_size) - $this->pagination_size);
|
||||
$start = ($offset + 1);
|
||||
$end = min($count, (($start + $this->pagination_size) - 1));
|
||||
|
||||
// Data
|
||||
|
||||
$SQL = "select view_exportjobs.*
|
||||
from view_exportjobs
|
||||
where view_exportjobs.exportjob_creator = {$this->current_user_serial}
|
||||
and view_exportjobs.subscription_full_title regexp :subscription_full_title
|
||||
limit {$this->pagination_size}
|
||||
offset {$offset}";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":subscription_full_title", $find_words);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$exportjobs = $this->getTableXML("exportjobs", $statement);
|
||||
|
||||
// Insert Pagination Attributes
|
||||
|
||||
$exportjobs->addAttribute("count", $count);
|
||||
$exportjobs->addAttribute("start", $start);
|
||||
$exportjobs->addAttribute("end", $end);
|
||||
$exportjobs->addAttribute("page", $this->pagination_page);
|
||||
|
||||
$_SESSION[self::PAGINATION_PAGE] = $this->pagination_page;
|
||||
|
||||
return $exportjobs;
|
||||
}
|
||||
|
||||
// =====================================
|
||||
// Return if users exports are completed
|
||||
// =====================================
|
||||
|
||||
public function checkUsersCompletedExports_AJAX() {
|
||||
|
||||
$SQL = "select count(*) as notify
|
||||
from view_exportjobs
|
||||
where view_exportjobs.exportjob_creator = {$this->current_user_serial}
|
||||
and view_exportjobs.exportjob_status = 'complete'
|
||||
and view_exportjobs.exportjob_notified = 0";
|
||||
|
||||
$exportjobs = $this->getTable("exportjobs", $SQL);
|
||||
|
||||
// Create the User Object.
|
||||
|
||||
$users_exports = array();
|
||||
|
||||
$users_exports["notify"] = ($exportjobs->record->notify == 0) ? false : true;
|
||||
|
||||
if ($_SESSION[self::AJAX]) {
|
||||
echo json_encode($users_exports);
|
||||
} else {
|
||||
return $users_exports;
|
||||
}
|
||||
}
|
||||
|
||||
// ===============
|
||||
// Download Export
|
||||
// ===============
|
||||
|
||||
public function downloadExport() {
|
||||
|
||||
$export_code = filter_input(INPUT_POST, "export_code") ?: "";
|
||||
|
||||
$SQL = "select view_exportjobs.*
|
||||
from view_exportjobs
|
||||
where view_exportjobs.exportjob_download_token = '{$export_code}'
|
||||
and view_exportjobs.exportjob_status = 'complete' limit 1";
|
||||
|
||||
$exportjob = $this->getTable("exportjob", $SQL);
|
||||
|
||||
$file_path = str_replace('../exports/', './exports/', $exportjob->record->exportjob_file_path);
|
||||
$file_name = $exportjob->record->exportjob_file_name;
|
||||
|
||||
header('Content-Type: application/octet-stream');
|
||||
header("Content-Disposition: attachment; filename=\"$file_name\"");
|
||||
|
||||
readfile($file_path);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,762 @@
|
||||
<?php
|
||||
|
||||
class FWCLicenses 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;
|
||||
}
|
||||
|
||||
// ============================
|
||||
// Search Recreational Licenses
|
||||
// ============================
|
||||
|
||||
public function searchRecreationalLicenses() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
$popovers = (new Popovers())->getPopovers();
|
||||
$dropdowns = (new Dropdowns())->getDropdowns();
|
||||
$constants = $this->getConstants();
|
||||
$cities = (new Cities())->getCities();
|
||||
|
||||
$XML = $this->mergeXML($popovers, "<XML/>");
|
||||
$XML = $this->mergeXML($dropdowns, $XML);
|
||||
$XML = $this->mergeXML($constants, $XML);
|
||||
$XML = $this->mergeXML($cities, $XML);
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$this->displayContent($this->applyXSL($XML, $this->getXSL("searchRecreationalLicenses")));
|
||||
|
||||
break;
|
||||
|
||||
case "search":
|
||||
|
||||
$licenses = $this->getRecreationalLicensesPage();
|
||||
|
||||
$XML = $this->mergeXML($licenses, $XML);
|
||||
|
||||
$this->displayContent($this->applyXSL($XML, $this->getXSL("searchRecreationalLicenses")));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================
|
||||
// Search Commercial Licenses
|
||||
// ==========================
|
||||
|
||||
public function searchCommercialLicenses() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
$popovers = (new Popovers())->getPopovers();
|
||||
$dropdowns = (new Dropdowns())->getDropdowns();
|
||||
$constants = $this->getConstants();
|
||||
$cities = (new Cities())->getCities();
|
||||
$licensescodes = $this->getCommercialLicenseCodes();
|
||||
|
||||
$XML = $this->mergeXML($popovers, "<XML/>");
|
||||
$XML = $this->mergeXML($dropdowns, $XML);
|
||||
$XML = $this->mergeXML($constants, $XML);
|
||||
$XML = $this->mergeXML($cities, $XML);
|
||||
$XML = $this->mergeXML($licensescodes, $XML);
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$this->displayContent($this->applyXSL($XML, $this->getXSL("searchCommercialLicenses")));
|
||||
|
||||
break;
|
||||
|
||||
case "search":
|
||||
|
||||
$licenses = $this->getRecreationalLicensesPage();
|
||||
|
||||
$XML = $this->mergeXML($licenses, $XML);
|
||||
|
||||
$this->displayContent($this->applyXSL($XML, $this->getXSL("searchCommercialLicenses")));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ===============
|
||||
// License Summary
|
||||
// ===============
|
||||
|
||||
public function licenseSummary() {
|
||||
|
||||
$license_serial = filter_input(INPUT_POST, "license_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$license = $this->getLicense($license_serial);
|
||||
|
||||
if ($license->count() == 0) {
|
||||
$this->logError("Invalid License ({$license_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$XML = $this->mergeXML($license, "<XML/>");
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("licenseSummary"));
|
||||
$this->displayContent($content);
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// Return AutoComplete License Numbers (ajax)
|
||||
// ==========================================
|
||||
|
||||
public function getAutoCompleteLicenseNumbers() {
|
||||
|
||||
$results = array();
|
||||
|
||||
$licensenumber = filter_input(INPUT_GET, "commercial_license_number") ?: "";
|
||||
$licensenumber = trim(preg_replace("/\s+/", " ", $licensenumber));
|
||||
$licensenumber = preg_replace("/'+/", "'", $licensenumber);
|
||||
$licensenumber = preg_replace('/"+/', '"', $licensenumber);
|
||||
$licensenumber = str_replace("'", "''", $licensenumber);
|
||||
|
||||
$SQL = "select distinct commercial_license_number from view_fwc_commercial_licenses where commercial_license_number like '%{$licensenumber}%' order by commercial_license_number limit 10 offset 0";
|
||||
|
||||
$matches = $this->getTable("licensenumbers", $SQL);
|
||||
|
||||
foreach ($matches as $match) {
|
||||
$results[] = (string) $match->commercial_license_number;
|
||||
}
|
||||
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode($results);
|
||||
exit();
|
||||
}
|
||||
|
||||
// =============================
|
||||
// Determine if a License exists
|
||||
// =============================
|
||||
|
||||
public function licenseExists() {
|
||||
|
||||
$license_serial = filter_input(INPUT_POST, "license_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$license_name = filter_input(INPUT_POST, "license_name") ?: "";
|
||||
|
||||
$SQL = "select license_serial
|
||||
from view_licenses
|
||||
where license_serial != :license_serial
|
||||
and lower(license_name) = :license_name";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":license_serial", $license_serial);
|
||||
$statement->bindValue(":license_name", strtolower($license_name));
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$recordset = $statement->fetchAll(PDO::FETCH_ASSOC);
|
||||
$exists = (count($recordset) > 0) ? true : false;
|
||||
|
||||
echo json_encode($exists);
|
||||
}
|
||||
|
||||
// ============================
|
||||
// Return a License Type Object
|
||||
// ============================
|
||||
|
||||
public function getCommercialLicenseCodes() {
|
||||
|
||||
$SQL = "select fwc_commercial_license_codes.*
|
||||
from fwc_commercial_license_codes";
|
||||
|
||||
return $this->getTable("licensecodes", $SQL);
|
||||
}
|
||||
|
||||
// ============================
|
||||
// Return a License Type Object
|
||||
// ============================
|
||||
|
||||
public function getLicenseTypes() {
|
||||
|
||||
$SQL = "select distinct license_type
|
||||
from fwc_recreational_licenses
|
||||
where license_type != ''";
|
||||
|
||||
return $this->getTable("licensetypes", $SQL);
|
||||
}
|
||||
|
||||
// ========================
|
||||
// Return an License Object
|
||||
// ========================
|
||||
|
||||
public function getLicense($license_serial = 0) {
|
||||
|
||||
$SQL = "select view_licenses.*
|
||||
from view_licenses
|
||||
where license_serial = {$license_serial}";
|
||||
|
||||
return $this->getTable("licenses", $SQL);
|
||||
}
|
||||
|
||||
// ========================
|
||||
// Return a Licenses Object
|
||||
// ========================
|
||||
|
||||
public function getLicenses() {
|
||||
|
||||
$SQL = "select view_licenses.* from view_licenses";
|
||||
|
||||
return $this->getTable("licenses", $SQL);
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// Return a Recreational Licenses Page Object
|
||||
// ==========================================
|
||||
|
||||
public function getRecreationalLicensesPage() {
|
||||
|
||||
// ===============
|
||||
// Sanitize Inputs
|
||||
// ===============
|
||||
|
||||
$license_last_name = trim(filter_input(INPUT_POST, "license_last_name") ?: "");
|
||||
$license_first_name = trim(filter_input(INPUT_POST, "license_first_name") ?: "");
|
||||
$license_counties = $this->getMultiSelectInput("license_county");
|
||||
$license_cities = $this->getMultiSelectInput("license_city");
|
||||
$license_types = $this->getMultiSelectInput("license_type");
|
||||
$license_genders = $this->getMultiSelectInput("license_gender");
|
||||
$license_ethnicities = $this->getMultiSelectInput("license_ethnicity");
|
||||
$license_start_date = trim(filter_input(INPUT_POST, "license_start_date") ?: "");
|
||||
$license_expire_date = trim(filter_input(INPUT_POST, "license_expire_date") ?: "");
|
||||
$pagination = trim(filter_input(INPUT_POST, "pagination") ?: "");
|
||||
|
||||
$license_start_date = empty($license_start_date) ? null : date("Y-m-d", strtotime($license_start_date));
|
||||
$license_expire_date = empty($license_expire_date) ? null : date("Y-m-d", strtotime($license_expire_date));
|
||||
|
||||
// ===================
|
||||
// Pagination Settings
|
||||
// ===================
|
||||
|
||||
$this->pagination_page = isset($_SESSION[self::PAGINATION_PAGE]) ? (int) $_SESSION[self::PAGINATION_PAGE] : 1;
|
||||
$this->pagination_size = (int) (filter_input(INPUT_POST, "licenses_per_page", FILTER_SANITIZE_NUMBER_INT) ?: $this->pagination_size);
|
||||
|
||||
if ($this->pagination_size <= 0) {
|
||||
$this->pagination_size = 25;
|
||||
}
|
||||
|
||||
$licenses_order_by = trim(filter_input(INPUT_POST, "licenses_order_by") ?: "license_last_name");
|
||||
$licenses_order_direction = strtoupper(trim(filter_input(INPUT_POST, "licenses_order_direction") ?: "ASC"));
|
||||
|
||||
$allowed_order_columns = [
|
||||
"license_last_name",
|
||||
"license_first_name",
|
||||
"license_county",
|
||||
"license_city",
|
||||
"license_type",
|
||||
"license_gender",
|
||||
"license_ethnicity",
|
||||
"license_start_date",
|
||||
"license_expire_date"
|
||||
];
|
||||
|
||||
if (!in_array($licenses_order_by, $allowed_order_columns, true)) {
|
||||
$licenses_order_by = "license_last_name";
|
||||
}
|
||||
|
||||
if (!in_array($licenses_order_direction, ["ASC", "DESC"], true)) {
|
||||
$licenses_order_direction = "ASC";
|
||||
}
|
||||
|
||||
// ===================
|
||||
// Connect to Database
|
||||
// ===================
|
||||
|
||||
$connection = $this->connect();
|
||||
$license_counties = $this->getDropdownValuesBySerial($connection, $license_counties);
|
||||
$license_types = $this->getDropdownValuesBySerial($connection, $license_types);
|
||||
$license_ethnicities = $this->getDropdownValuesBySerial($connection, $license_ethnicities);
|
||||
|
||||
// ==================
|
||||
// Build WHERE Clause
|
||||
// ==================
|
||||
|
||||
$where = [];
|
||||
$params = [];
|
||||
|
||||
if (!empty($license_last_name)) {
|
||||
$where[] = "fwc_recreational_licenses.license_last_name LIKE :license_last_name";
|
||||
$params[":license_last_name"] = $license_last_name . "%";
|
||||
}
|
||||
|
||||
if (!empty($license_first_name)) {
|
||||
$where[] = "fwc_recreational_licenses.license_first_name LIKE :license_first_name";
|
||||
$params[":license_first_name"] = $license_first_name . "%";
|
||||
}
|
||||
|
||||
$this->addInFilter($where, $params, "fwc_recreational_licenses.license_county", "license_county", $license_counties);
|
||||
$this->addInFilter($where, $params, "fwc_recreational_licenses.license_city", "license_city", $license_cities);
|
||||
$this->addInFilter($where, $params, "fwc_recreational_licenses.license_type", "license_type", $license_types);
|
||||
$this->addInFilter($where, $params, "fwc_recreational_licenses.license_gender", "license_gender", $license_genders);
|
||||
$this->addInFilter($where, $params, "fwc_recreational_licenses.license_ethnicity", "license_ethnicity", $license_ethnicities);
|
||||
|
||||
if (!empty($license_start_date) && !empty($license_expire_date)) {
|
||||
$where[] = "fwc_recreational_licenses.license_start_date BETWEEN :license_start_date AND :license_expire_date";
|
||||
$params[":license_start_date"] = $license_start_date;
|
||||
$params[":license_expire_date"] = $license_expire_date;
|
||||
}
|
||||
|
||||
$whereSQL = "";
|
||||
|
||||
if (!empty($where)) {
|
||||
$whereSQL = " WHERE " . implode(" AND ", $where);
|
||||
}
|
||||
|
||||
// ===========
|
||||
// Count Query
|
||||
// ===========
|
||||
|
||||
$SQL = "SELECT COUNT(*) AS totalcount FROM fwc_recreational_licenses {$whereSQL}";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
foreach ($params as $key => $value) {
|
||||
$statement->bindValue($key, $value, PDO::PARAM_STR);
|
||||
}
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$recordset = $statement->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$count = $recordset ? (int) $recordset["totalcount"] : 0;
|
||||
|
||||
// =================
|
||||
// Pagination Logic
|
||||
// =================
|
||||
|
||||
$totalPages = max(1, (int) ceil($count / $this->pagination_size));
|
||||
|
||||
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 = min($this->pagination_page + 1, $totalPages);
|
||||
break;
|
||||
|
||||
case "last":
|
||||
$this->pagination_page = $totalPages;
|
||||
break;
|
||||
|
||||
default:
|
||||
$this->pagination_page = min(max($this->pagination_page, 1), $totalPages);
|
||||
break;
|
||||
}
|
||||
|
||||
$offset = max(0, ($this->pagination_page - 1) * $this->pagination_size);
|
||||
|
||||
$start = ($count > 0) ? $offset + 1 : 0;
|
||||
$end = min($count, $offset + $this->pagination_size);
|
||||
|
||||
// ==========
|
||||
// Data Query
|
||||
// ==========
|
||||
|
||||
$SQL = " SELECT fwc_recreational_licenses.license_serial,
|
||||
fwc_recreational_licenses.license_last_name,
|
||||
fwc_recreational_licenses.license_first_name,
|
||||
fwc_recreational_licenses.license_county,
|
||||
fwc_recreational_licenses.license_city,
|
||||
fwc_recreational_licenses.license_type,
|
||||
fwc_recreational_licenses.license_gender,
|
||||
fwc_recreational_licenses.license_ethnicity,
|
||||
DATE_FORMAT(fwc_recreational_licenses.license_start_date, '%c/%e/%Y') AS license_start_date_verbose,
|
||||
DATE_FORMAT(fwc_recreational_licenses.license_expire_date, '%c/%e/%Y') AS license_expire_date_verbose
|
||||
FROM fwc_recreational_licenses
|
||||
{$whereSQL}
|
||||
ORDER BY fwc_recreational_licenses.{$licenses_order_by} {$licenses_order_direction}
|
||||
LIMIT :limit
|
||||
OFFSET :offset";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
foreach ($params as $key => $value) {
|
||||
$statement->bindValue($key, $value, PDO::PARAM_STR);
|
||||
}
|
||||
|
||||
$statement->bindValue(":limit", (int) $this->pagination_size, PDO::PARAM_INT);
|
||||
$statement->bindValue(":offset", (int) $offset, PDO::PARAM_INT);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$licenses = $this->getTableXML("licenses", $statement);
|
||||
|
||||
// ============================
|
||||
// Insert Pagination Attributes
|
||||
// ============================
|
||||
|
||||
$licenses->addAttribute("count", $count);
|
||||
$licenses->addAttribute("start", $start);
|
||||
$licenses->addAttribute("end", $end);
|
||||
$licenses->addAttribute("page", $this->pagination_page);
|
||||
$licenses->addAttribute("pages", $totalPages);
|
||||
$licenses->addAttribute("limit", $this->pagination_size);
|
||||
$licenses->addAttribute("type", "recreational");
|
||||
|
||||
$_SESSION[self::PAGINATION_PAGE] = $this->pagination_page;
|
||||
|
||||
return $licenses;
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// Return a Commercial Licenses Page Object
|
||||
// ========================================
|
||||
|
||||
public function getCommercialLicensesPage() {
|
||||
|
||||
// ===============
|
||||
// Sanitize Inputs
|
||||
// ===============
|
||||
|
||||
$commercial_license_company_or_last_name = trim(filter_input(INPUT_POST, "commercial_license_company_or_last_name") ?: "");
|
||||
$license_codes = $this->getMultiSelectInput("license_code");
|
||||
$commercial_license_number = trim(filter_input(INPUT_POST, "commercial_license_number") ?: "");
|
||||
$license_counties = $this->getMultiSelectInput("license_county");
|
||||
$commercial_license_total_tag_qty_from = filter_input(INPUT_POST, "commercial_license_total_tag_qty_from", FILTER_SANITIZE_NUMBER_INT);
|
||||
$commercial_license_total_tag_qty_to = filter_input(INPUT_POST, "commercial_license_total_tag_qty_to", FILTER_SANITIZE_NUMBER_INT);
|
||||
$commercial_license_begin_date_from = trim(filter_input(INPUT_POST, "commercial_license_begin_date_from") ?: "");
|
||||
$commercial_license_begin_date_to = trim(filter_input(INPUT_POST, "commercial_license_begin_date_to") ?: "");
|
||||
$commercial_license_expire_date_from = trim(filter_input(INPUT_POST, "commercial_license_expire_date_from") ?: "");
|
||||
$commercial_license_expire_date_to = trim(filter_input(INPUT_POST, "commercial_license_expire_date_to") ?: "");
|
||||
$pagination = trim(filter_input(INPUT_POST, "pagination") ?: "");
|
||||
|
||||
$commercial_license_total_tag_qty_from = ($commercial_license_total_tag_qty_from === null || $commercial_license_total_tag_qty_from === "") ? null : (int) $commercial_license_total_tag_qty_from;
|
||||
$commercial_license_total_tag_qty_to = ($commercial_license_total_tag_qty_to === null || $commercial_license_total_tag_qty_to === "") ? null : (int) $commercial_license_total_tag_qty_to;
|
||||
$commercial_license_begin_date_from = empty($commercial_license_begin_date_from) ? null : date("Y-m-d", strtotime($commercial_license_begin_date_from));
|
||||
$commercial_license_begin_date_to = empty($commercial_license_begin_date_to) ? null : date("Y-m-d", strtotime($commercial_license_begin_date_to));
|
||||
$commercial_license_expire_date_from = empty($commercial_license_expire_date_from) ? null : date("Y-m-d", strtotime($commercial_license_expire_date_from));
|
||||
$commercial_license_expire_date_to = empty($commercial_license_expire_date_to) ? null : date("Y-m-d", strtotime($commercial_license_expire_date_to));
|
||||
|
||||
// ===================
|
||||
// Pagination Settings
|
||||
// ===================
|
||||
|
||||
$this->pagination_page = isset($_SESSION[self::PAGINATION_PAGE]) ? (int) $_SESSION[self::PAGINATION_PAGE] : 1;
|
||||
$this->pagination_size = (int) (filter_input(INPUT_POST, "licenses_per_page", FILTER_SANITIZE_NUMBER_INT) ?: $this->pagination_size);
|
||||
|
||||
if ($this->pagination_size <= 0) {
|
||||
$this->pagination_size = 25;
|
||||
}
|
||||
|
||||
$licenses_order_by = trim(filter_input(INPUT_POST, "licenses_order_by") ?: "license_last_name");
|
||||
$licenses_order_direction = strtoupper(trim(filter_input(INPUT_POST, "licenses_order_direction") ?: "ASC"));
|
||||
|
||||
$allowed_order_columns = [
|
||||
"license_last_name" => "commercial_license_company_or_last_name",
|
||||
"license_county" => "commercial_license_county",
|
||||
"license_type" => "commercial_license_code",
|
||||
"commercial_license_number" => "commercial_license_number",
|
||||
"commercial_license_total_tag_qty" => "commercial_license_total_tag_qty",
|
||||
"license_start_date" => "commercial_license_begin_date",
|
||||
"license_expire_date" => "commercial_license_expire_date"
|
||||
];
|
||||
|
||||
if (!array_key_exists($licenses_order_by, $allowed_order_columns)) {
|
||||
$licenses_order_by = "license_last_name";
|
||||
}
|
||||
|
||||
if (!in_array($licenses_order_direction, ["ASC", "DESC"], true)) {
|
||||
$licenses_order_direction = "ASC";
|
||||
}
|
||||
|
||||
$licenses_order_column = $allowed_order_columns[$licenses_order_by];
|
||||
|
||||
// ===================
|
||||
// Connect to Database
|
||||
// ===================
|
||||
|
||||
$connection = $this->connect();
|
||||
$license_counties = $this->getDropdownValuesBySerial($connection, $license_counties);
|
||||
|
||||
// ==================
|
||||
// Build WHERE Clause
|
||||
// ==================
|
||||
|
||||
$where = [];
|
||||
$params = [];
|
||||
|
||||
if (!empty($commercial_license_company_or_last_name)) {
|
||||
$where[] = "fwc_commercial_licenses.commercial_license_company_or_last_name LIKE :commercial_license_company_or_last_name";
|
||||
$params[":commercial_license_company_or_last_name"] = $commercial_license_company_or_last_name . "%";
|
||||
}
|
||||
|
||||
if (!empty($commercial_license_number)) {
|
||||
$where[] = "fwc_commercial_licenses.commercial_license_number LIKE :commercial_license_number";
|
||||
$params[":commercial_license_number"] = "%" . $commercial_license_number . "%";
|
||||
}
|
||||
|
||||
$this->addInFilter($where, $params, "fwc_commercial_licenses.commercial_license_code", "license_code", $license_codes);
|
||||
$this->addInFilter($where, $params, "fwc_commercial_licenses.commercial_license_county", "license_county", $license_counties);
|
||||
|
||||
if ($commercial_license_total_tag_qty_from !== null) {
|
||||
$where[] = "fwc_commercial_licenses.commercial_license_total_tag_qty >= :commercial_license_total_tag_qty_from";
|
||||
$params[":commercial_license_total_tag_qty_from"] = $commercial_license_total_tag_qty_from;
|
||||
}
|
||||
|
||||
if ($commercial_license_total_tag_qty_to !== null) {
|
||||
$where[] = "fwc_commercial_licenses.commercial_license_total_tag_qty <= :commercial_license_total_tag_qty_to";
|
||||
$params[":commercial_license_total_tag_qty_to"] = $commercial_license_total_tag_qty_to;
|
||||
}
|
||||
|
||||
if (!empty($commercial_license_begin_date_from)) {
|
||||
$where[] = "fwc_commercial_licenses.commercial_license_begin_date >= :commercial_license_begin_date_from";
|
||||
$params[":commercial_license_begin_date_from"] = $commercial_license_begin_date_from;
|
||||
}
|
||||
|
||||
if (!empty($commercial_license_begin_date_to)) {
|
||||
$where[] = "fwc_commercial_licenses.commercial_license_begin_date <= :commercial_license_begin_date_to";
|
||||
$params[":commercial_license_begin_date_to"] = $commercial_license_begin_date_to;
|
||||
}
|
||||
|
||||
if (!empty($commercial_license_expire_date_from)) {
|
||||
$where[] = "fwc_commercial_licenses.commercial_license_expire_date >= :commercial_license_expire_date_from";
|
||||
$params[":commercial_license_expire_date_from"] = $commercial_license_expire_date_from;
|
||||
}
|
||||
|
||||
if (!empty($commercial_license_expire_date_to)) {
|
||||
$where[] = "fwc_commercial_licenses.commercial_license_expire_date <= :commercial_license_expire_date_to";
|
||||
$params[":commercial_license_expire_date_to"] = $commercial_license_expire_date_to;
|
||||
}
|
||||
|
||||
$whereSQL = "";
|
||||
|
||||
if (!empty($where)) {
|
||||
$whereSQL = " WHERE " . implode(" AND ", $where);
|
||||
}
|
||||
|
||||
// ===========
|
||||
// Count Query
|
||||
// ===========
|
||||
|
||||
$SQL = "SELECT COUNT(*) AS totalcount FROM fwc_commercial_licenses {$whereSQL}";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
foreach ($params as $key => $value) {
|
||||
$statement->bindValue($key, $value, is_int($value) ? PDO::PARAM_INT : PDO::PARAM_STR);
|
||||
}
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$recordset = $statement->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$count = $recordset ? (int) $recordset["totalcount"] : 0;
|
||||
|
||||
// =================
|
||||
// Pagination Logic
|
||||
// =================
|
||||
|
||||
$totalPages = max(1, (int) ceil($count / $this->pagination_size));
|
||||
|
||||
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 = min($this->pagination_page + 1, $totalPages);
|
||||
break;
|
||||
|
||||
case "last":
|
||||
$this->pagination_page = $totalPages;
|
||||
break;
|
||||
|
||||
default:
|
||||
$this->pagination_page = min(max($this->pagination_page, 1), $totalPages);
|
||||
break;
|
||||
}
|
||||
|
||||
$offset = max(0, ($this->pagination_page - 1) * $this->pagination_size);
|
||||
|
||||
$start = ($count > 0) ? $offset + 1 : 0;
|
||||
$end = min($count, $offset + $this->pagination_size);
|
||||
|
||||
// ==========
|
||||
// Data Query
|
||||
// ==========
|
||||
|
||||
$SQL = " SELECT fwc_commercial_licenses.commercial_license_serial AS license_serial,
|
||||
'' AS license_first_name,
|
||||
fwc_commercial_licenses.commercial_license_company_or_last_name AS license_last_name,
|
||||
fwc_commercial_licenses.commercial_license_county AS license_county,
|
||||
'' AS license_city,
|
||||
fwc_commercial_licenses.commercial_license_code AS license_type,
|
||||
'' AS license_gender,
|
||||
'' AS license_ethnicity,
|
||||
DATE_FORMAT(fwc_commercial_licenses.commercial_license_begin_date, '%c/%e/%Y') AS license_start_date_verbose,
|
||||
DATE_FORMAT(fwc_commercial_licenses.commercial_license_expire_date, '%c/%e/%Y') AS license_expire_date_verbose,
|
||||
fwc_commercial_licenses.commercial_license_number,
|
||||
fwc_commercial_licenses.commercial_license_total_tag_qty
|
||||
FROM fwc_commercial_licenses
|
||||
{$whereSQL}
|
||||
ORDER BY fwc_commercial_licenses.{$licenses_order_column} {$licenses_order_direction}
|
||||
LIMIT :limit
|
||||
OFFSET :offset";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
foreach ($params as $key => $value) {
|
||||
$statement->bindValue($key, $value, is_int($value) ? PDO::PARAM_INT : PDO::PARAM_STR);
|
||||
}
|
||||
|
||||
$statement->bindValue(":limit", (int) $this->pagination_size, PDO::PARAM_INT);
|
||||
$statement->bindValue(":offset", (int) $offset, PDO::PARAM_INT);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$licenses = $this->getTableXML("licenses", $statement);
|
||||
|
||||
// ============================
|
||||
// Insert Pagination Attributes
|
||||
// ============================
|
||||
|
||||
$licenses->addAttribute("count", $count);
|
||||
$licenses->addAttribute("start", $start);
|
||||
$licenses->addAttribute("end", $end);
|
||||
$licenses->addAttribute("page", $this->pagination_page);
|
||||
$licenses->addAttribute("pages", $totalPages);
|
||||
$licenses->addAttribute("limit", $this->pagination_size);
|
||||
$licenses->addAttribute("type", "commercial");
|
||||
|
||||
$_SESSION[self::PAGINATION_PAGE] = $this->pagination_page;
|
||||
|
||||
return $licenses;
|
||||
}
|
||||
|
||||
// ===============
|
||||
// Search Licenses
|
||||
// ===============
|
||||
|
||||
private function getMultiSelectInput($name) {
|
||||
|
||||
$value = $_POST[$name] ?? null;
|
||||
|
||||
if ($value === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!is_array($value)) {
|
||||
$value = explode(",", $value);
|
||||
}
|
||||
|
||||
$value = array_values(array_filter(array_map("trim", $value), function ($item) {
|
||||
return $item !== "";
|
||||
}));
|
||||
|
||||
return empty($value) ? null : $value;
|
||||
}
|
||||
|
||||
private function getDropdownValuesBySerial($connection, $serials) {
|
||||
|
||||
if (empty($serials)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$serials = array_values(array_filter(array_map("intval", $serials), function ($serial) {
|
||||
return $serial > 0;
|
||||
}));
|
||||
|
||||
if (empty($serials)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$placeholders = [];
|
||||
$params = [];
|
||||
|
||||
foreach ($serials as $index => $serial) {
|
||||
$placeholder = ":dropdown_serial_{$index}";
|
||||
$placeholders[] = $placeholder;
|
||||
$params[$placeholder] = $serial;
|
||||
}
|
||||
|
||||
$SQL = "select dropdown_value
|
||||
from dropdowns
|
||||
where dropdown_serial in (" . implode(", ", $placeholders) . ")";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
foreach ($params as $key => $value) {
|
||||
$statement->bindValue($key, $value, PDO::PARAM_INT);
|
||||
}
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$values = $statement->fetchAll(PDO::FETCH_COLUMN);
|
||||
|
||||
return empty($values) ? ["__NO_MATCHING_DROPDOWN_VALUE__"] : $values;
|
||||
}
|
||||
|
||||
private function addInFilter(&$where, &$params, $column, $name, $values) {
|
||||
|
||||
if (empty($values)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$placeholders = [];
|
||||
|
||||
foreach ($values as $index => $value) {
|
||||
$placeholder = ":{$name}_{$index}";
|
||||
$placeholders[] = $placeholder;
|
||||
$params[$placeholder] = $value;
|
||||
}
|
||||
|
||||
$where[] = "{$column} IN (" . implode(", ", $placeholders) . ")";
|
||||
}
|
||||
|
||||
// ========================
|
||||
// Return a Licenses Object
|
||||
// ========================
|
||||
|
||||
public function getSelectedLicenses($licenses = array()) {
|
||||
|
||||
if (empty($licenses)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$SQL = "select fwc_recreational_licenses.* from fwc_recreational_licenses where license_serial in ({$licenses})";
|
||||
|
||||
return $this->getTable("licenses", $SQL);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,314 @@
|
||||
<?php
|
||||
|
||||
class HistoryCodes 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;
|
||||
}
|
||||
|
||||
// ===================
|
||||
// Setup History Codes
|
||||
// ===================
|
||||
|
||||
public function setupHistoryCodes() {
|
||||
|
||||
$historycodes = $this->getHistoryCodesPage();
|
||||
$popovers = (new Popovers())->getPopovers();
|
||||
|
||||
$XML = $this->mergeXML($historycodes, "<XML/>");
|
||||
$XML = $this->mergeXML($popovers, $XML);
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("setupHistoryCodes"));
|
||||
|
||||
$this->displayContent($content);
|
||||
}
|
||||
|
||||
// ================
|
||||
// Add History Code
|
||||
// ================
|
||||
|
||||
public function addHistoryCode() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$content = $this->applyXSL("", $this->getXSL("addHistoryCode"));
|
||||
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "add":
|
||||
|
||||
$historycode_code = filter_input(INPUT_POST, "historycode_code") ?: "";
|
||||
$historycode_description = filter_input(INPUT_POST, "historycode_description") ?: "";
|
||||
|
||||
$SQL = "insert into historycodes
|
||||
|
||||
( historycode_code,
|
||||
historycode_description,
|
||||
historycode_active,
|
||||
historycode_creator,
|
||||
historycode_created )
|
||||
|
||||
VALUES ( :historycode_code,
|
||||
:historycode_description,
|
||||
:historycode_active,
|
||||
:historycode_creator,
|
||||
:historycode_created )";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":historycode_code", strtoupper($historycode_code));
|
||||
$statement->bindValue(":historycode_description", $historycode_description);
|
||||
$statement->bindValue(":historycode_active", true, PDO::PARAM_BOOL);
|
||||
$statement->bindValue(":historycode_creator", $this->current_user_name);
|
||||
$statement->bindValue(":historycode_created", $this->getTimestamp());
|
||||
|
||||
$statement->execute();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// ===================
|
||||
// Edit a History Code
|
||||
// ===================
|
||||
|
||||
public function editHistoryCode() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$historycode_serial = filter_input(INPUT_POST, "historycode_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$historycode = $this->getHistoryCode($historycode_serial);
|
||||
|
||||
if ($historycode->count() == 0) {
|
||||
$this->logError("Invalid History Code ({$historycode_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$content = $this->applyXSL($historycode, $this->getXSL("editHistoryCode"));
|
||||
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "update":
|
||||
|
||||
$historycode_serial = filter_input(INPUT_POST, "historycode_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$historycode_code = filter_input(INPUT_POST, "historycode_code") ?: "";
|
||||
$historycode_description = filter_input(INPUT_POST, "historycode_description") ?: "";
|
||||
$historycode_active = filter_input(INPUT_POST, "historycode_active", FILTER_VALIDATE_BOOLEAN) ?: false;
|
||||
|
||||
// Verify the HistoryCodes
|
||||
|
||||
$historycode = $this->getHistoryCode($historycode_serial);
|
||||
|
||||
if ($historycode->count() == 0) {
|
||||
$this->logError("Invalid HistoryCodes ({$historycode_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$SQL = "update historycodes
|
||||
set historycode_code = :historycode_code,
|
||||
historycode_description = :historycode_description,
|
||||
historycode_active = :historycode_active,
|
||||
historycode_changer = :historycode_changer,
|
||||
historycode_changed = :historycode_changed
|
||||
where historycode_serial = :historycode_serial";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":historycode_serial", $historycode_serial);
|
||||
$statement->bindValue(":historycode_code", strtoupper($historycode_code));
|
||||
$statement->bindValue(":historycode_description", $historycode_description);
|
||||
$statement->bindValue(":historycode_active", $historycode_active, PDO::PARAM_BOOL);
|
||||
$statement->bindValue(":historycode_changer", $this->current_user_name);
|
||||
$statement->bindValue(":historycode_changed", $this->getTimestamp());
|
||||
|
||||
$statement->execute();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// ===================
|
||||
// Delete History Code
|
||||
// ===================
|
||||
|
||||
public function deleteHistoryCode() {
|
||||
|
||||
$historycode_serial = filter_input(INPUT_POST, "historycode_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$historycode = $this->getHistoryCode($historycode_serial);
|
||||
|
||||
if ($historycode->count() == 0) {
|
||||
$this->logError("Invalid History Code ({$historycode_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$SQL = "delete from historycodes where historycode_serial = {$historycode_serial}";
|
||||
|
||||
$this->executeSQL($SQL);
|
||||
}
|
||||
|
||||
// =====================================
|
||||
// Return an Active History Codes Object
|
||||
// =====================================
|
||||
|
||||
public function getActiveHistoryCodes() {
|
||||
|
||||
$SQL = "select view_historycodes.*
|
||||
from view_historycodes
|
||||
where historycode_active is true";
|
||||
|
||||
return $this->getTable("historycodes", $SQL);
|
||||
}
|
||||
|
||||
// ==============================
|
||||
// Return an History Codes Object
|
||||
// ==============================
|
||||
|
||||
public function getHistoryCode($historycode_serial = 0) {
|
||||
|
||||
$SQL = "select view_historycodes.*
|
||||
from view_historycodes
|
||||
where historycode_serial = {$historycode_serial}";
|
||||
|
||||
return $this->getTable("historycodes", $SQL);
|
||||
}
|
||||
|
||||
// =============================
|
||||
// Return a History Codes Object
|
||||
// =============================
|
||||
|
||||
public function getHistoryCodes() {
|
||||
|
||||
$SQL = "select view_historycodes.*
|
||||
from view_historycodes";
|
||||
|
||||
return $this->getTable("historycodes", $SQL);
|
||||
}
|
||||
|
||||
// ==================================
|
||||
// Return a History Codes Page Object
|
||||
// ==================================
|
||||
|
||||
public function getHistoryCodesPage() {
|
||||
|
||||
// Find Criteria
|
||||
|
||||
$find_historycode = filter_input(INPUT_POST, "find_historycode") ?: "";
|
||||
$find_historycode = $this->sanitizeString($find_historycode);
|
||||
|
||||
$find_words = implode("|", explode(" ", $find_historycode));
|
||||
|
||||
// Record Count
|
||||
|
||||
$connection = $this->connect();
|
||||
|
||||
$SQL = "select count(*) as count
|
||||
from view_historycodes
|
||||
where historycode_code regexp :historycode_code
|
||||
or historycode_description regexp :historycode_description";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":historycode_code", $find_words);
|
||||
$statement->bindValue(":historycode_description", $find_words);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$recordset = $statement->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$count = (count($recordset) > 0) ? (integer) $recordset["count"] : (integer) 0;
|
||||
|
||||
// Pagination
|
||||
|
||||
$pagination = filter_input(INPUT_POST, "pagination") ?: "";
|
||||
|
||||
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 = ($count / $this->pagination_size);
|
||||
break;
|
||||
}
|
||||
|
||||
$offset = (($this->pagination_page * $this->pagination_size) - $this->pagination_size);
|
||||
$start = ($offset + 1);
|
||||
$end = min($count, (($start + $this->pagination_size) - 1));
|
||||
|
||||
// Data
|
||||
|
||||
$SQL = "select view_historycodes.*
|
||||
from view_historycodes
|
||||
where historycode_code regexp :historycode_code
|
||||
or historycode_description regexp :historycode_description
|
||||
order by historycode_code
|
||||
limit {$this->pagination_size}
|
||||
offset {$offset}";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":historycode_code", $find_words);
|
||||
$statement->bindValue(":historycode_description", $find_words);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$historycodes = $this->getTableXML("historycodes", $statement);
|
||||
|
||||
// Insert Pagination Attributes
|
||||
|
||||
$historycodes->addAttribute("count", $count);
|
||||
$historycodes->addAttribute("start", $start);
|
||||
$historycodes->addAttribute("end", $end);
|
||||
$historycodes->addAttribute("page", $this->pagination_page);
|
||||
|
||||
$_SESSION[self::PAGINATION_PAGE] = $this->pagination_page;
|
||||
|
||||
return $historycodes;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,202 @@
|
||||
<?php
|
||||
|
||||
// =============
|
||||
// Journal Class
|
||||
// =============
|
||||
|
||||
class Journal extends Base {
|
||||
|
||||
// Variables.
|
||||
|
||||
private $current_user_id = "";
|
||||
private $current_user_name = "";
|
||||
private $current_user_email = "";
|
||||
private $pagination_page = 1;
|
||||
private $pagination_size = 20;
|
||||
|
||||
// ==================
|
||||
// Class Constructor.
|
||||
// ==================
|
||||
|
||||
public function __construct() {
|
||||
|
||||
set_error_handler(array($this, "displayError"));
|
||||
|
||||
date_default_timezone_set(self::TIMEZONE);
|
||||
|
||||
$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;
|
||||
}
|
||||
|
||||
// =================
|
||||
// Clear the Journal
|
||||
// =================
|
||||
|
||||
public function clearJournal() {
|
||||
|
||||
$SQL = "truncate journal";
|
||||
|
||||
$this->executeSQL($SQL);
|
||||
|
||||
$this->journalEntry("Journal was Cleared.");
|
||||
}
|
||||
|
||||
// =======================
|
||||
// Return a Journal Object
|
||||
// =======================
|
||||
|
||||
public function getJournal($limit = 500) {
|
||||
|
||||
$SQL = "select journal.*,
|
||||
date_format(journal.journal_timestamp, '%Y-%m-%d %h:%i %p') as journal_timestamp_verbose
|
||||
from journal
|
||||
order by journal.journal_timestamp desc
|
||||
limit {$limit}";
|
||||
|
||||
return $this->getTable("journal", $SQL);
|
||||
}
|
||||
|
||||
// ============================
|
||||
// Return a Journal Page Object
|
||||
// ============================
|
||||
|
||||
public function getJournalPage() {
|
||||
|
||||
// Find Criteria
|
||||
|
||||
$find_journal = filter_input(INPUT_POST, "find_journal") ?: "";
|
||||
$find_words = $this->sanitizeString($find_journal);
|
||||
|
||||
// Show Per Page
|
||||
|
||||
$this->pagination_size = filter_input(INPUT_POST, "journals_per_page", FILTER_SANITIZE_NUMBER_INT) ?: $this->pagination_size;
|
||||
|
||||
// Record Count
|
||||
|
||||
$connection = $this->connect();
|
||||
|
||||
$SQL = "select count(*) as count
|
||||
from view_journal
|
||||
where journal_timestamp regexp :journal_timestamp
|
||||
or journal_origin regexp :journal_origin
|
||||
or journal_ip regexp :journal_ip
|
||||
or journal_entry regexp :journal_entry";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":journal_timestamp", $find_words);
|
||||
$statement->bindValue(":journal_origin", $find_words);
|
||||
$statement->bindValue(":journal_ip", $find_words);
|
||||
$statement->bindValue(":journal_entry", $find_words);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$recordset = $statement->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$count = (count($recordset) > 0) ? (integer) $recordset["count"] : (integer) 0;
|
||||
|
||||
// Pagination
|
||||
|
||||
$pagination = filter_input(INPUT_POST, "pagination") ?: "";
|
||||
|
||||
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 = ($count / $this->pagination_size);
|
||||
break;
|
||||
}
|
||||
|
||||
$offset = (($this->pagination_page * $this->pagination_size) - $this->pagination_size);
|
||||
$start = ($offset + 1);
|
||||
$end = min($count, (($start + $this->pagination_size) - 1));
|
||||
|
||||
// Data
|
||||
|
||||
$SQL = "select view_journal.*
|
||||
from view_journal
|
||||
where journal_timestamp regexp :journal_timestamp
|
||||
or journal_origin regexp :journal_origin
|
||||
or journal_ip regexp :journal_ip
|
||||
or journal_entry regexp :journal_entry
|
||||
limit {$this->pagination_size}
|
||||
offset {$offset}";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":journal_timestamp", $find_words);
|
||||
$statement->bindValue(":journal_origin", $find_words);
|
||||
$statement->bindValue(":journal_ip", $find_words);
|
||||
$statement->bindValue(":journal_entry", $find_words);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$journal = $this->getTableXML("journal", $statement);
|
||||
|
||||
// Insert Pagination Attributes
|
||||
|
||||
$journal->addAttribute("count", $count);
|
||||
$journal->addAttribute("start", $start);
|
||||
$journal->addAttribute("end", $end);
|
||||
$journal->addAttribute("page", $this->pagination_page);
|
||||
|
||||
$_SESSION[self::PAGINATION_PAGE] = $this->pagination_page;
|
||||
|
||||
return $journal;
|
||||
}
|
||||
|
||||
// ======================
|
||||
// Create a Journal Entry
|
||||
// ======================
|
||||
|
||||
public function journalEntry($journal_entry = "") {
|
||||
|
||||
if (empty($journal_entry)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$SQL = "insert into journal
|
||||
|
||||
( journal_origin,
|
||||
journal_ip,
|
||||
journal_entry )
|
||||
|
||||
VALUES ( :journal_origin,
|
||||
:journal_ip,
|
||||
:journal_entry )";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":journal_origin", $this->current_user_name);
|
||||
$statement->bindValue(":journal_ip", $_SERVER["REMOTE_ADDR"] ?? "");
|
||||
$statement->bindValue(":journal_entry", $journal_entry);
|
||||
|
||||
$statement->execute();
|
||||
}
|
||||
|
||||
// ============
|
||||
// View Journal
|
||||
// ============
|
||||
|
||||
public function viewJournal() {
|
||||
|
||||
$journal = $this->getJournalPage();
|
||||
$popovers = (new Popovers())->getPopovers();
|
||||
|
||||
$XML = $this->mergeXML($journal, "<XML/>");
|
||||
$XML = $this->mergeXML($popovers, $XML);
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("./system/viewJournal"));
|
||||
|
||||
$this->displayContent($content);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
// =============
|
||||
// Metrics Class
|
||||
// =============
|
||||
|
||||
class Metrics extends Base {
|
||||
|
||||
// ==================
|
||||
// Class Constructor.
|
||||
// ==================
|
||||
|
||||
public function __construct() {
|
||||
|
||||
set_error_handler(array($this,"displayError"));
|
||||
|
||||
date_default_timezone_set(self::TIMEZONE);
|
||||
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// Return a Daily Work Order Metrics Object
|
||||
// ========================================
|
||||
|
||||
private function getDailyWorkOrderMetrics() {
|
||||
|
||||
$SQL = "select dayname(workorder_created) as day,
|
||||
count(*) as count
|
||||
from view_workorders
|
||||
where date(workorder_created) >= (date(now()) - interval 6 day)
|
||||
group by day
|
||||
order by workorder_created desc";
|
||||
|
||||
return $this->getTable("dailymetrics", $SQL);
|
||||
|
||||
}
|
||||
|
||||
// =====================================
|
||||
// Return a Monthly Call Metrics Object.
|
||||
// =====================================
|
||||
|
||||
private function getMonthlyWorkOrderMetrics() {
|
||||
|
||||
$SQL = "select monthname(workorder_created) as month,
|
||||
count(*) as count
|
||||
from view_workorders
|
||||
where date(workorder_created) >= (date(now()) - interval 6 month)
|
||||
group by month
|
||||
order by workorder_created desc";
|
||||
|
||||
return $this->getTable("monthlymetrics", $SQL);
|
||||
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// Return a Weekly Work Order Metrics Object
|
||||
// =========================================
|
||||
|
||||
private function getWeeklyWorkOrderMetrics() {
|
||||
|
||||
$SQL = "select week(workorder_created) as week,
|
||||
count(*) as count
|
||||
from view_workorders
|
||||
where date(workorder_created) >= (date(now()) - interval 6 week)
|
||||
group by week
|
||||
order by workorder_created desc";
|
||||
|
||||
return $this->getTable("weeklymetrics", $SQL);
|
||||
|
||||
}
|
||||
|
||||
// =======================
|
||||
// View Work Order Metrics
|
||||
// =======================
|
||||
|
||||
public function viewWorkOrderMetrics() {
|
||||
|
||||
$dailymetrics = $this->getDailyWorkOrderMetrics();
|
||||
$weeklymetrics = $this->getWeeklyWorkOrderMetrics();
|
||||
$monthlymetrics = $this->getMonthlyWorkorderMetrics();
|
||||
|
||||
$XSLParms["DAILYMETRICS"] = $dailymetrics->asXML();
|
||||
$XSLParms["WEEKLYMETRICS"] = $weeklymetrics->asXML();
|
||||
$XSLParms["MONTHLYMETRICS"] = $monthlymetrics->asXML();
|
||||
|
||||
$content = $this->applyXSL("", $this->getXSL("./system/viewWorkOrderMetrics"), $XSLParms);
|
||||
|
||||
$this->displayContent($content);
|
||||
|
||||
exit();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,244 @@
|
||||
<?php
|
||||
|
||||
// ===========
|
||||
// Notes Class
|
||||
// ===========
|
||||
|
||||
class Notes extends Base {
|
||||
|
||||
// Constants
|
||||
|
||||
const VALID_TYPES = array("User");
|
||||
|
||||
// Variables
|
||||
|
||||
private $current_user_id = "";
|
||||
private $current_user_name = "";
|
||||
private $current_user_email = "";
|
||||
|
||||
// =================
|
||||
// Class Constructor
|
||||
// =================
|
||||
|
||||
public function __construct() {
|
||||
|
||||
set_error_handler(array($this, "displayError"));
|
||||
|
||||
date_default_timezone_set(self::TIMEZONE);
|
||||
|
||||
$this->current_user_id = $_SESSION[self::USER_ID] ?? "";
|
||||
$this->current_user_name = $_SESSION[self::USER_NAME] ?? "";
|
||||
$this->current_user_email = $_SESSION[self::USER_EMAIL] ?? "";
|
||||
}
|
||||
|
||||
// ========
|
||||
// Add Note
|
||||
// ========
|
||||
|
||||
public function addNote() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$note_type = filter_input(INPUT_POST, "note_type") ?: "";
|
||||
$note_reference = filter_input(INPUT_POST, "note_reference", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
if (!in_array($note_type, self::VALID_TYPES) or empty($note_reference)) {
|
||||
$this->logError("Invalid Note Type ({$note_type} or Reference {$note_reference} " . __METHOD__);
|
||||
}
|
||||
|
||||
$XSLParms["NOTE_TYPE"] = $note_type;
|
||||
$XSLParms["NOTE_REFERENCE"] = $note_reference;
|
||||
|
||||
$content = $this->applyXSL("", $this->getXSL("./system/addNote"), $XSLParms);
|
||||
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "add":
|
||||
|
||||
$note_type = filter_input(INPUT_POST, "note_type") ?: "";
|
||||
$note_reference = filter_input(INPUT_POST, "note_reference", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$note_text = filter_input(INPUT_POST, "note_text") ?: "";
|
||||
|
||||
$SQL = "insert into notes
|
||||
|
||||
( note_type,
|
||||
note_reference,
|
||||
note_text,
|
||||
note_origin )
|
||||
|
||||
VALUES ( :note_type,
|
||||
:note_reference,
|
||||
:note_text,
|
||||
:note_origin )";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":note_type", $note_type);
|
||||
$statement->bindValue(":note_reference", $note_reference);
|
||||
$statement->bindValue(":note_text", $note_text);
|
||||
$statement->bindValue(":note_origin", $this->current_user_name);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// ===========
|
||||
// Delete Note
|
||||
// ===========
|
||||
|
||||
public function deleteNote() {
|
||||
|
||||
$note_serial = filter_input(INPUT_POST, "note_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$note = $this->getNote($note_serial);
|
||||
|
||||
if ($note->count() == 0) {
|
||||
$this->logError("Invalid Note ({$note_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$SQL = "delete from notes
|
||||
where note_serial = {$note_serial}";
|
||||
|
||||
$this->executeSQL($SQL);
|
||||
}
|
||||
|
||||
// =========
|
||||
// Edit Note
|
||||
// =========
|
||||
|
||||
public function editNote() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$note_serial = filter_input(INPUT_POST, "note_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$note = $this->getNote($note_serial);
|
||||
|
||||
if ($note->count() == 0) {
|
||||
$this->logError("Invalid Note ({$note_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$XML = $this->mergeXML($note, "<XML/>");
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("./system/editNote"));
|
||||
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "update":
|
||||
|
||||
$note_serial = filter_input(INPUT_POST, "note_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$note_text = filter_input(INPUT_POST, "note_text") ?: "";
|
||||
|
||||
$SQL = "update notes
|
||||
set note_text = :note_text,
|
||||
note_origin = :note_origin
|
||||
where note_serial = :note_serial";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":note_serial", $note_serial);
|
||||
$statement->bindValue(":note_text", $note_text);
|
||||
$statement->bindValue(":note_origin", $this->current_user_name);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// ====================
|
||||
// Return a Note Object
|
||||
// ====================
|
||||
|
||||
public function getNote($note_serial = 0) {
|
||||
|
||||
$SQL = "select view_notes.*
|
||||
from view_notes
|
||||
where note_serial = {$note_serial}";
|
||||
|
||||
return $this->getTable("notes", $SQL);
|
||||
}
|
||||
|
||||
// =====================
|
||||
// Return a Notes Object
|
||||
// =====================
|
||||
|
||||
public function getNotes($note_type = "", $note_reference = 0) {
|
||||
|
||||
$SQL = "select view_notes.*
|
||||
from view_notes
|
||||
where note_type = '{$note_type}'
|
||||
and note_reference = {$note_reference}
|
||||
order by note_timestamp asc";
|
||||
|
||||
return $this->getTable("notes", $SQL);
|
||||
}
|
||||
|
||||
// =====================
|
||||
// Return a Notes Object
|
||||
// =====================
|
||||
|
||||
public function getAllNotes($note_reference = 0) {
|
||||
|
||||
$SQL = "select view_notes.*
|
||||
from view_notes
|
||||
where note_reference = {$note_reference}
|
||||
order by note_timestamp asc";
|
||||
|
||||
// $this->debug($SQL);
|
||||
|
||||
return $this->getTable("notes", $SQL);
|
||||
}
|
||||
|
||||
// ==============
|
||||
// Add Note Quick
|
||||
// ==============
|
||||
|
||||
public function addNoteQuick($note_type = "", $note_reference = 0, $note_text = "") {
|
||||
|
||||
$SQL = "insert into notes
|
||||
|
||||
( note_type,
|
||||
note_reference,
|
||||
note_text,
|
||||
note_origin )
|
||||
|
||||
VALUES ( :note_type,
|
||||
:note_reference,
|
||||
:note_text,
|
||||
:note_origin )";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":note_type", $note_type);
|
||||
$statement->bindValue(":note_reference", $note_reference);
|
||||
$statement->bindValue(":note_text", $note_text);
|
||||
$statement->bindValue(":note_origin", $this->current_user_name);
|
||||
|
||||
$statement->execute();
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,314 @@
|
||||
<?php
|
||||
|
||||
class PoliticalParties 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;
|
||||
}
|
||||
|
||||
// =======================
|
||||
// Setup Political Parties
|
||||
// =======================
|
||||
|
||||
public function setupPoliticalParties() {
|
||||
|
||||
$politicalparties = $this->getPoliticalPartiesPage();
|
||||
$popovers = (new Popovers())->getPopovers();
|
||||
|
||||
$XML = $this->mergeXML($politicalparties, "<XML/>");
|
||||
$XML = $this->mergeXML($popovers, $XML);
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("setupPoliticalParties"));
|
||||
|
||||
$this->displayContent($content);
|
||||
}
|
||||
|
||||
// ===================
|
||||
// Add Political Party
|
||||
// ===================
|
||||
|
||||
public function addPoliticalParty() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$content = $this->applyXSL("", $this->getXSL("addPoliticalParty"));
|
||||
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "add":
|
||||
|
||||
$politicalparty_code = filter_input(INPUT_POST, "politicalparty_code") ?: "";
|
||||
$politicalparty_name = filter_input(INPUT_POST, "politicalparty_name") ?: "";
|
||||
|
||||
$SQL = "insert into politicalparties
|
||||
|
||||
( politicalparty_code,
|
||||
politicalparty_name,
|
||||
politicalparty_active,
|
||||
politicalparty_creator,
|
||||
politicalparty_created )
|
||||
|
||||
VALUES ( :politicalparty_code,
|
||||
:politicalparty_name,
|
||||
:politicalparty_active,
|
||||
:politicalparty_creator,
|
||||
:politicalparty_created )";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":politicalparty_code", strtoupper($politicalparty_code));
|
||||
$statement->bindValue(":politicalparty_name", $politicalparty_name);
|
||||
$statement->bindValue(":politicalparty_active", true, PDO::PARAM_BOOL);
|
||||
$statement->bindValue(":politicalparty_creator", $this->current_user_name);
|
||||
$statement->bindValue(":politicalparty_created", $this->getTimestamp());
|
||||
|
||||
$statement->execute();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// ======================
|
||||
// Edit a Political Party
|
||||
// ======================
|
||||
|
||||
public function editPoliticalParty() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$politicalparty_serial = filter_input(INPUT_POST, "politicalparty_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$politicalparty = $this->getPoliticalParty($politicalparty_serial);
|
||||
|
||||
if ($politicalparty->count() == 0) {
|
||||
$this->logError("Invalid Political Party ({$politicalparty_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$content = $this->applyXSL($politicalparty, $this->getXSL("editPoliticalParty"));
|
||||
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "update":
|
||||
|
||||
$politicalparty_serial = filter_input(INPUT_POST, "politicalparty_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$politicalparty_code = filter_input(INPUT_POST, "politicalparty_code") ?: "";
|
||||
$politicalparty_name = filter_input(INPUT_POST, "politicalparty_name") ?: "";
|
||||
$politicalparty_active = filter_input(INPUT_POST, "politicalparty_active", FILTER_VALIDATE_BOOLEAN) ?: false;
|
||||
|
||||
// Verify the PoliticalParties
|
||||
|
||||
$politicalparty = $this->getPoliticalParty($politicalparty_serial);
|
||||
|
||||
if ($politicalparty->count() == 0) {
|
||||
$this->logError("Invalid PoliticalParties ({$politicalparty_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$SQL = "update politicalparties
|
||||
set politicalparty_code = :politicalparty_code,
|
||||
politicalparty_name = :politicalparty_name,
|
||||
politicalparty_active = :politicalparty_active,
|
||||
politicalparty_changer = :politicalparty_changer,
|
||||
politicalparty_changed = :politicalparty_changed
|
||||
where politicalparty_serial = :politicalparty_serial";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":politicalparty_serial", $politicalparty_serial);
|
||||
$statement->bindValue(":politicalparty_code", strtoupper($politicalparty_code));
|
||||
$statement->bindValue(":politicalparty_name", $politicalparty_name);
|
||||
$statement->bindValue(":politicalparty_active", $politicalparty_active, PDO::PARAM_BOOL);
|
||||
$statement->bindValue(":politicalparty_changer", $this->current_user_name);
|
||||
$statement->bindValue(":politicalparty_changed", $this->getTimestamp());
|
||||
|
||||
$statement->execute();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// ======================
|
||||
// Delete Political Party
|
||||
// ======================
|
||||
|
||||
public function deletePoliticalParty() {
|
||||
|
||||
$politicalparty_serial = filter_input(INPUT_POST, "politicalparty_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$politicalparty = $this->getPoliticalParty($politicalparty_serial);
|
||||
|
||||
if ($politicalparty->count() == 0) {
|
||||
$this->logError("Invalid Political Party ({$politicalparty_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$SQL = "delete from politicalparties where politicalparty_serial = {$politicalparty_serial}";
|
||||
|
||||
$this->executeSQL($SQL);
|
||||
}
|
||||
|
||||
// =======================================
|
||||
// Return an Active Political Party Object
|
||||
// =======================================
|
||||
|
||||
public function getActivePoliticalParties() {
|
||||
|
||||
$SQL = "select view_politicalparties.*
|
||||
from view_politicalparties
|
||||
where politicalparty_active is true";
|
||||
|
||||
return $this->getTable("politicalparties", $SQL);
|
||||
}
|
||||
|
||||
// ================================
|
||||
// Return an Political Party Object
|
||||
// ================================
|
||||
|
||||
public function getPoliticalParty($politicalparty_serial = 0) {
|
||||
|
||||
$SQL = "select view_politicalparties.*
|
||||
from view_politicalparties
|
||||
where politicalparty_serial = {$politicalparty_serial}";
|
||||
|
||||
return $this->getTable("politicalparties", $SQL);
|
||||
}
|
||||
|
||||
// ===============================
|
||||
// Return a Political Party Object
|
||||
// ===============================
|
||||
|
||||
public function getPoliticalParties() {
|
||||
|
||||
$SQL = "select view_politicalparties.*
|
||||
from view_politicalparties";
|
||||
|
||||
return $this->getTable("politicalparties", $SQL);
|
||||
}
|
||||
|
||||
// =====================================
|
||||
// Return a Political Partys Page Object
|
||||
// =====================================
|
||||
|
||||
public function getPoliticalPartiesPage() {
|
||||
|
||||
// Find Criteria
|
||||
|
||||
$find_politicalparty = filter_input(INPUT_POST, "find_politicalparty") ?: "";
|
||||
$find_politicalparty = $this->sanitizeString($find_politicalparty);
|
||||
|
||||
$find_words = implode("|", explode(" ", $find_politicalparty));
|
||||
|
||||
// Record Count
|
||||
|
||||
$connection = $this->connect();
|
||||
|
||||
$SQL = "select count(*) as count
|
||||
from view_politicalparties
|
||||
where politicalparty_code regexp :politicalparty_code
|
||||
or politicalparty_name regexp :politicalparty_name";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":politicalparty_code", $find_words);
|
||||
$statement->bindValue(":politicalparty_name", $find_words);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$recordset = $statement->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$count = (count($recordset) > 0) ? (integer) $recordset["count"] : (integer) 0;
|
||||
|
||||
// Pagination
|
||||
|
||||
$pagination = filter_input(INPUT_POST, "pagination") ?: "";
|
||||
|
||||
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 = ($count / $this->pagination_size);
|
||||
break;
|
||||
}
|
||||
|
||||
$offset = (($this->pagination_page * $this->pagination_size) - $this->pagination_size);
|
||||
$start = ($offset + 1);
|
||||
$end = min($count, (($start + $this->pagination_size) - 1));
|
||||
|
||||
// Data
|
||||
|
||||
$SQL = "select view_politicalparties.*
|
||||
from view_politicalparties
|
||||
where politicalparty_code regexp :politicalparty_code
|
||||
or politicalparty_name regexp :politicalparty_name
|
||||
order by politicalparty_code
|
||||
limit {$this->pagination_size}
|
||||
offset {$offset}";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":politicalparty_code", $find_words);
|
||||
$statement->bindValue(":politicalparty_name", $find_words);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$politicalparties = $this->getTableXML("politicalparties", $statement);
|
||||
|
||||
// Insert Pagination Attributes
|
||||
|
||||
$politicalparties->addAttribute("count", $count);
|
||||
$politicalparties->addAttribute("start", $start);
|
||||
$politicalparties->addAttribute("end", $end);
|
||||
$politicalparties->addAttribute("page", $this->pagination_page);
|
||||
|
||||
$_SESSION[self::PAGINATION_PAGE] = $this->pagination_page;
|
||||
|
||||
return $politicalparties;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,352 @@
|
||||
<?php
|
||||
|
||||
// ==============
|
||||
// Popovers Class
|
||||
// ==============
|
||||
|
||||
class Popovers extends Base {
|
||||
|
||||
// Variables.
|
||||
|
||||
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_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;
|
||||
}
|
||||
|
||||
// ===========
|
||||
// Add Popover
|
||||
// ===========
|
||||
|
||||
public function addPopover() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$content = $this->applyXSL("", $this->getXSL("./system/addPopover"));
|
||||
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "add":
|
||||
|
||||
$popover_name = filter_input(INPUT_POST, "popover_name") ?: "";
|
||||
$popover_title = filter_input(INPUT_POST, "popover_title") ?: "";
|
||||
$popover_placeholder = filter_input(INPUT_POST, "popover_placeholder") ?: "";
|
||||
$popover_text = filter_input(INPUT_POST, "popover_text") ?: "";
|
||||
|
||||
$SQL = "insert into popovers
|
||||
|
||||
( popover_name,
|
||||
popover_title,
|
||||
popover_placeholder,
|
||||
popover_text,
|
||||
popover_creator,
|
||||
popover_created )
|
||||
|
||||
VALUES ( :popover_name,
|
||||
:popover_title,
|
||||
:popover_placeholder,
|
||||
:popover_text,
|
||||
:popover_creator,
|
||||
:popover_created)";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":popover_name", $popover_name);
|
||||
$statement->bindValue(":popover_title", $popover_title);
|
||||
$statement->bindValue(":popover_placeholder", $popover_placeholder);
|
||||
$statement->bindValue(":popover_text", $popover_text);
|
||||
$statement->bindValue(":popover_creator", $this->current_user_name);
|
||||
$statement->bindValue(":popover_created", $this->getTimestamp());
|
||||
|
||||
$statement->execute();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// ==============
|
||||
// Delete Popover
|
||||
// ==============
|
||||
|
||||
public function deletePopover() {
|
||||
|
||||
$popover_serial = filter_input(INPUT_POST, "popover_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$popover = $this->getPopover($popover_serial);
|
||||
|
||||
if ($popover->count() == 0) {
|
||||
$this->logError("Invalid Popover ({$popover_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$SQL = "delete from popovers
|
||||
where popover_serial = {$popover_serial}";
|
||||
|
||||
$this->executeSQL($SQL);
|
||||
}
|
||||
|
||||
// ============
|
||||
// Edit Popover
|
||||
// ============
|
||||
|
||||
public function editPopover() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$popover_serial = filter_input(INPUT_POST, "popover_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$popover = $this->getPopover($popover_serial);
|
||||
|
||||
if ($popover->count() == 0) {
|
||||
$this->logError("Invalid Popover ({$popover_serial}): " . __METHOD__);
|
||||
}
|
||||
|
||||
$XML = $this->mergeXML($popover, "<XML/>");
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("./system/editPopover"));
|
||||
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "update":
|
||||
|
||||
$popover_serial = filter_input(INPUT_POST, "popover_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$popover_name = filter_input(INPUT_POST, "popover_name") ?: "";
|
||||
$popover_title = filter_input(INPUT_POST, "popover_title") ?: "";
|
||||
$popover_placeholder = filter_input(INPUT_POST, "popover_placeholder") ?: "";
|
||||
$popover_text = filter_input(INPUT_POST, "popover_text") ?: "";
|
||||
|
||||
$popover = $this->getPopover($popover_serial);
|
||||
|
||||
if ($popover->count() == 0) {
|
||||
$this->logError("Invalid Popover ({$popover_serial}): " . __METHOD__);
|
||||
}
|
||||
|
||||
$SQL = "update popovers
|
||||
set popover_name = :popover_name,
|
||||
popover_title = :popover_title,
|
||||
popover_placeholder = :popover_placeholder,
|
||||
popover_text = :popover_text,
|
||||
popover_changer = :popover_changer,
|
||||
popover_changed = :popover_changed
|
||||
where popover_serial = :popover_serial";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":popover_serial", $popover_serial);
|
||||
$statement->bindValue(":popover_name", $popover_name);
|
||||
$statement->bindValue(":popover_title", $popover_title);
|
||||
$statement->bindValue(":popover_placeholder", $popover_placeholder);
|
||||
$statement->bindValue(":popover_text", $popover_text);
|
||||
$statement->bindValue(":popover_changer", $this->current_user_name);
|
||||
$statement->bindValue(":popover_changed", $this->getTimestamp());
|
||||
|
||||
$statement->execute();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// =======================
|
||||
// Return a Popover Object
|
||||
// =======================
|
||||
|
||||
public function getPopover($popover_serial = 0) {
|
||||
|
||||
$SQL = "select view_popovers.*
|
||||
from view_popovers
|
||||
where popover_serial = {$popover_serial}";
|
||||
|
||||
return $this->getTable("popovers", $SQL);
|
||||
}
|
||||
|
||||
// =======================
|
||||
// Return a Popover Object
|
||||
// =======================
|
||||
|
||||
public function getPopoverByName($popover_name = "") {
|
||||
|
||||
$SQL = "select view_popovers.*
|
||||
from view_popovers
|
||||
where popover_name = '{$popover_name}'";
|
||||
|
||||
return $this->getTable("popovers", $SQL);
|
||||
}
|
||||
|
||||
// ========================
|
||||
// Return a Popovers Object
|
||||
// ========================
|
||||
|
||||
public function getPopovers() {
|
||||
|
||||
$SQL = "select view_popovers.*
|
||||
from view_popovers";
|
||||
|
||||
return $this->getTable("popovers", $SQL);
|
||||
}
|
||||
|
||||
// =============================
|
||||
// Return a Popovers Page Object
|
||||
// =============================
|
||||
|
||||
public function getPopoversPage() {
|
||||
|
||||
// Find Criteria
|
||||
|
||||
$find_popover = filter_input(INPUT_POST, "find_popover") ?: "";
|
||||
$find_words = $this->sanitizeString($find_popover);
|
||||
|
||||
// Show Per Page
|
||||
|
||||
$this->pagination_size = filter_input(INPUT_POST, "popovers_per_page", FILTER_SANITIZE_NUMBER_INT) ?: $this->pagination_size;
|
||||
|
||||
// Record Count
|
||||
|
||||
$connection = $this->connect();
|
||||
|
||||
$SQL = "select count(*) as count
|
||||
from view_popovers
|
||||
where popover_name regexp :popover_name
|
||||
or popover_title regexp :popover_title";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":popover_name", $find_words);
|
||||
$statement->bindValue(":popover_title", $find_words);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$recordset = $statement->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$count = (count($recordset) > 0) ? (integer) $recordset["count"] : (integer) 0;
|
||||
|
||||
// Pagination
|
||||
|
||||
$pagination = filter_input(INPUT_POST, "pagination") ?: "";
|
||||
|
||||
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 = ($count / $this->pagination_size);
|
||||
break;
|
||||
}
|
||||
|
||||
$offset = (($this->pagination_page * $this->pagination_size) - $this->pagination_size);
|
||||
$start = ($offset + 1);
|
||||
$end = min($count, (($start + $this->pagination_size) - 1));
|
||||
|
||||
// Data
|
||||
|
||||
$SQL = "select view_popovers.*
|
||||
from view_popovers
|
||||
where popover_name regexp :popover_name
|
||||
or popover_title regexp :popover_title
|
||||
limit {$this->pagination_size}
|
||||
offset {$offset}";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":popover_name", $find_words);
|
||||
$statement->bindValue(":popover_title", $find_words);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$popovers = $this->getTableXML("popovers", $statement);
|
||||
|
||||
// Insert Pagination Attributes
|
||||
|
||||
$popovers->addAttribute("count", $count);
|
||||
$popovers->addAttribute("start", $start);
|
||||
$popovers->addAttribute("end", $end);
|
||||
$popovers->addAttribute("page", $this->pagination_page);
|
||||
|
||||
$_SESSION[self::PAGINATION_PAGE] = $this->pagination_page;
|
||||
|
||||
return $popovers;
|
||||
}
|
||||
|
||||
// =============================
|
||||
// Determine if a Popover exists
|
||||
// =============================
|
||||
|
||||
public function popoverExists() {
|
||||
|
||||
$popover_serial = filter_input(INPUT_POST, "popover_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$popover_name = filter_input(INPUT_POST, "popover_name") ?: "";
|
||||
|
||||
$popover_name = strtolower($popover_name);
|
||||
|
||||
$SQL = "select popover_serial
|
||||
from view_popovers
|
||||
where popover_serial != :popover_serial
|
||||
and lower(popover_name) = :popover_name";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":popover_serial", $popover_serial);
|
||||
$statement->bindValue(":popover_name", $popover_name);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$popovers = $statement->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$exists = (count($popovers) > 0) ? true : false;
|
||||
|
||||
echo json_encode($exists);
|
||||
}
|
||||
|
||||
// ==============
|
||||
// Setup Popovers
|
||||
// ==============
|
||||
|
||||
public function setupPopovers() {
|
||||
|
||||
$popovers = $this->getPopoversPage();
|
||||
$XML = $this->mergeXML($popovers, "<XML/>");
|
||||
$content = $this->applyXSL($XML, $this->getXSL("./system/setupPopovers"));
|
||||
|
||||
$this->displayContent($content);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,784 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
$basePath = realpath(__DIR__ . '/..');
|
||||
require_once $basePath . '/vendor/autoload.php';
|
||||
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
||||
|
||||
// =====================
|
||||
// Process_ExportRequest
|
||||
// =====================
|
||||
|
||||
class Process_ExportRequest {
|
||||
|
||||
// Variables
|
||||
|
||||
private $log = "";
|
||||
private $settings = "";
|
||||
private $connection = "";
|
||||
|
||||
// ==================
|
||||
// Class Constructor.
|
||||
// ==================
|
||||
|
||||
public function __construct() {
|
||||
|
||||
$basePath = realpath(__DIR__ . '/..');
|
||||
$logfile = $basePath . "/scripts/exportrequests.log";
|
||||
|
||||
// ==========================
|
||||
// Log Rotation (50 MB limit)
|
||||
// ==========================
|
||||
|
||||
$maxLogSize = 50 * 1024 * 1024; // 50 MB
|
||||
|
||||
if (file_exists($logfile) && filesize($logfile) >= $maxLogSize) {
|
||||
|
||||
$rotated = $logfile . '-';
|
||||
rename($logfile, $rotated);
|
||||
}
|
||||
|
||||
$this->log = fopen($logfile, "a");
|
||||
|
||||
if ($this->log === false) {
|
||||
|
||||
error_log("Process_ExportRequest : Unable to open log file");
|
||||
exit();
|
||||
}
|
||||
|
||||
$this->log(str_repeat("*", 50));
|
||||
|
||||
// Get Settings
|
||||
|
||||
$this->settings = new SimpleXMLElement((file_exists($basePath . "/xml/settings.xml") ? file_get_contents($basePath . "/xml/settings.xml") : "<settings/>"));
|
||||
|
||||
if ($this->settings->count() === 0) {
|
||||
|
||||
error_log("Process_ExportRequest : Unable to initialize settings");
|
||||
exit();
|
||||
}
|
||||
|
||||
// Open Database Connections
|
||||
|
||||
$this->connection = $this->connect();
|
||||
}
|
||||
|
||||
// ==============================================
|
||||
// Return a VoterVue Database Database Connection
|
||||
// ==============================================
|
||||
|
||||
public function connect() {
|
||||
|
||||
if ($this->settings->Environment == 'Production') {
|
||||
$host = 'localhost';
|
||||
} else {
|
||||
$host = '192.168.1.190';
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
$database = (string) $this->settings->DatabaseName;
|
||||
$user = (string) $this->settings->DatabaseUser;
|
||||
$password = (string) $this->settings->DatabasePassword;
|
||||
|
||||
$connection = new PDO("mysql:host={$host};dbname={$database};charset=utf8", $user, $password);
|
||||
|
||||
$connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
|
||||
$connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
} catch (PDOException | Exception $e) {
|
||||
|
||||
trigger_error($e->getMessage());
|
||||
}
|
||||
|
||||
return $connection;
|
||||
}
|
||||
|
||||
// =============================
|
||||
// Log a message to the Log File
|
||||
// =============================
|
||||
|
||||
private function log($message = "") {
|
||||
|
||||
fwrite($this->log, date("Y-m-d H:i A") . " : " . "{$message} \n");
|
||||
}
|
||||
|
||||
// ===================
|
||||
// Process Parcel Data
|
||||
// ===================
|
||||
|
||||
public function process() {
|
||||
|
||||
$this->log("Starting Searched Record Export Job");
|
||||
|
||||
$this->runExportJob();
|
||||
|
||||
$this->purgeExportJobs();
|
||||
|
||||
$this->log("Completed Searched Record Export Job");
|
||||
}
|
||||
|
||||
// ==============
|
||||
// Run Export Job
|
||||
// ==============
|
||||
|
||||
private function runExportJob() {
|
||||
|
||||
$this->log("Processing Export Job");
|
||||
|
||||
$nextjob = $this->claimNextJob();
|
||||
|
||||
if (!$nextjob) {
|
||||
$this->log("Nothing to do.");
|
||||
return;
|
||||
}
|
||||
|
||||
$exportjob_serial = (int) $nextjob['exportjob_serial'];
|
||||
$exportjob_license_type = (string) $nextjob['exportjob_license_type'];
|
||||
$exportjob_searchcriteria = (string) $nextjob['exportjob_searchcriteria'];
|
||||
$exportjob_file_name = (string) $nextjob['exportjob_file_name'];
|
||||
$exportjob_file_type = (string) $nextjob['exportjob_file_type'];
|
||||
|
||||
try {
|
||||
|
||||
switch ($exportjob_license_type) {
|
||||
|
||||
case "recreational":
|
||||
|
||||
$recreational_licenses = $this->getRecreationalLicenses($exportjob_searchcriteria);
|
||||
$export_file = $this->createExportFile($exportjob_file_name, $exportjob_file_type, $recreational_licenses, $exportjob_license_type);
|
||||
|
||||
break;
|
||||
|
||||
case "commercial":
|
||||
|
||||
// $comm_licenses = $this->getPZFactsFullDataset($user_subscription_start_date, $user_subscription_end_date, $counties);
|
||||
// $result = $this->generatePZFactsExportFile($exportjob_file_name, $exportjob_file_type, $pzfacts, $subscription);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
$exportjob_download_token = hash('sha256', random_bytes(32));
|
||||
|
||||
$SQL = "UPDATE exportjobs
|
||||
SET exportjob_status = 'complete',
|
||||
exportjob_completed = NOW(),
|
||||
exportjob_file_path = :exportjob_file_path,
|
||||
exportjob_file_type = :exportjob_file_type,
|
||||
exportjob_download_token = :exportjob_download_token
|
||||
WHERE exportjob_serial = :exportjob_serial ";
|
||||
|
||||
$update = $this->connect()->prepare($SQL);
|
||||
|
||||
$update->execute([':exportjob_file_path' => $export_file['exportjob_file_path'], ":exportjob_download_token" => $exportjob_download_token,
|
||||
':exportjob_serial' => $exportjob_serial, ':exportjob_file_type' => $export_file['exportjob_file_type']]);
|
||||
} catch (Throwable $e) {
|
||||
|
||||
$SQL = "UPDATE exportjobs
|
||||
SET exportjob_status = 'failed',
|
||||
exportjob_completed = NOW(),
|
||||
exportjob_error_message = :exportjob_error_message
|
||||
WHERE exportjob_serial = :exportjob_serial";
|
||||
|
||||
$fail = $this->connect()->prepare($SQL);
|
||||
|
||||
$fail->execute([':exportjob_serial' => $exportjob_serial, ':exportjob_error_message' => $e->getMessage()]);
|
||||
|
||||
// Notify Admins of error
|
||||
$this->sendWebHookAlert("Export Job {$exportjob_serial} has failed. Check Error Logs for details.");
|
||||
$this->email_admins("Export Job Failure.", "Export Job {$exportjob_serial} has failed. Check Error Logs for details.");
|
||||
}
|
||||
}
|
||||
|
||||
// =================================
|
||||
// Purge Exports Older then 24 Hours
|
||||
// =================================
|
||||
|
||||
private function purgeExportJobs() {
|
||||
|
||||
$this->log("Purging Export Jobs Database Files");
|
||||
|
||||
$this->purgeFiles();
|
||||
}
|
||||
|
||||
// =======================
|
||||
// Claim Next Job in Queue
|
||||
// =======================
|
||||
|
||||
private function claimNextJob() {
|
||||
|
||||
$this->connection->beginTransaction();
|
||||
|
||||
$SQL = "SELECT view_exportjobs.*
|
||||
FROM view_exportjobs
|
||||
WHERE view_exportjobs.exportjob_status = 'queued'
|
||||
ORDER BY view_exportjobs.exportjob_created ASC
|
||||
LIMIT 1 FOR UPDATE";
|
||||
|
||||
$statement = $this->connection->prepare($SQL);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$job = $statement->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$job) {
|
||||
$this->connection->commit();
|
||||
return null;
|
||||
}
|
||||
|
||||
$SQL = "UPDATE exportjobs
|
||||
SET exportjob_status = 'running'
|
||||
WHERE exportjob_serial = :exportjob_serial";
|
||||
|
||||
$statement = $this->connection->prepare($SQL);
|
||||
|
||||
$statement->execute([':exportjob_serial' => (int) $job['exportjob_serial']]);
|
||||
|
||||
$this->connection->commit();
|
||||
|
||||
return $job;
|
||||
}
|
||||
|
||||
// ==================================
|
||||
// Return a Users Subscription Object
|
||||
// ==================================
|
||||
|
||||
private function getUserSubscription($subscription, $user) {
|
||||
|
||||
$SQL = "select view_usersubscriptions.*
|
||||
from view_usersubscriptions
|
||||
where view_usersubscriptions.usersubscription_user = {$user}
|
||||
and view_usersubscriptions.usersubscription_subscription = {$subscription}";
|
||||
|
||||
$usersubscription = $this->connect()->query($SQL)->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
return $usersubscription;
|
||||
}
|
||||
|
||||
// ============================
|
||||
// Return a Subscription Object
|
||||
// ============================
|
||||
|
||||
private function getSubscription($subscription) {
|
||||
|
||||
$SQL = "select view_subscriptions.*
|
||||
from view_subscriptions
|
||||
where subscription_serial = {$subscription}";
|
||||
|
||||
$subscription = $this->connect()->query($SQL)->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
return $subscription;
|
||||
}
|
||||
|
||||
// ================================
|
||||
// Get Recreational License Dataset
|
||||
// ================================
|
||||
|
||||
private function getRecreationalLicenses($search_criteria) {
|
||||
|
||||
set_time_limit(0);
|
||||
|
||||
$criteria = json_decode($search_criteria, true);
|
||||
|
||||
if (!is_array($criteria)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$connection = $this->connect();
|
||||
|
||||
// -------------------------------------------------
|
||||
// Convert county serials to county text values
|
||||
// -------------------------------------------------
|
||||
|
||||
if (!empty($criteria['license_county'])) {
|
||||
|
||||
$countySerials = array_filter(array_map('trim', explode(',', $criteria['license_county'])));
|
||||
|
||||
if (!empty($countySerials)) {
|
||||
|
||||
$placeholders = [];
|
||||
|
||||
foreach ($countySerials as $index => $serial) {
|
||||
$placeholders[] = ":county{$index}";
|
||||
}
|
||||
|
||||
$SQL = "select dropdown_value
|
||||
from dropdowns
|
||||
where dropdown_serial in (" . implode(',', $placeholders) . ")";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
foreach ($countySerials as $index => $serial) {
|
||||
$statement->bindValue(":county{$index}", $serial, PDO::PARAM_INT);
|
||||
}
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$criteria['license_county'] = $statement->fetchAll(PDO::FETCH_COLUMN);
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
// Convert ethnicity serials to ethnicity text values
|
||||
// --------------------------------------------------
|
||||
|
||||
if (!empty($criteria['license_ethnicity'])) {
|
||||
|
||||
$ethnicitySerials = array_filter(array_map('trim', explode(',', $criteria['license_ethnicity'])));
|
||||
|
||||
if (!empty($ethnicitySerials)) {
|
||||
|
||||
$placeholders = [];
|
||||
|
||||
foreach ($ethnicitySerials as $index => $serial) {
|
||||
$placeholders[] = ":ethnicity{$index}";
|
||||
}
|
||||
|
||||
$SQL = "select dropdown_value
|
||||
from dropdowns
|
||||
where dropdown_serial in (" . implode(',', $placeholders) . ")";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
foreach ($ethnicitySerials as $index => $serial) {
|
||||
$statement->bindValue(":ethnicity{$index}", $serial, PDO::PARAM_INT);
|
||||
}
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$criteria['license_ethnicity'] = $statement->fetchAll(PDO::FETCH_COLUMN);
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------
|
||||
// Build recreational license query
|
||||
// --------------------------------
|
||||
|
||||
$allowedColumns = [
|
||||
'license_last_name',
|
||||
'license_first_name',
|
||||
'license_county',
|
||||
'license_city',
|
||||
'license_type',
|
||||
'license_gender',
|
||||
'license_ethnicity',
|
||||
'license_start_date',
|
||||
'license_expire_date'
|
||||
];
|
||||
|
||||
$where = [];
|
||||
$params = [];
|
||||
|
||||
foreach ($criteria as $key => $value) {
|
||||
|
||||
if (!in_array($key, $allowedColumns, true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_array($value)) {
|
||||
|
||||
if (empty($value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$placeholders = [];
|
||||
|
||||
foreach ($value as $index => $item) {
|
||||
$param = ":" . $key . "_" . $index;
|
||||
$placeholders[] = $param;
|
||||
$params[$param] = $item;
|
||||
}
|
||||
|
||||
$where[] = "{$key} in (" . implode(',', $placeholders) . ")";
|
||||
} else {
|
||||
|
||||
$value = trim($value);
|
||||
|
||||
if ($value === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strpos($value, ',') !== false) {
|
||||
|
||||
$items = array_filter(array_map('trim', explode(',', $value)));
|
||||
$placeholders = [];
|
||||
|
||||
foreach ($items as $index => $item) {
|
||||
$param = ":" . $key . "_" . $index;
|
||||
$placeholders[] = $param;
|
||||
$params[$param] = $item;
|
||||
}
|
||||
|
||||
$where[] = "{$key} in (" . implode(',', $placeholders) . ")";
|
||||
} elseif ($key === 'license_start_date') {
|
||||
|
||||
$where[] = "{$key} >= :{$key}";
|
||||
$params[":{$key}"] = date('Y-m-d', strtotime($value));
|
||||
} elseif ($key === 'license_expire_date') {
|
||||
|
||||
$where[] = "{$key} <= :{$key}";
|
||||
$params[":{$key}"] = date('Y-m-d', strtotime($value));
|
||||
} else {
|
||||
|
||||
$where[] = "{$key} like :{$key}";
|
||||
$params[":{$key}"] = '%' . $value . '%';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$SQL = "select fwc_recreational_licenses.*
|
||||
from fwc_recreational_licenses";
|
||||
|
||||
if (!empty($where)) {
|
||||
$SQL .= " where " . implode(" and ", $where);
|
||||
}
|
||||
|
||||
$SQL .= " order by license_last_name, license_first_name";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
foreach ($params as $param => $value) {
|
||||
$statement->bindValue($param, $value);
|
||||
}
|
||||
|
||||
$statement->execute();
|
||||
|
||||
return $statement->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
// ======================================
|
||||
// Get Planning/Zoning Facts Full Dataset
|
||||
// ======================================
|
||||
|
||||
private function getPZFactsFullDataset($user_subscription_start_date, $user_subscription_end_date, $counties) {
|
||||
|
||||
set_time_limit(0);
|
||||
|
||||
// determine real date range based upon users subscription start date
|
||||
|
||||
if ($user_subscription_start_date <= date('Y-m-d', strtotime('-1 year'))) {
|
||||
$user_subscription_start_date = date('Y-m-d', strtotime('-1 year'));
|
||||
}
|
||||
|
||||
$SQL = "select view_pzfacts.*
|
||||
from view_pzfacts
|
||||
where view_pzfacts.pzfact_entry_date between '{$user_subscription_start_date}' and '{$user_subscription_end_date}'
|
||||
and view_pzfacts.pzfact_county in ($counties)";
|
||||
|
||||
$pzfacts = $this->connect()->query($SQL)->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
return $pzfacts;
|
||||
}
|
||||
|
||||
// ===============================
|
||||
// Get Business Facts Full Dataset
|
||||
// ===============================
|
||||
|
||||
private function getBusinessFactsFullDataset($user_subscription_start_date, $user_subscription_end_date, $counties) {
|
||||
|
||||
set_time_limit(0);
|
||||
|
||||
// determine real date range based upon users subscription start date
|
||||
|
||||
if ($user_subscription_start_date <= date('Y-m-d', strtotime('-1 year'))) {
|
||||
$user_subscription_start_date = date('Y-m-d', strtotime('-1 year'));
|
||||
}
|
||||
|
||||
$SQL = "select view_businessfacts.*
|
||||
from view_businessfacts
|
||||
where view_businessfacts.businessfact_entry_date between '{$user_subscription_start_date}' and '{$user_subscription_end_date}'
|
||||
and view_businessfacts.businessfact_county in ($counties)";
|
||||
|
||||
$businessfacts = $this->connect()->query($SQL)->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
return $businessfacts;
|
||||
}
|
||||
|
||||
// ========================
|
||||
// Return a Counties Object
|
||||
// ========================
|
||||
|
||||
private function getSubscriptionCounties($subscription_serial) {
|
||||
|
||||
$SQL = "select view_subscriptioncounties.*
|
||||
from view_subscriptioncounties
|
||||
where view_subscriptioncounties.subscriptioncounty_subscription = '{$subscription_serial}'";
|
||||
|
||||
$counties = $this->connect()->query($SQL)->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$countyNames = [];
|
||||
|
||||
foreach ($counties as $county) {
|
||||
|
||||
$countyNames[] = $county['subscriptioncounty_county'];
|
||||
}
|
||||
|
||||
$counties = implode(', ', $countyNames);
|
||||
|
||||
return $counties;
|
||||
}
|
||||
|
||||
// ====================
|
||||
// Purges Files on Disk
|
||||
// ====================
|
||||
|
||||
private function purgeFiles() {
|
||||
|
||||
$SQL = "select *
|
||||
from exportjobs
|
||||
where exportjobs.exportjob_created < (NOW() - INTERVAL 24 HOUR)";
|
||||
|
||||
$exportfiles = $this->connect()->query($SQL)->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
if (count($exportfiles) == 0) {
|
||||
$this->log("Nothing To Purge");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($exportfiles as $files) {
|
||||
|
||||
$filename = $files['exportjob_file_path'];
|
||||
|
||||
unlink($filename);
|
||||
}
|
||||
|
||||
$baseDir = './exports';
|
||||
|
||||
foreach (new DirectoryIterator($baseDir) as $item) {
|
||||
|
||||
if ($item->isDot() || !$item->isDir()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$folderPath = $item->getPathname();
|
||||
|
||||
// Check if directory is empty
|
||||
$files = scandir($folderPath);
|
||||
|
||||
if ($files !== false && count($files) === 2) {
|
||||
rmdir($folderPath);
|
||||
}
|
||||
}
|
||||
|
||||
$this->log("Purging Export Jobs Database Records");
|
||||
|
||||
$SQL = "delete from exportjobs
|
||||
where exportjobs.exportjob_created < (NOW() - INTERVAL 24 HOUR)";
|
||||
|
||||
$this->connection->query($SQL);
|
||||
}
|
||||
|
||||
// ==================
|
||||
// Create Export File
|
||||
// ==================
|
||||
|
||||
private function createExportFile($exportjob_file_name, $exportjob_file_type, $recreational_licenses, $exportjob_license_type) {
|
||||
|
||||
$job_code = $this->getUniqueJobCode();
|
||||
|
||||
//Create a dedicated job folder
|
||||
$base_directory = "./exports/{$job_code}";
|
||||
|
||||
if (!is_dir($base_directory)) {
|
||||
mkdir($base_directory, 0777, true);
|
||||
}
|
||||
|
||||
$exportjob_file_path = "{$base_directory}/{$exportjob_file_name}";
|
||||
|
||||
switch ($exportjob_file_type) {
|
||||
|
||||
case "CSV":
|
||||
|
||||
// Create a dedicated job folder
|
||||
$base_directory = "./exports/{$job_code}";
|
||||
|
||||
if (!is_dir($base_directory)) {
|
||||
mkdir($base_directory, 0777, true);
|
||||
}
|
||||
|
||||
$exportjob_file_path = "{$base_directory}/{$exportjob_file_name}";
|
||||
|
||||
$file_pointer = (fopen($exportjob_file_path, 'w'));
|
||||
|
||||
if (!$file_pointer) {
|
||||
throw new RuntimeException("Unable to write: {$exportjob_file_path}");
|
||||
}
|
||||
|
||||
// Add CSV headers
|
||||
|
||||
fputcsv($file_pointer, ['lastname', 'firstname', 'Gender', 'ethnicity', 'county', 'city', 'licence_type', 'start_date', 'expire_date'], ',', '"', '\\');
|
||||
|
||||
foreach ($recreational_licenses as $recreational_license) {
|
||||
|
||||
fputcsv($file_pointer, $recreational_license, ',', '"', '\\');
|
||||
}
|
||||
|
||||
fclose($file_pointer);
|
||||
|
||||
break;
|
||||
|
||||
case "PDF":
|
||||
|
||||
$this->createPDFExport_ResidentialLicenses($recreational_licenses, $base_directory, $exportjob_file_name);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
$exportjob_file_path = str_replace('../exports/', './exports/', $exportjob_file_path);
|
||||
$exportjob_file_type = strtoupper(pathinfo($exportjob_file_path, PATHINFO_EXTENSION));
|
||||
|
||||
return ['exportjob_file_name' => $exportjob_file_name, 'exportjob_file_path' => $exportjob_file_path, 'exportjob_file_type' => $exportjob_file_type];
|
||||
}
|
||||
|
||||
// =======================
|
||||
// Format Raw Phone Number
|
||||
// =======================
|
||||
|
||||
public function formatPhoneNumber(string $phonenumber): string {
|
||||
|
||||
// Remove everything except digits
|
||||
$digits = preg_replace('/\D+/', '', $phonenumber);
|
||||
|
||||
// Handle leading country code (US)
|
||||
if (strlen($digits) === 11 && str_starts_with($digits, '1')) {
|
||||
$digits = substr($digits, 1);
|
||||
}
|
||||
|
||||
return substr($digits, 0, 3) . '-' . substr($digits, 3, 3) . '-' . substr($digits, 6, 4);
|
||||
}
|
||||
|
||||
// ========================
|
||||
// Creates Permit Facts PDF
|
||||
// ========================
|
||||
|
||||
private function createPDFExport_ResidentialLicenses($permitfacts, $exportjob_base_directory, $exportjob_file_name) {
|
||||
|
||||
require_once ("./reports/Print_SearchedLicensesPDF.php");
|
||||
|
||||
$report = (new Print_SearchedLicensesPDF())->print($permitfacts, $exportjob_base_directory, $exportjob_file_name);
|
||||
return $report;
|
||||
}
|
||||
|
||||
// ======================
|
||||
// Return Unique Job Code
|
||||
// ======================
|
||||
|
||||
private function getUniqueJobCode() {
|
||||
return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
|
||||
random_int(0, 0xffff), random_int(0, 0xffff), random_int(0, 0xffff),
|
||||
random_int(0, 0x0fff) | 0x4000, random_int(0, 0x3fff) | 0x8000,
|
||||
random_int(0, 0xffff), random_int(0, 0xffff), random_int(0, 0xffff)
|
||||
);
|
||||
}
|
||||
|
||||
// ==========================
|
||||
// Send an Alert/Notification
|
||||
// ==========================
|
||||
|
||||
public function sendWebHookAlert($message, $title = "🚨 DEC Application Alert", $alerttype = "1fff00") {
|
||||
|
||||
$webhookUrl = (string) $this->settings->DiscordWebHookURL;
|
||||
|
||||
$data = [
|
||||
'embeds' => [[
|
||||
'title' => $title,
|
||||
'description' => $message,
|
||||
'color' => hexdec($alerttype),
|
||||
'footer' => [
|
||||
'text' => 'Real Estate Data Inc. System Notificiation',
|
||||
],
|
||||
'timestamp' => date('c'), // ISO 8601 format
|
||||
]]
|
||||
];
|
||||
|
||||
$jsonData = json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
||||
|
||||
$ch = curl_init($webhookUrl);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
|
||||
if ($response === false) {
|
||||
$this->log('Curl error: ' . curl_error($ch));
|
||||
}
|
||||
|
||||
curl_close($ch);
|
||||
}
|
||||
|
||||
// ============
|
||||
// Email Admins
|
||||
// ============
|
||||
|
||||
public function email_admins($subject = "", $message = "") {
|
||||
|
||||
$this->log(date("Y-m-d H:i:s") . " - Emailing Admins...");
|
||||
|
||||
$settings = new SimpleXMLElement((file_exists("./xml/settings.xml") ? file_get_contents("./xml/settings.xml") : "<settings/>"));
|
||||
|
||||
// Server Variables
|
||||
$host = (string) $settings->SmtpServer;
|
||||
$username = (string) $settings->SmtpUserName;
|
||||
$password = (string) $settings->SmtpPassword;
|
||||
|
||||
// Recipient Variables
|
||||
$from_email = (string) $settings->FromEmail;
|
||||
$from_name = (string) $settings->FromName;
|
||||
|
||||
$support_email = (string) $settings->SupportEmail;
|
||||
$support_name = (string) $settings->SupportName;
|
||||
|
||||
if ((string) $settings->Environment == 'Production') {
|
||||
|
||||
$admin_email = (string) $settings->AdminEmail;
|
||||
$admin_name = (string) $settings->AdminName;
|
||||
}
|
||||
|
||||
// Content Variables
|
||||
|
||||
$attachment_name = "";
|
||||
|
||||
$mail = new PHPMailer(true);
|
||||
|
||||
try {
|
||||
|
||||
//Server settings
|
||||
$mail->isSMTP();
|
||||
$mail->Host = $host;
|
||||
$mail->SMTPAuth = true;
|
||||
$mail->Username = $username;
|
||||
$mail->Password = $password;
|
||||
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
|
||||
$mail->Port = 465;
|
||||
|
||||
//Recipients
|
||||
$mail->setFrom($from_email, $from_name);
|
||||
$mail->addAddress($support_email, $support_name);
|
||||
|
||||
if ($settings->Environment == 'Production') {
|
||||
$mail->addAddress($admin_email, $admin_name);
|
||||
}
|
||||
|
||||
//Attachments
|
||||
$mail->addAttachment($attachment_name);
|
||||
|
||||
//Content
|
||||
$mail->isHTML(true);
|
||||
$mail->Subject = $subject;
|
||||
$mail->Body = $message;
|
||||
|
||||
$mail->send();
|
||||
} catch (Exception $e) {
|
||||
$this->log("Message could not be sent. Mailer Error: {$e->ErrorInfo}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,314 @@
|
||||
<?php
|
||||
|
||||
class RaceCodes 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;
|
||||
}
|
||||
|
||||
// ================
|
||||
// Setup Race Codes
|
||||
// ================
|
||||
|
||||
public function setupRaceCodes() {
|
||||
|
||||
$racecodes = $this->getRaceCodesPage();
|
||||
$popovers = (new Popovers())->getPopovers();
|
||||
|
||||
$XML = $this->mergeXML($racecodes, "<XML/>");
|
||||
$XML = $this->mergeXML($popovers, $XML);
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("setupRaceCodes"));
|
||||
|
||||
$this->displayContent($content);
|
||||
}
|
||||
|
||||
// =============
|
||||
// Add Race Code
|
||||
// =============
|
||||
|
||||
public function addRaceCode() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$content = $this->applyXSL("", $this->getXSL("addRaceCode"));
|
||||
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "add":
|
||||
|
||||
$racecode_code = filter_input(INPUT_POST, "racecode_code") ?: "";
|
||||
$racecode_description = filter_input(INPUT_POST, "racecode_description") ?: "";
|
||||
|
||||
$SQL = "insert into racecodes
|
||||
|
||||
( racecode_code,
|
||||
racecode_description,
|
||||
racecode_active,
|
||||
racecode_creator,
|
||||
racecode_created )
|
||||
|
||||
VALUES ( :racecode_code,
|
||||
:racecode_description,
|
||||
:racecode_active,
|
||||
:racecode_creator,
|
||||
:racecode_created )";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":racecode_code", strtoupper($racecode_code));
|
||||
$statement->bindValue(":racecode_description", $racecode_description);
|
||||
$statement->bindValue(":racecode_active", true, PDO::PARAM_BOOL);
|
||||
$statement->bindValue(":racecode_creator", $this->current_user_name);
|
||||
$statement->bindValue(":racecode_created", $this->getTimestamp());
|
||||
|
||||
$statement->execute();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// ===================
|
||||
// Edit a Race Code
|
||||
// ===================
|
||||
|
||||
public function editRaceCode() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$racecode_serial = filter_input(INPUT_POST, "racecode_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$racecode = $this->getRaceCode($racecode_serial);
|
||||
|
||||
if ($racecode->count() == 0) {
|
||||
$this->logError("Invalid Race Code ({$racecode_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$content = $this->applyXSL($racecode, $this->getXSL("editRaceCode"));
|
||||
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "update":
|
||||
|
||||
$racecode_serial = filter_input(INPUT_POST, "racecode_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$racecode_code = filter_input(INPUT_POST, "racecode_code") ?: "";
|
||||
$racecode_description = filter_input(INPUT_POST, "racecode_description") ?: "";
|
||||
$racecode_active = filter_input(INPUT_POST, "racecode_active", FILTER_VALIDATE_BOOLEAN) ?: false;
|
||||
|
||||
// Verify the RaceCodes
|
||||
|
||||
$racecode = $this->getRaceCode($racecode_serial);
|
||||
|
||||
if ($racecode->count() == 0) {
|
||||
$this->logError("Invalid RaceCodes ({$racecode_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$SQL = "update racecodes
|
||||
set racecode_code = :racecode_code,
|
||||
racecode_description = :racecode_description,
|
||||
racecode_active = :racecode_active,
|
||||
racecode_changer = :racecode_changer,
|
||||
racecode_changed = :racecode_changed
|
||||
where racecode_serial = :racecode_serial";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":racecode_serial", $racecode_serial);
|
||||
$statement->bindValue(":racecode_code", strtoupper($racecode_code));
|
||||
$statement->bindValue(":racecode_description", $racecode_description);
|
||||
$statement->bindValue(":racecode_active", $racecode_active, PDO::PARAM_BOOL);
|
||||
$statement->bindValue(":racecode_changer", $this->current_user_name);
|
||||
$statement->bindValue(":racecode_changed", $this->getTimestamp());
|
||||
|
||||
$statement->execute();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// ===================
|
||||
// Delete Race Code
|
||||
// ===================
|
||||
|
||||
public function deleteRaceCode() {
|
||||
|
||||
$racecode_serial = filter_input(INPUT_POST, "racecode_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$racecode = $this->getRaceCode($racecode_serial);
|
||||
|
||||
if ($racecode->count() == 0) {
|
||||
$this->logError("Invalid Race Code ({$racecode_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$SQL = "delete from racecodes where racecode_serial = {$racecode_serial}";
|
||||
|
||||
$this->executeSQL($SQL);
|
||||
}
|
||||
|
||||
// =====================================
|
||||
// Return an Active Race Codes Object
|
||||
// =====================================
|
||||
|
||||
public function getActiveRaceCodes() {
|
||||
|
||||
$SQL = "select view_racecodes.*
|
||||
from view_racecodes
|
||||
where racecode_active is true";
|
||||
|
||||
return $this->getTable("racecodes", $SQL);
|
||||
}
|
||||
|
||||
// ==============================
|
||||
// Return an Race Codes Object
|
||||
// ==============================
|
||||
|
||||
public function getRaceCode($racecode_serial = 0) {
|
||||
|
||||
$SQL = "select view_racecodes.*
|
||||
from view_racecodes
|
||||
where racecode_serial = {$racecode_serial}";
|
||||
|
||||
return $this->getTable("racecodes", $SQL);
|
||||
}
|
||||
|
||||
// =============================
|
||||
// Return a Race Codes Object
|
||||
// =============================
|
||||
|
||||
public function getRaceCodes() {
|
||||
|
||||
$SQL = "select view_racecodes.*
|
||||
from view_racecodes";
|
||||
|
||||
return $this->getTable("racecodes", $SQL);
|
||||
}
|
||||
|
||||
// ==================================
|
||||
// Return a Race Codes Page Object
|
||||
// ==================================
|
||||
|
||||
public function getRaceCodesPage() {
|
||||
|
||||
// Find Criteria
|
||||
|
||||
$find_racecode = filter_input(INPUT_POST, "find_racecode") ?: "";
|
||||
$find_racecode = $this->sanitizeString($find_racecode);
|
||||
|
||||
$find_words = implode("|", explode(" ", $find_racecode));
|
||||
|
||||
// Record Count
|
||||
|
||||
$connection = $this->connect();
|
||||
|
||||
$SQL = "select count(*) as count
|
||||
from view_racecodes
|
||||
where racecode_code regexp :racecode_code
|
||||
or racecode_description regexp :racecode_description";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":racecode_code", $find_words);
|
||||
$statement->bindValue(":racecode_description", $find_words);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$recordset = $statement->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$count = (count($recordset) > 0) ? (integer) $recordset["count"] : (integer) 0;
|
||||
|
||||
// Pagination
|
||||
|
||||
$pagination = filter_input(INPUT_POST, "pagination") ?: "";
|
||||
|
||||
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 = ($count / $this->pagination_size);
|
||||
break;
|
||||
}
|
||||
|
||||
$offset = (($this->pagination_page * $this->pagination_size) - $this->pagination_size);
|
||||
$start = ($offset + 1);
|
||||
$end = min($count, (($start + $this->pagination_size) - 1));
|
||||
|
||||
// Data
|
||||
|
||||
$SQL = "select view_racecodes.*
|
||||
from view_racecodes
|
||||
where racecode_code regexp :racecode_code
|
||||
or racecode_description regexp :racecode_description
|
||||
order by racecode_code
|
||||
limit {$this->pagination_size}
|
||||
offset {$offset}";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":racecode_code", $find_words);
|
||||
$statement->bindValue(":racecode_description", $find_words);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$racecodes = $this->getTableXML("racecodes", $statement);
|
||||
|
||||
// Insert Pagination Attributes
|
||||
|
||||
$racecodes->addAttribute("count", $count);
|
||||
$racecodes->addAttribute("start", $start);
|
||||
$racecodes->addAttribute("end", $end);
|
||||
$racecodes->addAttribute("page", $this->pagination_page);
|
||||
|
||||
$_SESSION[self::PAGINATION_PAGE] = $this->pagination_page;
|
||||
|
||||
return $racecodes;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,479 @@
|
||||
<?php
|
||||
|
||||
// =============
|
||||
// Reports Class
|
||||
// =============
|
||||
|
||||
class Reports extends Base {
|
||||
|
||||
// Variables.
|
||||
|
||||
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_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;
|
||||
}
|
||||
|
||||
// ==========
|
||||
// Add Report
|
||||
// ==========
|
||||
|
||||
public function addReport() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$constants = $this->getConstants();
|
||||
|
||||
$XML = $this->mergeXML($constants, "<XML/>");
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("./system/addReport"));
|
||||
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "add":
|
||||
|
||||
$report_name = filter_input(INPUT_POST, "report_name") ?: "";
|
||||
$report_class = filter_input(INPUT_POST, "report_class") ?: "";
|
||||
$report_type = filter_input(INPUT_POST, "report_type") ?: "Report";
|
||||
$report_description = filter_input(INPUT_POST, "report_description") ?: "";
|
||||
$report_target = filter_input(INPUT_POST, "report_target") ?: "";
|
||||
|
||||
$report_class = trim(preg_replace("/\s+/", " ", $report_class));
|
||||
|
||||
$SQL = "insert into reports
|
||||
|
||||
( report_class,
|
||||
report_type,
|
||||
report_name,
|
||||
report_description,
|
||||
report_target )
|
||||
|
||||
VALUES ( :report_class,
|
||||
:report_type,
|
||||
:report_name,
|
||||
:report_description,
|
||||
:report_target)";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":report_class", $report_class);
|
||||
$statement->bindValue(":report_type", $report_type);
|
||||
$statement->bindValue(":report_name", $report_name);
|
||||
$statement->bindValue(":report_description", $report_description);
|
||||
$statement->bindValue(":report_target", $report_target);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// =============
|
||||
// Delete Report
|
||||
// =============
|
||||
|
||||
public function deleteReport() {
|
||||
|
||||
$report_serial = filter_input(INPUT_POST, "report_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$reports = $this->getReport($report_serial);
|
||||
|
||||
if ($reports->count() == 0) {
|
||||
$this->logError("Invalid Report ({$report_serial}): " . __METHOD__);
|
||||
}
|
||||
|
||||
$SQL = "delete from reports
|
||||
where report_serial = {$report_serial}";
|
||||
|
||||
$this->executeSQL($SQL);
|
||||
}
|
||||
|
||||
// ===========
|
||||
// Edit Report
|
||||
// ===========
|
||||
|
||||
public function editReport() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$report_serial = filter_input(INPUT_POST, "report_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$reports = $this->getReport($report_serial);
|
||||
|
||||
if ($reports->count() == 0) {
|
||||
$this->logError("Invalid Report ({$report_serial}): " . __METHOD__);
|
||||
}
|
||||
|
||||
$constants = $this->getConstants();
|
||||
|
||||
$XML = $this->mergeXML($reports, "<XML/>");
|
||||
$XML = $this->mergeXML($constants, $XML);
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("./system/editReport"));
|
||||
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "update":
|
||||
|
||||
$report_serial = filter_input(INPUT_POST, "report_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$report_name = filter_input(INPUT_POST, "report_name") ?: "";
|
||||
$report_class = filter_input(INPUT_POST, "report_class") ?: "";
|
||||
$report_type = filter_input(INPUT_POST, "report_type") ?: "Report";
|
||||
$report_description = filter_input(INPUT_POST, "report_description") ?: "";
|
||||
$report_target = filter_input(INPUT_POST, "report_target") ?: "";
|
||||
|
||||
$report_class = trim(preg_replace("/\s+/", " ", $report_class));
|
||||
|
||||
$reports = $this->getReport($report_serial);
|
||||
|
||||
if ($reports->count() == 0) {
|
||||
$this->logError("Invalid Report ({$report_serial}): " . __METHOD__);
|
||||
}
|
||||
|
||||
$SQL = "update reports
|
||||
set report_class = :report_class,
|
||||
report_type = :report_type,
|
||||
report_name = :report_name,
|
||||
report_description = :report_description,
|
||||
report_target = :report_target
|
||||
where report_serial = :report_serial";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":report_serial", $report_serial);
|
||||
$statement->bindValue(":report_class", $report_class);
|
||||
$statement->bindValue(":report_type", $report_type);
|
||||
$statement->bindValue(":report_name", $report_name);
|
||||
$statement->bindValue(":report_description", $report_description);
|
||||
$statement->bindValue(":report_target", $report_target);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// ======================
|
||||
// Return a Report Object
|
||||
// ======================
|
||||
|
||||
public function getReport($report_serial = 0) {
|
||||
|
||||
$SQL = "select view_reports.*
|
||||
from view_reports
|
||||
where report_serial = {$report_serial}";
|
||||
|
||||
return $this->getTable("reports", $SQL);
|
||||
}
|
||||
|
||||
// ===========================================
|
||||
// Return the report_serial for a report_class
|
||||
// ===========================================
|
||||
|
||||
public function getReportSerial($report_class = "") {
|
||||
|
||||
$SQL = "select view_reports.report_serial
|
||||
from view_reports
|
||||
where report_class = '{$report_class}'";
|
||||
|
||||
$reports = $this->getTable("reports", $SQL);
|
||||
|
||||
return (integer) ($reports->record->report_serial ?? 0);
|
||||
}
|
||||
|
||||
// =======================
|
||||
// Return a Reports Object
|
||||
// =======================
|
||||
|
||||
public function getReports() {
|
||||
|
||||
$SQL = "select view_reports.*
|
||||
from view_reports";
|
||||
|
||||
return $this->getTable("reports", $SQL);
|
||||
}
|
||||
|
||||
// ============================
|
||||
// Return a Reports Page Object
|
||||
// ============================
|
||||
|
||||
public function getReportsPage() {
|
||||
|
||||
// Find Criteria
|
||||
|
||||
$find_report = filter_input(INPUT_POST, "find_report") ?: "";
|
||||
$find_words = $this->sanitizeString($find_report);
|
||||
|
||||
// $find_words = implode("|", explode(" ", $find_report));
|
||||
// Show Per Page
|
||||
|
||||
$this->pagination_size = filter_input(INPUT_POST, "reports_per_page", FILTER_SANITIZE_NUMBER_INT) ?: $this->pagination_size;
|
||||
|
||||
// Record Count
|
||||
|
||||
$connection = $this->connect();
|
||||
|
||||
$SQL = "select count(*) as count
|
||||
from view_reports
|
||||
where (report_class regexp :report_class
|
||||
or report_name regexp :report_name
|
||||
or report_type regexp :report_type
|
||||
or report_description regexp :report_description)";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":report_class", $find_words);
|
||||
$statement->bindValue(":report_name", $find_words);
|
||||
$statement->bindValue(":report_type", $find_words);
|
||||
$statement->bindValue(":report_description", $find_words);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$recordset = $statement->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$count = (count($recordset) > 0) ? (integer) $recordset["count"] : (integer) 0;
|
||||
|
||||
// Pagination
|
||||
|
||||
$pagination = filter_input(INPUT_POST, "pagination") ?: "";
|
||||
|
||||
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 = ($count / $this->pagination_size);
|
||||
break;
|
||||
}
|
||||
|
||||
$offset = (($this->pagination_page * $this->pagination_size) - $this->pagination_size);
|
||||
$start = ($offset + 1);
|
||||
$end = min($count, (($start + $this->pagination_size) - 1));
|
||||
|
||||
// Data
|
||||
|
||||
$SQL = "select view_reports.*
|
||||
from view_reports
|
||||
where (report_class regexp :report_class
|
||||
or report_name regexp :report_name
|
||||
or report_type regexp :report_type
|
||||
or report_description regexp :report_description)
|
||||
limit {$this->pagination_size}
|
||||
offset {$offset}";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":report_class", $find_words);
|
||||
$statement->bindValue(":report_name", $find_words);
|
||||
$statement->bindValue(":report_type", $find_words);
|
||||
$statement->bindValue(":report_description", $find_words);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$reports = $this->getTableXML("reports", $statement);
|
||||
|
||||
// Insert Pagination Attributes
|
||||
|
||||
$reports->addAttribute("count", $count);
|
||||
$reports->addAttribute("start", $start);
|
||||
$reports->addAttribute("end", $end);
|
||||
$reports->addAttribute("page", $this->pagination_page);
|
||||
|
||||
$_SESSION[self::PAGINATION_PAGE] = $this->pagination_page;
|
||||
|
||||
return $reports;
|
||||
}
|
||||
|
||||
// ==================================
|
||||
// Return a Select Report Page Object
|
||||
// ==================================
|
||||
|
||||
public function getSelectReportPage() {
|
||||
|
||||
// Find Criteria
|
||||
|
||||
$select_report = filter_input(INPUT_POST, "select_report") ?: "";
|
||||
$find_words = $this->sanitizeString($select_report);
|
||||
|
||||
// Show Per Page
|
||||
|
||||
$this->pagination_size = filter_input(INPUT_POST, "reports_per_page", FILTER_SANITIZE_NUMBER_INT) ?: $this->pagination_size;
|
||||
|
||||
// Record Count
|
||||
|
||||
$connection = $this->connect();
|
||||
|
||||
$SQL = "select count(*) as count
|
||||
from view_reports
|
||||
where report_name regexp :report_name
|
||||
or report_description regexp :report_description";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":report_name", $find_words);
|
||||
$statement->bindValue(":report_description", $find_words);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$recordset = $statement->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$count = (count($recordset) > 0) ? (integer) $recordset["count"] : (integer) 0;
|
||||
|
||||
// Pagination
|
||||
|
||||
$pagination = filter_input(INPUT_POST, "pagination") ?: "";
|
||||
|
||||
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 = ($count / $this->pagination_size);
|
||||
break;
|
||||
}
|
||||
|
||||
$offset = (($this->pagination_page * $this->pagination_size) - $this->pagination_size);
|
||||
$start = ($offset + 1);
|
||||
$end = min($count, (($start + $this->pagination_size) - 1));
|
||||
|
||||
// Data
|
||||
|
||||
$SQL = "select view_reports.*
|
||||
from view_reports
|
||||
where report_name regexp :report_name
|
||||
or report_description regexp :report_description
|
||||
limit {$this->pagination_size}
|
||||
offset {$offset}";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":report_name", $find_words);
|
||||
$statement->bindValue(":report_description", $find_words);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$reports = $this->getTableXML("reports", $statement);
|
||||
|
||||
// Insert Pagination Attributes
|
||||
|
||||
$reports->addAttribute("count", $count);
|
||||
$reports->addAttribute("start", $start);
|
||||
$reports->addAttribute("end", $end);
|
||||
$reports->addAttribute("page", $this->pagination_page);
|
||||
|
||||
$_SESSION[self::PAGINATION_PAGE] = $this->pagination_page;
|
||||
|
||||
return $reports;
|
||||
}
|
||||
|
||||
// ====================================
|
||||
// Determine if the Report Class Exists
|
||||
// ====================================
|
||||
|
||||
public function reportExists() {
|
||||
|
||||
$exists = false;
|
||||
|
||||
$report_serial = filter_input(INPUT_POST, "report_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$report_class = filter_input(INPUT_POST, "report_class") ?: "";
|
||||
|
||||
$report_class = trim(preg_replace("/\s+/", " ", $report_class));
|
||||
|
||||
$SQL = "select report_serial
|
||||
from view_reports
|
||||
where report_serial != :report_serial
|
||||
and lower(report_class) = :report_class";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":report_serial", $report_serial);
|
||||
$statement->bindValue(":report_class", $report_class);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$recordset = $statement->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$exists = (count($recordset) > 0) ? true : false;
|
||||
|
||||
echo json_encode($exists);
|
||||
}
|
||||
|
||||
// ================
|
||||
// Select a Report.
|
||||
// ================
|
||||
|
||||
public function selectReport() {
|
||||
|
||||
$reports = $this->getSelectReportPage();
|
||||
$popovers = (new Popovers())->getPopovers();
|
||||
|
||||
$XML = $this->mergeXML($reports, "<XML/>");
|
||||
$XML = $this->mergeXML($popovers, $XML);
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("./system/selectReport"));
|
||||
|
||||
$this->displayContent($content);
|
||||
}
|
||||
|
||||
// =============
|
||||
// Setup Reports
|
||||
// =============
|
||||
|
||||
public function setupReports() {
|
||||
|
||||
$reports = $this->getReportsPage();
|
||||
$popovers = (new Popovers())->getPopovers();
|
||||
|
||||
$XML = $this->mergeXML($reports, "<XML/>");
|
||||
$XML = $this->mergeXML($popovers, $XML);
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("./system/setupReports"));
|
||||
|
||||
$this->displayContent($content);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,253 @@
|
||||
<?php
|
||||
|
||||
class SearchHistory extends Base {
|
||||
|
||||
// Variables
|
||||
|
||||
private $current_user_serial = 0;
|
||||
private $current_user_id = "";
|
||||
private $current_user_name = "";
|
||||
private $current_user_email = "";
|
||||
|
||||
// =================
|
||||
// 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] ?? "";
|
||||
}
|
||||
|
||||
// ============================
|
||||
// Save Users Search Parameters
|
||||
// ============================
|
||||
|
||||
public function saveUserSearchParameters($searchpayload) {
|
||||
|
||||
$user = $this->current_user_serial;
|
||||
$subscription_serial = $searchpayload['subscription_serial'];
|
||||
|
||||
switch ($subscription_serial) {
|
||||
|
||||
case 5:
|
||||
case 9:
|
||||
case 11:
|
||||
case 13:
|
||||
case 15:
|
||||
|
||||
$searchcriteria = json_encode(array_filter($searchpayload, fn($key) => str_starts_with($key, 'permit_'), ARRAY_FILTER_USE_KEY));
|
||||
|
||||
break;
|
||||
|
||||
case 7:
|
||||
case 10:
|
||||
case 12:
|
||||
case 14:
|
||||
case 16:
|
||||
|
||||
$searchcriteria = json_encode(array_filter($searchpayload, fn($key) => str_starts_with($key, 'permit_'), ARRAY_FILTER_USE_KEY));
|
||||
|
||||
break;
|
||||
|
||||
default :
|
||||
$this->debug("ERROR....");
|
||||
return;
|
||||
}
|
||||
|
||||
$SQL = "insert into searchhistories
|
||||
|
||||
( searchhistory_user,
|
||||
searchhistory_subscription,
|
||||
searchhistory_parameters,
|
||||
searchhistory_creator,
|
||||
searchhistory_created )
|
||||
|
||||
values ( :searchhistory_user,
|
||||
:searchhistory_subscription,
|
||||
:searchhistory_parameters,
|
||||
:searchhistory_creator,
|
||||
:searchhistory_created )";
|
||||
|
||||
$connection = $this->connect();
|
||||
$statement = $connection->prepare($SQL);
|
||||
$statement->bindValue(":searchhistory_user", $user);
|
||||
$statement->bindValue(":searchhistory_subscription", $subscription_serial);
|
||||
$statement->bindValue(":searchhistory_parameters", $searchcriteria);
|
||||
$statement->bindValue(":searchhistory_creator", $this->current_user_name);
|
||||
$statement->bindValue(":searchhistory_created", $this->getTimestamp());
|
||||
|
||||
$statement->execute();
|
||||
}
|
||||
|
||||
// ============================
|
||||
// Save Users Search Parameters
|
||||
// ============================
|
||||
|
||||
public function updateUserSearchParameters($searchpayload) {
|
||||
|
||||
$user = $this->current_user_serial;
|
||||
$subscription_serial = $searchpayload['subscription_serial'];
|
||||
|
||||
switch ($subscription_serial) {
|
||||
|
||||
case 5:
|
||||
case 9:
|
||||
case 11:
|
||||
case 13:
|
||||
case 15:
|
||||
|
||||
$searchcriteria = json_encode(array_filter($searchpayload, fn($key) => str_starts_with($key, 'permit_'), ARRAY_FILTER_USE_KEY));
|
||||
|
||||
break;
|
||||
|
||||
case 7:
|
||||
case 10:
|
||||
case 12:
|
||||
case 14:
|
||||
case 16:
|
||||
|
||||
$searchcriteria = json_encode(array_filter($searchpayload, fn($key) => str_starts_with($key, 'permit_'), ARRAY_FILTER_USE_KEY));
|
||||
|
||||
break;
|
||||
|
||||
default :
|
||||
return;
|
||||
}
|
||||
|
||||
$SQL = "update searchhistories
|
||||
set searchhistory_parameters = :searchhistory_parameters,
|
||||
searchhistory_changer = :searchhistory_changer,
|
||||
searchhistory_changed = :searchhistory_changed
|
||||
where searchhistory_user = :searchhistory_user
|
||||
and searchhistory_subscription = :searchhistory_subscription";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":searchhistory_parameters", $searchcriteria);
|
||||
$statement->bindValue(":searchhistory_changer", $this->current_user_name);
|
||||
$statement->bindValue(":searchhistory_changed", $this->getTimestamp());
|
||||
$statement->bindValue(":searchhistory_user", $user);
|
||||
$statement->bindValue(":searchhistory_subscription", $subscription_serial);
|
||||
|
||||
$statement->execute();
|
||||
}
|
||||
|
||||
// ============================
|
||||
// Gets Users Search Parameters
|
||||
// ============================
|
||||
|
||||
public function getUsersPreviousSearchParameters($user, $subscription) {
|
||||
|
||||
$SQL = "select view_searchhistories.*
|
||||
from view_searchhistories
|
||||
where view_searchhistories.searchhistory_user = {$user}
|
||||
and view_searchhistories.searchhistory_subscription = {$subscription}";
|
||||
|
||||
$recordset = $this->getTable("searchhistory", $SQL);
|
||||
|
||||
return $this->materializeSearchHistoryParameters($recordset);
|
||||
}
|
||||
|
||||
// ============================
|
||||
// Gets Users Search Parameters
|
||||
// ============================
|
||||
|
||||
public function materializeSearchHistoryParameters(SimpleXMLElement $SXE): SimpleXMLElement {
|
||||
|
||||
if (!isset($SXE->record)) {
|
||||
return $SXE;
|
||||
}
|
||||
|
||||
// Keys that should ALWAYS materialize as <key><id>..</id></key>
|
||||
// even if there is only one value.
|
||||
$multiSelectKeys = [
|
||||
'permitfact_project_city', 'permitfact_county', 'permitfact_project_type', 'permitfact_work_type', 'permitfact_building_type',
|
||||
'businessfact_city', 'businessfact_city', 'businessfact_county', 'businessfact_action', 'businessfact_business_class',
|
||||
'pzfact_project_city', 'pzfact_project_city', 'pzfact_project_city', 'pzfact_project_city'
|
||||
];
|
||||
|
||||
foreach ($SXE->record as $record) {
|
||||
|
||||
if (!isset($record->searchhistory_parameters)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$json = trim((string) $record->searchhistory_parameters);
|
||||
if ($json === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data = json_decode($json, true);
|
||||
if (!is_array($data)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Clear existing text content
|
||||
$record->searchhistory_parameters[0] = null;
|
||||
|
||||
foreach ($data as $key => $value) {
|
||||
|
||||
$nodeName = preg_replace('/[^A-Za-z0-9_\-:.]/', '_', (string) $key);
|
||||
|
||||
$isMulti = in_array($key, $multiSelectKeys, true);
|
||||
|
||||
// If this is a multi-select key:
|
||||
// - Accept arrays (preferred)
|
||||
// - Accept CSV strings (legacy)
|
||||
// - Accept single scalar and wrap it in <id>
|
||||
if ($isMulti) {
|
||||
$parent = $record->searchhistory_parameters->addChild($nodeName);
|
||||
|
||||
if (is_array($value)) {
|
||||
$parts = $value;
|
||||
} else {
|
||||
$valueStr = trim((string) $value);
|
||||
|
||||
// empty -> create empty parent node and move on
|
||||
if ($valueStr === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// CSV or single
|
||||
$parts = (strpos($valueStr, ',') !== false) ? explode(',', $valueStr) : [$valueStr];
|
||||
}
|
||||
|
||||
$parts = array_values(array_filter(array_map('trim', $parts), fn($v) => $v !== ''));
|
||||
|
||||
foreach ($parts as $p) {
|
||||
$parent->addChild('id', htmlspecialchars($p, ENT_XML1 | ENT_QUOTES, 'UTF-8'));
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Non-multi-select keys (same as your current behavior)
|
||||
if (is_string($value) && strpos($value, ',') !== false) {
|
||||
|
||||
$parent = $record->searchhistory_parameters->addChild($nodeName);
|
||||
|
||||
$parts = array_values(array_filter(array_map('trim', explode(',', $value)), fn($v) => $v !== ''));
|
||||
foreach ($parts as $p) {
|
||||
$parent->addChild('id', htmlspecialchars($p, ENT_XML1 | ENT_QUOTES, 'UTF-8'));
|
||||
}
|
||||
} else {
|
||||
$record->searchhistory_parameters->addChild(
|
||||
$nodeName,
|
||||
htmlspecialchars((string) $value, ENT_XML1 | ENT_QUOTES, 'UTF-8')
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $SXE;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,384 @@
|
||||
<?php
|
||||
|
||||
class Statuses 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;
|
||||
}
|
||||
|
||||
// ==========
|
||||
// Add Status
|
||||
// ==========
|
||||
|
||||
public function addStatus() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$content = $this->applyXSL("", $this->getXSL("./system/addStatus"));
|
||||
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "add":
|
||||
|
||||
$status_name = filter_input(INPUT_POST, "status_name") ?: "";
|
||||
$status_classes = filter_input(INPUT_POST, "status_classes") ?: "";
|
||||
$status_active = filter_input(INPUT_POST, "status_active", FILTER_VALIDATE_BOOLEAN) ?: false;
|
||||
|
||||
$SQL = "insert into statuses
|
||||
|
||||
( status_name,
|
||||
status_classes,
|
||||
status_active,
|
||||
status_creator,
|
||||
status_created )
|
||||
|
||||
VALUES ( :status_name,
|
||||
:status_classes,
|
||||
:status_active,
|
||||
:status_creator,
|
||||
:status_created )";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":status_name", $status_name);
|
||||
$statement->bindValue(":status_classes", $status_classes);
|
||||
$statement->bindValue(":status_active", $status_active, PDO::PARAM_BOOL);
|
||||
$statement->bindValue(":status_creator", $this->current_user_name);
|
||||
$statement->bindValue(":status_created", $this->getTimestamp());
|
||||
|
||||
$statement->execute();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// =============
|
||||
// Delete Status
|
||||
// =============
|
||||
|
||||
public function deleteStatus() {
|
||||
|
||||
$status_serial = filter_input(INPUT_POST, "status_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$status = $this->getStatus($status_serial);
|
||||
|
||||
if ($status->count() == 0) {
|
||||
$this->logError("Invalid Status ({$status_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$SQL = "delete from statuses
|
||||
where status_serial = {$status_serial}";
|
||||
|
||||
$this->executeSQL($SQL);
|
||||
}
|
||||
|
||||
// ============================
|
||||
// Determine if a Status exists
|
||||
// ============================
|
||||
|
||||
public function statusExists() {
|
||||
|
||||
$status_serial = filter_input(INPUT_POST, "status_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$status_name = filter_input(INPUT_POST, "status_name") ?: "";
|
||||
|
||||
$SQL = "select status_serial
|
||||
from view_statuses
|
||||
where status_serial != :status_serial
|
||||
and lower(status_name) = :status_name";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":status_serial", $status_serial);
|
||||
$statement->bindValue(":status_name", strtolower($status_name));
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$recordset = $statement->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$exists = (count($recordset) > 0) ? true : false;
|
||||
|
||||
echo json_encode($exists);
|
||||
}
|
||||
|
||||
// ======================================
|
||||
// Determine if a Status is Active (AJAX)
|
||||
// ======================================
|
||||
|
||||
public function statusActive() {
|
||||
|
||||
$status_serial = filter_input(INPUT_POST, "status_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$active = false;
|
||||
|
||||
$SQL = "select workorder_status
|
||||
from workorders
|
||||
where workorder_status = {$status_serial}
|
||||
limit 1";
|
||||
|
||||
$workorders = $this->getTable("workorders", $SQL);
|
||||
|
||||
$active = ($workorders->count() > 0) ? true : false;
|
||||
|
||||
echo json_encode($active);
|
||||
}
|
||||
|
||||
// =============
|
||||
// Edit a Status
|
||||
// =============
|
||||
|
||||
public function editStatus() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$status_serial = filter_input(INPUT_POST, "status_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$status = $this->getStatus($status_serial);
|
||||
|
||||
if ($status->count() == 0) {
|
||||
$this->logError("Invalid Status ({$status_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$XML = $this->mergeXML($status, "<XML/>");
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("./system/editStatus"));
|
||||
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "update":
|
||||
|
||||
$status_serial = filter_input(INPUT_POST, "status_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$status_name = filter_input(INPUT_POST, "status_name") ?: "";
|
||||
$status_classes = filter_input(INPUT_POST, "status_classes") ?: "";
|
||||
$status_active = filter_input(INPUT_POST, "status_active", FILTER_VALIDATE_BOOLEAN) ?: false;
|
||||
$status_default = filter_input(INPUT_POST, "status_default", FILTER_VALIDATE_BOOLEAN) ?: false;
|
||||
|
||||
// Verify the Status
|
||||
|
||||
$status = $this->getStatus($status_serial);
|
||||
|
||||
if ($status->count() == 0) {
|
||||
$this->logError("Invalid Status ({$status_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$SQL = "update statuses
|
||||
set status_name = :status_name,
|
||||
status_classes = :status_classes,
|
||||
status_active = :status_active,
|
||||
status_default = :status_default,
|
||||
status_changer = :status_changer,
|
||||
status_changed = :status_changed
|
||||
where status_serial = :status_serial";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":status_serial", $status_serial);
|
||||
$statement->bindValue(":status_name", $status_name);
|
||||
$statement->bindValue(":status_classes", $status_classes);
|
||||
$statement->bindValue(":status_active", $status_active, PDO::PARAM_BOOL);
|
||||
$statement->bindValue(":status_default", $status_default, PDO::PARAM_BOOL);
|
||||
$statement->bindValue(":status_changer", $this->current_user_name);
|
||||
$statement->bindValue(":status_changed", $this->getTimestamp());
|
||||
|
||||
$statement->execute();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// ================================
|
||||
// Return an Active Statuses Object
|
||||
// ================================
|
||||
|
||||
public function getActiveStatuses() {
|
||||
|
||||
$SQL = "select view_statuses.*
|
||||
from view_statuses
|
||||
where status_active is true";
|
||||
|
||||
return $this->getTable("statuses", $SQL);
|
||||
}
|
||||
|
||||
// -------------------------
|
||||
// Return the Default Status
|
||||
// -------------------------
|
||||
|
||||
public function getDefaultStatus() {
|
||||
|
||||
$SQL = "select status_serial
|
||||
from view_statuses
|
||||
where status_default is true";
|
||||
|
||||
return $this->getTable("statuses", $SQL);
|
||||
}
|
||||
|
||||
// =======================
|
||||
// Return an Status Object
|
||||
// =======================
|
||||
|
||||
public function getStatus($status_serial = 0) {
|
||||
|
||||
$SQL = "select view_statuses.*
|
||||
from view_statuses
|
||||
where status_serial = {$status_serial}";
|
||||
|
||||
return $this->getTable("statuses", $SQL);
|
||||
}
|
||||
|
||||
// ===========================
|
||||
// Return a Statuss Object
|
||||
// ===========================
|
||||
|
||||
public function getStatuses() {
|
||||
|
||||
$SQL = "select view_statuses.*
|
||||
from view_statuses";
|
||||
|
||||
return $this->getTable("statuses", $SQL);
|
||||
}
|
||||
|
||||
// ============================
|
||||
// Return a Statuss Page Object
|
||||
// ============================
|
||||
|
||||
public function getStatusesPage() {
|
||||
|
||||
// Find Criteria
|
||||
|
||||
$find_status = filter_input(INPUT_POST, "find_status") ?: "";
|
||||
$find_status = $this->sanitizeString($find_status);
|
||||
|
||||
$find_words = implode("|", explode(" ", $find_status));
|
||||
|
||||
// Record Count
|
||||
|
||||
$connection = $this->connect();
|
||||
|
||||
$SQL = "select count(*) as count
|
||||
from view_statuses
|
||||
where status_name regexp :status_name
|
||||
or status_classes regexp :status_classes";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":status_name", $find_words);
|
||||
$statement->bindValue(":status_classes", $find_words);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$recordset = $statement->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$count = (count($recordset) > 0) ? (integer) $recordset["count"] : (integer) 0;
|
||||
|
||||
// Pagination
|
||||
|
||||
$pagination = filter_input(INPUT_POST, "pagination") ?: "";
|
||||
|
||||
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 = ($count / $this->pagination_size);
|
||||
break;
|
||||
}
|
||||
|
||||
$offset = (($this->pagination_page * $this->pagination_size) - $this->pagination_size);
|
||||
$start = ($offset + 1);
|
||||
$end = min($count, (($start + $this->pagination_size) - 1));
|
||||
|
||||
// Data
|
||||
|
||||
$SQL = "select view_statuses.*
|
||||
from view_statuses
|
||||
where status_name regexp :status_name
|
||||
or status_classes regexp :status_classes
|
||||
order by status_name
|
||||
limit {$this->pagination_size}
|
||||
offset {$offset}";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":status_name", $find_words);
|
||||
$statement->bindValue(":status_classes", $find_words);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$statuses = $this->getTableXML("statuses", $statement);
|
||||
|
||||
// Insert Pagination Attributes
|
||||
|
||||
$statuses->addAttribute("count", $count);
|
||||
$statuses->addAttribute("start", $start);
|
||||
$statuses->addAttribute("end", $end);
|
||||
$statuses->addAttribute("page", $this->pagination_page);
|
||||
|
||||
$_SESSION[self::PAGINATION_PAGE] = $this->pagination_page;
|
||||
|
||||
return $statuses;
|
||||
}
|
||||
|
||||
// ==============
|
||||
// Setup Statuses
|
||||
// ==============
|
||||
|
||||
public function setupStatuses() {
|
||||
|
||||
$statuses = $this->getStatusesPage();
|
||||
$popovers = (new Popovers())->getPopovers();
|
||||
|
||||
$XML = $this->mergeXML($statuses, "<XML/>");
|
||||
$XML = $this->mergeXML($popovers, $XML);
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("./system/setupStatuses"));
|
||||
|
||||
$this->displayContent($content);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,961 @@
|
||||
<?php
|
||||
|
||||
class Subscriptions 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;
|
||||
}
|
||||
|
||||
// =========================
|
||||
// Go To Subscription Driver
|
||||
// =========================
|
||||
|
||||
public function goToSubscription() {
|
||||
|
||||
$subscription_serial = (integer) filter_input(INPUT_POST, "subscription_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$usersubscription_serial = (integer) filter_input(INPUT_POST, "usersubscription_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$subscription = $this->getSubscription($subscription_serial);
|
||||
|
||||
if ($subscription->count() === 0) {
|
||||
$this->logError("Invalid Subscription ({$subscription_serial}): " . __METHOD__);
|
||||
}
|
||||
|
||||
switch ($subscription_serial) {
|
||||
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
|
||||
$_SESSION['subscription_serial'] = $subscription_serial;
|
||||
$_SESSION['usersubscription_serial'] = $usersubscription_serial;
|
||||
|
||||
(new PermitFacts())->searchPermitFacts();
|
||||
|
||||
break;
|
||||
|
||||
case 5:
|
||||
|
||||
$_SESSION['subscription_serial'] = $subscription_serial;
|
||||
$_SESSION['usersubscription_serial'] = $usersubscription_serial;
|
||||
|
||||
(new PlanningAndZoningFacts())->searchPlanningAndZoningFacts();
|
||||
|
||||
break;
|
||||
|
||||
case 6:
|
||||
|
||||
$_SESSION['subscription_serial'] = $subscription_serial;
|
||||
$_SESSION['usersubscription_serial'] = $usersubscription_serial;
|
||||
|
||||
(new PlanningAndZoningFacts())->planningAndZoningFactsBasic();
|
||||
|
||||
break;
|
||||
|
||||
case 7:
|
||||
|
||||
$_SESSION['subscription_serial'] = $subscription_serial;
|
||||
$_SESSION['usersubscription_serial'] = $usersubscription_serial;
|
||||
|
||||
(new BusinessFacts())->searchBusinessFacts();
|
||||
|
||||
break;
|
||||
case 8:
|
||||
|
||||
$_SESSION['subscription_serial'] = $subscription_serial;
|
||||
$_SESSION['usersubscription_serial'] = $usersubscription_serial;
|
||||
|
||||
(new BusinessFacts())->businessFactsBasic();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ===================
|
||||
// Setup Subscriptions
|
||||
// ===================
|
||||
|
||||
public function setupSubscriptions() {
|
||||
|
||||
$subscriptions = $this->getSubscriptionsPage();
|
||||
$popovers = (new Popovers())->getPopovers();
|
||||
|
||||
$XML = $this->mergeXML($subscriptions, "<XML/>");
|
||||
$XML = $this->mergeXML($popovers, $XML);
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("./system/setupSubscriptions"));
|
||||
|
||||
$this->displayContent($content);
|
||||
}
|
||||
|
||||
// ====================
|
||||
// Subscription Summary
|
||||
// ====================
|
||||
|
||||
public function subscriptionSummary() {
|
||||
|
||||
$subscription_serial = filter_input(INPUT_POST, "subscription_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$subscription = $this->getSubscription($subscription_serial);
|
||||
|
||||
if ($subscription->count() == 0) {
|
||||
$this->logError("Invalid Subscription ({$subscription_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$counties = $this->getSubscriptionCountiesByMarket($subscription->record->subscription_serial);
|
||||
$cities = $this->getSubscriptionCitiesByMarket($subscription->record->subscription_serial);
|
||||
|
||||
$XML = $this->mergeXML($subscription, "<XML/>");
|
||||
$XML = $this->mergeXML($counties, $XML);
|
||||
$XML = $this->mergeXML($cities, $XML);
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("./system/subscriptionSummary"));
|
||||
$this->displayContent($content);
|
||||
}
|
||||
|
||||
// ===================
|
||||
// Users Subscriptions
|
||||
// ===================
|
||||
|
||||
public function usersSubscriptions() {
|
||||
|
||||
$subscriptions = $this->getUsersActiveSubscriptions($this->current_user_serial);
|
||||
$popovers = (new Popovers())->getPopovers();
|
||||
|
||||
$XML = $this->mergeXML($subscriptions, "<XML/>");
|
||||
$XML = $this->mergeXML($popovers, $XML);
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("./system/userSubscriptions"));
|
||||
|
||||
$this->displayContent($content);
|
||||
}
|
||||
|
||||
// ================
|
||||
// Add Subscription
|
||||
// ================
|
||||
|
||||
public function addSubscription() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$dropdowns = (new Dropdowns())->getDropdowns();
|
||||
|
||||
$content = $this->applyXSL($dropdowns, $this->getXSL("./system/addSubscription"));
|
||||
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "add":
|
||||
|
||||
$subscription_title = filter_input(INPUT_POST, "subscription_title") ?: "";
|
||||
$subscription_service_level = filter_input(INPUT_POST, "subscription_service_level", FILTER_SANITIZE_NUMBER_INT) ?: "";
|
||||
$subscription_market = filter_input(INPUT_POST, "subscription_market", FILTER_SANITIZE_NUMBER_INT) ?: "";
|
||||
|
||||
$SQL = "insert into subscriptions
|
||||
|
||||
( subscription_title,
|
||||
subscription_service_level,
|
||||
subscription_market,
|
||||
subscription_creator,
|
||||
subscription_created )
|
||||
|
||||
VALUES ( :subscription_title,
|
||||
:subscription_service_level,
|
||||
:subscription_market,
|
||||
:subscription_creator,
|
||||
:subscription_created )";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":subscription_title", $subscription_title);
|
||||
$statement->bindValue(":subscription_service_level", $subscription_service_level);
|
||||
$statement->bindValue(":subscription_market", $subscription_market);
|
||||
$statement->bindValue(":subscription_creator", $this->current_user_name);
|
||||
$statement->bindValue(":subscription_created", $this->getTimestamp());
|
||||
|
||||
$statement->execute();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// =================
|
||||
// Edit Subscription
|
||||
// =================
|
||||
|
||||
public function editSubscription() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$subscription_serial = (integer) filter_input(INPUT_POST, "subscription_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$subscription = $this->getSubscription($subscription_serial);
|
||||
|
||||
if ($subscription->count() === 0) {
|
||||
$this->logError("Invalid Subscription ({$subscription_serial}): " . __METHOD__);
|
||||
}
|
||||
|
||||
$dropdowns = (new Dropdowns())->getDropdowns();
|
||||
|
||||
$XML = $this->mergeXML($dropdowns, "<XML/>");
|
||||
$XML = $this->mergeXML($subscription, $XML);
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("./system/editSubscription"));
|
||||
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "update":
|
||||
|
||||
$subscription_serial = filter_input(INPUT_POST, "subscription_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$subscription_title = filter_input(INPUT_POST, "subscription_title") ?: "";
|
||||
$subscription_service_level = filter_input(INPUT_POST, "subscription_service_level", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$subscription_market = filter_input(INPUT_POST, "subscription_market", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$subscriptions = $this->getSubscription($subscription_serial);
|
||||
|
||||
if ($subscriptions->count() == 0) {
|
||||
$this->logError("Invalid Subscription ({$subscription_serial}): " . __METHOD__);
|
||||
}
|
||||
|
||||
// Update the Subscription
|
||||
|
||||
$SQL = "update subscriptions
|
||||
set subscription_title = :subscription_title,
|
||||
subscription_service_level = :subscription_service_level,
|
||||
subscription_market = :subscription_market
|
||||
where subscription_serial = :subscription_serial";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":subscription_serial", $subscription_serial);
|
||||
$statement->bindValue(":subscription_title", $subscription_title);
|
||||
$statement->bindValue(":subscription_service_level", $subscription_service_level);
|
||||
$statement->bindValue(":subscription_market", $subscription_market);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// ===================
|
||||
// Delete Subscription
|
||||
// ===================
|
||||
|
||||
public function deleteSubscription() {
|
||||
|
||||
$subscription_serial = filter_input(INPUT_POST, "subscription_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$subscription = $this->getSubscription($subscription_serial);
|
||||
|
||||
if ($subscription->count() == 0) {
|
||||
$this->logError("Invalid Subscription ({$subscription_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$SQL = "delete from subscriptions
|
||||
where subscription_serial = {$subscription_serial}";
|
||||
|
||||
$this->executeSQL($SQL);
|
||||
}
|
||||
|
||||
// ========================
|
||||
// Add Subscription to User
|
||||
// ========================
|
||||
|
||||
public function addSubscriptionToUser() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$user_serial = filter_input(INPUT_POST, "user_reference", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$user = (new Users())->getUser($user_serial);
|
||||
$subscriptions = $this->getSubscriptions();
|
||||
|
||||
$XML = $this->mergeXML($user, "<XML/>");
|
||||
$XML = $this->mergeXML($subscriptions, $XML);
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("./system/addSubscriptionToUser"));
|
||||
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "add":
|
||||
|
||||
$subscription_serial = filter_input(INPUT_POST, "subscription_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$user_serial = filter_input(INPUT_POST, "user_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$subscription_start_date = filter_input(INPUT_POST, "subscription_start_date") ?: "";
|
||||
$subscription_end_date = filter_input(INPUT_POST, "subscription_end_date") ?: "";
|
||||
|
||||
$subscription_start_date = date("Y-m-d", strtotime($subscription_start_date));
|
||||
$subscription_end_date = date("Y-m-d", strtotime($subscription_end_date));
|
||||
|
||||
$SQL = "insert into usersubscriptions
|
||||
|
||||
( usersubscription_user,
|
||||
usersubscription_subscription,
|
||||
usersubscription_start_date,
|
||||
usersubscription_end_date,
|
||||
usersubscription_creator,
|
||||
usersubscription_created )
|
||||
|
||||
VALUES ( :usersubscription_user,
|
||||
:usersubscription_subscription,
|
||||
:usersubscription_start_date,
|
||||
:usersubscription_end_date,
|
||||
:usersubscription_creator,
|
||||
:usersubscription_created )";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":usersubscription_user", $user_serial);
|
||||
$statement->bindValue(":usersubscription_subscription", $subscription_serial);
|
||||
$statement->bindValue(":usersubscription_start_date", $subscription_start_date);
|
||||
$statement->bindValue(":usersubscription_end_date", $subscription_end_date);
|
||||
$statement->bindValue(":usersubscription_creator", $this->current_user_name);
|
||||
$statement->bindValue(":usersubscription_created", $this->getTimestamp());
|
||||
|
||||
$statement->execute();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================
|
||||
// Add County To Subscription
|
||||
// ==========================
|
||||
|
||||
public function addCountyToSubscription() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$subscription_serial = filter_input(INPUT_POST, "subscription_reference", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$subscription = $this->getSubscription($subscription_serial);
|
||||
|
||||
if ($subscription->count() === 0) {
|
||||
$this->logError("Invalid Subscription ({$subscription_serial}): " . __METHOD__);
|
||||
}
|
||||
|
||||
$counties = (new Counties())->getCounties();
|
||||
|
||||
$XML = $this->mergeXML($subscription, "<xml/>");
|
||||
$XML = $this->mergeXML($counties, $XML);
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("./system/addCountyToSubscription"));
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "add":
|
||||
|
||||
$subscription_serial = filter_input(INPUT_POST, "subscription_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$county_serial = filter_input(INPUT_POST, "county_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$SQL = "insert into subscriptioncounties
|
||||
|
||||
( subscriptioncounty_subscription,
|
||||
subscriptioncounty_county,
|
||||
subscriptioncounty_creator,
|
||||
subscriptioncounty_created )
|
||||
|
||||
VALUES ( :subscriptioncounty_subscription,
|
||||
:subscriptioncounty_county,
|
||||
:subscriptioncounty_creator,
|
||||
:subscriptioncounty_created )";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":subscriptioncounty_subscription", $subscription_serial);
|
||||
$statement->bindValue(":subscriptioncounty_county", $county_serial);
|
||||
$statement->bindValue(":subscriptioncounty_creator", $this->current_user_name);
|
||||
$statement->bindValue(":subscriptioncounty_created", $this->getTimestamp());
|
||||
|
||||
$statement->execute();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================
|
||||
// Edit a Subscriptions County
|
||||
// ===========================
|
||||
|
||||
public function editSubscriptionCounty() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$subscriptioncounty_serial = filter_input(INPUT_POST, "subscriptioncounty_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$subscriptioncounty = $this->getSubscriptionCounty($subscriptioncounty_serial);
|
||||
|
||||
if ($subscriptioncounty->count() === 0) {
|
||||
$this->logError("Invalid Subscription County ({$subscriptioncounty_serial}): " . __METHOD__);
|
||||
}
|
||||
|
||||
$counties = (new Counties())->getCounties();
|
||||
|
||||
$XML = $this->mergeXML($subscriptioncounty, "<xml/>");
|
||||
$XML = $this->mergeXML($counties, $XML);
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("./system/editSubscriptionCounty"));
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "update":
|
||||
|
||||
$subscriptioncounty_serial = filter_input(INPUT_POST, "subscriptioncounty_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$county_serial = filter_input(INPUT_POST, "county_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$SQL = "update subscriptioncounties
|
||||
set subscriptioncounty_county = :subscriptioncounty_county,
|
||||
subscriptioncounty_changer = :subscriptioncounty_changer,
|
||||
subscriptioncounty_changed = :subscriptioncounty_changed
|
||||
where subscriptioncounty_serial = :subscriptioncounty_serial";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":subscriptioncounty_serial", $subscriptioncounty_serial);
|
||||
$statement->bindValue(":subscriptioncounty_county", $county_serial);
|
||||
$statement->bindValue(":subscriptioncounty_changer", $this->current_user_name);
|
||||
$statement->bindValue(":subscriptioncounty_changed", $this->getTimestamp());
|
||||
|
||||
$statement->execute();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================
|
||||
// Delete Subscription County
|
||||
// ==========================
|
||||
|
||||
public function deleteSubscriptionCounty() {
|
||||
|
||||
$subscriptioncounty_serial = filter_input(INPUT_POST, "subscriptioncounty_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$subscriptioncounty = $this->getSubscriptionCounty($subscriptioncounty_serial);
|
||||
|
||||
if ($subscriptioncounty->count() == 0) {
|
||||
$this->logError("Invalid Subscription County ({$subscriptioncounty_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$SQL = "delete from subscriptioncounties where subscriptioncounty_serial = {$subscriptioncounty_serial}";
|
||||
|
||||
$this->executeSQL($SQL);
|
||||
}
|
||||
|
||||
// ===================================
|
||||
// Return a Subscription County Object
|
||||
// ===================================
|
||||
|
||||
public function getSubscriptionCounty($subscriptioncounty_serial = 0) {
|
||||
|
||||
$SQL = "select view_subscriptioncounties.*
|
||||
from view_subscriptioncounties
|
||||
where subscriptioncounty_serial = {$subscriptioncounty_serial}";
|
||||
|
||||
return $this->getTable("subscriptioncounty", $SQL);
|
||||
}
|
||||
|
||||
// ==========================
|
||||
// Add City To Subscription
|
||||
// ==========================
|
||||
|
||||
public function addCityToSubscription() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$subscription_serial = filter_input(INPUT_POST, "subscription_reference", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$subscription = $this->getSubscription($subscription_serial);
|
||||
|
||||
if ($subscription->count() === 0) {
|
||||
$this->logError("Invalid Subscription ({$subscription_serial}): " . __METHOD__);
|
||||
}
|
||||
|
||||
$cities = (new Cities())->getCities();
|
||||
|
||||
$XML = $this->mergeXML($subscription, "<xml/>");
|
||||
$XML = $this->mergeXML($cities, $XML);
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("./system/addCityToSubscription"));
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "add":
|
||||
|
||||
$subscription_serial = filter_input(INPUT_POST, "subscription_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$city_serial = filter_input(INPUT_POST, "city_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$SQL = "insert into subscriptioncities
|
||||
|
||||
( subscriptioncity_subscription,
|
||||
subscriptioncity_city,
|
||||
subscriptioncity_creator,
|
||||
subscriptioncity_created )
|
||||
|
||||
VALUES ( :subscriptioncity_subscription,
|
||||
:subscriptioncity_city,
|
||||
:subscriptioncity_creator,
|
||||
:subscriptioncity_created )";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":subscriptioncity_subscription", $subscription_serial);
|
||||
$statement->bindValue(":subscriptioncity_city", $city_serial);
|
||||
$statement->bindValue(":subscriptioncity_creator", $this->current_user_name);
|
||||
$statement->bindValue(":subscriptioncity_created", $this->getTimestamp());
|
||||
|
||||
$statement->execute();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================
|
||||
// Edit a Subscriptions City
|
||||
// ===========================
|
||||
|
||||
public function editSubscriptionCity() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$subscriptioncity_serial = filter_input(INPUT_POST, "subscriptioncity_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$subscriptioncity = $this->getSubscriptionCity($subscriptioncity_serial);
|
||||
|
||||
if ($subscriptioncity->count() === 0) {
|
||||
$this->logError("Invalid Subscription City ({$subscriptioncity_serial}): " . __METHOD__);
|
||||
}
|
||||
|
||||
$cities = (new Cities())->getCities();
|
||||
|
||||
$XML = $this->mergeXML($subscriptioncity, "<xml/>");
|
||||
$XML = $this->mergeXML($cities, $XML);
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("./system/editSubscriptionCity"));
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "update":
|
||||
|
||||
$subscriptioncity_serial = filter_input(INPUT_POST, "subscriptioncity_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$city_serial = filter_input(INPUT_POST, "city_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$SQL = "update subscriptioncities
|
||||
set subscriptioncity_city = :subscriptioncity_city,
|
||||
subscriptioncity_changer = :subscriptioncity_changer,
|
||||
subscriptioncity_changed = :subscriptioncity_changed
|
||||
where subscriptioncity_serial = :subscriptioncity_serial";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":subscriptioncity_serial", $subscriptioncity_serial);
|
||||
$statement->bindValue(":subscriptioncity_city", $city_serial);
|
||||
$statement->bindValue(":subscriptioncity_changer", $this->current_user_name);
|
||||
$statement->bindValue(":subscriptioncity_changed", $this->getTimestamp());
|
||||
|
||||
$statement->execute();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================
|
||||
// Delete Subscription City
|
||||
// ==========================
|
||||
|
||||
public function deleteSubscriptionCity() {
|
||||
|
||||
$subscriptioncity_serial = filter_input(INPUT_POST, "subscriptioncity_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$subscriptioncity = $this->getSubscriptionCity($subscriptioncity_serial);
|
||||
|
||||
if ($subscriptioncity->count() == 0) {
|
||||
$this->logError("Invalid Subscription City ({$subscriptioncity_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$SQL = "delete from subscriptioncities where subscriptioncity_serial = {$subscriptioncity_serial}";
|
||||
|
||||
$this->executeSQL($SQL);
|
||||
}
|
||||
|
||||
// ===================================
|
||||
// Return a Subscription City Object
|
||||
// ===================================
|
||||
|
||||
public function getSubscriptionCity($subscriptioncity_serial = 0) {
|
||||
|
||||
$SQL = "select view_subscriptioncities.*
|
||||
from view_subscriptioncities
|
||||
where subscriptioncity_serial = {$subscriptioncity_serial}";
|
||||
|
||||
return $this->getTable("subscriptioncity", $SQL);
|
||||
}
|
||||
|
||||
// =========================
|
||||
// Edit a Users Subscription
|
||||
// =========================
|
||||
|
||||
public function editUsersSubscription() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$user_serial = filter_input(INPUT_POST, "user_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$usersubscription_serial = filter_input(INPUT_POST, "usersubscription_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$user = (new Users())->getUser($user_serial);
|
||||
$usersubscription = $this->getUsersSubscription($usersubscription_serial);
|
||||
$subscriptions = $this->getSubscriptionsPage();
|
||||
|
||||
$XML = $this->mergeXML($user, "<XML/>");
|
||||
$XML = $this->mergeXML($usersubscription, $XML);
|
||||
$XML = $this->mergeXML($subscriptions, $XML);
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("./system/editUsersSubscription"));
|
||||
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "update":
|
||||
|
||||
$usersubscription_serial = filter_input(INPUT_POST, "usersubscription_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$subscription_start_date = filter_input(INPUT_POST, "subscription_start_date") ?: "";
|
||||
$subscription_end_date = filter_input(INPUT_POST, "subscription_end_date") ?: "";
|
||||
|
||||
$subscription_start_date = date("Y-m-d", strtotime($subscription_start_date));
|
||||
$subscription_end_date = date("Y-m-d", strtotime($subscription_end_date));
|
||||
|
||||
$SQL = "update usersubscriptions
|
||||
set usersubscription_start_date = :usersubscription_start_date,
|
||||
usersubscription_end_date = :usersubscription_end_date,
|
||||
usersubscription_changer = :usersubscription_changer,
|
||||
usersubscription_changed = :usersubscription_changed
|
||||
where usersubscription_serial = :usersubscription_serial";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":usersubscription_start_date", $subscription_start_date);
|
||||
$statement->bindValue(":usersubscription_end_date", $subscription_end_date);
|
||||
$statement->bindValue(":usersubscription_serial", $usersubscription_serial);
|
||||
$statement->bindValue(":usersubscription_changer", $this->current_user_name);
|
||||
$statement->bindValue(":usersubscription_changed", $this->getTimestamp());
|
||||
|
||||
$statement->execute();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// =========================
|
||||
// Delete Users Subscription
|
||||
// =========================
|
||||
|
||||
public function deleteUsersSubscription() {
|
||||
|
||||
$usersubscription_serial = filter_input(INPUT_POST, "usersubscription_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$subscription = $this->getUsersSubscription($usersubscription_serial);
|
||||
|
||||
if ($subscription->count() == 0) {
|
||||
$this->logError("Invalid Subscription ({$usersubscription_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$SQL = "delete from usersubscriptions
|
||||
where usersubscription_serial = {$usersubscription_serial}";
|
||||
|
||||
$this->executeSQL($SQL);
|
||||
}
|
||||
|
||||
// ============================
|
||||
// Return a Subscription Object
|
||||
// ============================
|
||||
|
||||
public function getSubscription($subscription_serial = 0) {
|
||||
|
||||
$SQL = "select view_subscriptions.*
|
||||
from view_subscriptions
|
||||
where subscription_serial = {$subscription_serial}";
|
||||
|
||||
return $this->getTable("subscriptions", $SQL);
|
||||
}
|
||||
|
||||
// ============================
|
||||
// Return a Subscription Object
|
||||
// ============================
|
||||
|
||||
public function getSubscriptions() {
|
||||
|
||||
$SQL = "select view_subscriptions.*
|
||||
from view_subscriptions";
|
||||
|
||||
return $this->getTable("subscriptions", $SQL);
|
||||
}
|
||||
|
||||
// ==================================
|
||||
// Return a Subscriptions Page Object
|
||||
// ==================================
|
||||
|
||||
public function getSubscriptionsPage() {
|
||||
|
||||
// Find Criteria
|
||||
|
||||
$find_subscription = filter_input(INPUT_POST, "find_subscription") ?: "";
|
||||
$find_subscription = $this->sanitizeString($find_subscription);
|
||||
|
||||
$find_words = implode("|", explode(" ", $find_subscription));
|
||||
|
||||
// Record Count
|
||||
|
||||
$connection = $this->connect();
|
||||
|
||||
$SQL = "select count(*) as count
|
||||
from view_subscriptions
|
||||
where subscription_title regexp :subscription_title
|
||||
or subscription_service_level regexp :subscription_service_level
|
||||
or subscription_market regexp :subscription_market";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":subscription_title", $find_words);
|
||||
$statement->bindValue(":subscription_service_level", $find_words);
|
||||
$statement->bindValue(":subscription_market", $find_words);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$recordset = $statement->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$count = (count($recordset) > 0) ? (integer) $recordset["count"] : (integer) 0;
|
||||
|
||||
// Pagination
|
||||
|
||||
$pagination = filter_input(INPUT_POST, "pagination") ?: "";
|
||||
|
||||
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 = ($count / $this->pagination_size);
|
||||
break;
|
||||
}
|
||||
|
||||
$offset = (($this->pagination_page * $this->pagination_size) - $this->pagination_size);
|
||||
$start = ($offset + 1);
|
||||
$end = min($count, (($start + $this->pagination_size) - 1));
|
||||
|
||||
// Data
|
||||
|
||||
$SQL = "select view_subscriptions.*
|
||||
from view_subscriptions
|
||||
where subscription_title regexp :subscription_title
|
||||
or subscription_service_level regexp :subscription_service_level
|
||||
or subscription_market regexp :subscription_market
|
||||
order by subscription_title
|
||||
limit {$this->pagination_size}
|
||||
offset {$offset}";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":subscription_title", $find_words);
|
||||
$statement->bindValue(":subscription_service_level", $find_words);
|
||||
$statement->bindValue(":subscription_market", $find_words);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$subscriptions = $this->getTableXML("subscriptions", $statement);
|
||||
|
||||
// Insert Pagination Attributes
|
||||
|
||||
$subscriptions->addAttribute("count", $count);
|
||||
$subscriptions->addAttribute("start", $start);
|
||||
$subscriptions->addAttribute("end", $end);
|
||||
$subscriptions->addAttribute("page", $this->pagination_page);
|
||||
|
||||
$_SESSION[self::PAGINATION_PAGE] = $this->pagination_page;
|
||||
|
||||
return $subscriptions;
|
||||
}
|
||||
|
||||
// ============================
|
||||
// Return a Users Subscriptions
|
||||
// ============================
|
||||
|
||||
public function getUsersActiveSubscriptions($user_serial) {
|
||||
|
||||
$SQL = "select view_usersubscriptions.*
|
||||
from view_usersubscriptions
|
||||
where usersubscription_user = {$user_serial}";
|
||||
// order by view_usersubscriptions.subscription_title";
|
||||
|
||||
return $this->getTable("usersubscriptions", $SQL);
|
||||
}
|
||||
|
||||
// ===========================
|
||||
// Return a Users Subscription
|
||||
// ===========================
|
||||
|
||||
public function getUsersSubscription($usersubscription_serial) {
|
||||
|
||||
$SQL = "select view_usersubscriptions.*
|
||||
from view_usersubscriptions
|
||||
where usersubscription_serial = {$usersubscription_serial}";
|
||||
|
||||
return $this->getTable("usersubscription", $SQL);
|
||||
}
|
||||
|
||||
// ==================================
|
||||
// Determine if a Subscription exists
|
||||
// ==================================
|
||||
|
||||
public function subscriptionExists() {
|
||||
|
||||
$subscription_serial = filter_input(INPUT_POST, "subscription_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$subscription_title = filter_input(INPUT_POST, "subscription_title") ?: "";
|
||||
|
||||
$SQL = "select subscription_serial
|
||||
from view_subscriptions
|
||||
where subscription_serial != :subscription_serial
|
||||
and lower(subscription_title) = :subscription_title";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":subscription_serial", $subscription_serial);
|
||||
$statement->bindValue(":subscription_title", strtolower($subscription_title));
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$recordset = $statement->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$exists = (count($recordset) > 0) ? true : false;
|
||||
|
||||
echo json_encode($exists);
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// Return a Subscriptions Assigned Counties
|
||||
// ========================================
|
||||
|
||||
public function getSubscriptionCountiesByMarket($subscription_serial) {
|
||||
|
||||
$SQL = "select view_subscriptioncounties.*
|
||||
from view_subscriptioncounties
|
||||
where subscriptioncounty_subscription = {$subscription_serial}";
|
||||
|
||||
return $this->getTable("subscriptioncounties", $SQL);
|
||||
}
|
||||
|
||||
// ======================================
|
||||
// Return a Subscriptions Assigned Cities
|
||||
// ======================================
|
||||
|
||||
public function getSubscriptionCitiesByMarket($subscription_serial) {
|
||||
|
||||
$SQL = "select view_subscriptioncities.*
|
||||
from view_subscriptioncities
|
||||
where subscriptioncity_subscription = {$subscription_serial}";
|
||||
|
||||
return $this->getTable("subscriptioncities", $SQL);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,749 @@
|
||||
<?php
|
||||
|
||||
// ===========
|
||||
// Users Class
|
||||
// ===========
|
||||
|
||||
class Users extends Base {
|
||||
|
||||
// Variables
|
||||
|
||||
private $current_user_id = "";
|
||||
private $current_user_serial = "";
|
||||
private $current_user_name = "";
|
||||
private $current_user_client_name = "";
|
||||
private $current_user_email = "";
|
||||
private $pagination_size = 20;
|
||||
private $pagination_page = 1;
|
||||
|
||||
// ================================
|
||||
// __construct : Class Constructor.
|
||||
// ================================
|
||||
|
||||
public function __construct() {
|
||||
|
||||
set_error_handler(array($this, "displayError"));
|
||||
|
||||
date_default_timezone_set(self::TIMEZONE);
|
||||
|
||||
$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->current_user_client_name = $_SESSION[self::USER_CLIENT_NAME] ?? "";
|
||||
|
||||
$this->pagination_page = $_SESSION[self::PAGINATION_PAGE] ?? 1;
|
||||
}
|
||||
|
||||
// ===========
|
||||
// Setup Users
|
||||
// ===========
|
||||
|
||||
public function setupUsers() {
|
||||
|
||||
$users = $this->getUsersPage();
|
||||
$popovers = (new Popovers())->getPopovers();
|
||||
|
||||
$XML = $this->mergeXML($users, "<XML/>");
|
||||
$XML = $this->mergeXML($popovers, $XML);
|
||||
|
||||
$html = $this->applyXSL($XML, $this->getXSL("./system/setupUsers"));
|
||||
|
||||
$this->displayContent($html);
|
||||
}
|
||||
|
||||
// ============
|
||||
// User Summary
|
||||
// ============
|
||||
|
||||
public function userSummary() {
|
||||
|
||||
$user_serial = filter_input(INPUT_POST, "user_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$user = $this->getUser($user_serial);
|
||||
|
||||
if ($user->count() == 0) {
|
||||
$this->logError("Invalid User ({$user_serial}). " . __METHOD__);
|
||||
}
|
||||
|
||||
$notes = (new Notes())->getAllNotes($user_serial);
|
||||
// $subscriptions = (new Subscriptions())->getUsersActiveSubscriptions($user_serial);
|
||||
|
||||
$XML = $this->mergeXML($user, "<XML/>");
|
||||
// $XML = $this->mergeXML($subscriptions, $XML);
|
||||
$XML = $this->mergeXML($notes, $XML);
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("./system/userSummary"));
|
||||
|
||||
$this->displayContent($content);
|
||||
}
|
||||
|
||||
// ========
|
||||
// Add User
|
||||
// ========
|
||||
|
||||
public function addUser() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$popovers = (new Popovers())->getPopovers();
|
||||
$constants = $this->getConstants();
|
||||
|
||||
$XML = $this->mergeXML($popovers, "<XML/>");
|
||||
$XML = $this->mergeXML($constants, $XML);
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("./system/addUser"));
|
||||
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "add":
|
||||
|
||||
$user_name = filter_input(INPUT_POST, "user_name") ?: "";
|
||||
$user_client_name = filter_input(INPUT_POST, "user_client_name") ?: "";
|
||||
$user_email = filter_input(INPUT_POST, "user_email") ?: "";
|
||||
$user_role = filter_input(INPUT_POST, "user_role") ?: "";
|
||||
|
||||
$user_name = strtoupper(preg_replace("/\s+/", " ", $user_name));
|
||||
|
||||
$user_random_password = $this->generateRandomPassword();
|
||||
$user_temp_password = password_hash($user_random_password, PASSWORD_DEFAULT);
|
||||
|
||||
$user_change_password = (boolean) true;
|
||||
$user_active = (boolean) true;
|
||||
|
||||
// Add the User
|
||||
|
||||
$connection = $this->connect();
|
||||
|
||||
$SQL = "insert into users
|
||||
|
||||
( user_name,
|
||||
user_email,
|
||||
user_client_name,
|
||||
user_password,
|
||||
user_role,
|
||||
user_change_password,
|
||||
user_active,
|
||||
user_creator,
|
||||
user_created )
|
||||
|
||||
values ( :user_name,
|
||||
:user_email,
|
||||
:user_client_name,
|
||||
:user_password,
|
||||
:user_role,
|
||||
:user_change_password,
|
||||
:user_active,
|
||||
:user_creator,
|
||||
:user_created )";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":user_name", $user_name);
|
||||
$statement->bindValue(":user_email", $user_email);
|
||||
$statement->bindValue(":user_client_name", $user_client_name);
|
||||
$statement->bindValue(":user_password", $user_temp_password);
|
||||
$statement->bindValue(":user_role", $user_role);
|
||||
$statement->bindValue(":user_change_password", $user_change_password, PDO::PARAM_BOOL);
|
||||
$statement->bindValue(":user_active", $user_active, PDO::PARAM_BOOL);
|
||||
$statement->bindValue(":user_creator", $this->current_user_name);
|
||||
$statement->bindValue(":user_created", $this->getTimestamp());
|
||||
|
||||
if (!$statement->execute()) {
|
||||
trigger_error($statement->errorInfo()[2]);
|
||||
}
|
||||
|
||||
$user = $this->getUserByUserName($user_name);
|
||||
|
||||
// Send User Credentials
|
||||
|
||||
(new Email())->emailNewUserCredentials($user, $user_random_password);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// ===========
|
||||
// Delete User
|
||||
// ===========
|
||||
|
||||
public function deleteUser() {
|
||||
|
||||
$user_serial = filter_input(INPUT_POST, "user_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$users = $this->getUser($user_serial);
|
||||
|
||||
if ($users->count() == 0) {
|
||||
$this->logError("Invalid User ({$user_serial}): " . __METHOD__);
|
||||
}
|
||||
|
||||
$SQL = "delete from users
|
||||
where user_serial = {$user_serial}";
|
||||
|
||||
$this->executeSQL($SQL);
|
||||
}
|
||||
|
||||
// =========
|
||||
// Edit User
|
||||
// =========
|
||||
|
||||
public function editUser() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$user_serial = (integer) filter_input(INPUT_POST, "user_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$user = $this->getUser($user_serial);
|
||||
|
||||
if ($user->count() === 0) {
|
||||
$this->logError("Invalid User ({$user_serial}): " . __METHOD__);
|
||||
}
|
||||
|
||||
$popovers = (new Popovers())->getPopovers();
|
||||
$constants = $this->getConstants();
|
||||
|
||||
$XML = $this->mergeXML($user, "<XML/>");
|
||||
$XML = $this->mergeXML($popovers, $XML);
|
||||
$XML = $this->mergeXML($constants, $XML);
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("./system/editUser"));
|
||||
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "update":
|
||||
|
||||
$user_serial = filter_input(INPUT_POST, "user_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$user_name = filter_input(INPUT_POST, "user_name") ?: "";
|
||||
$user_email = filter_input(INPUT_POST, "user_email") ?: "";
|
||||
$user_client_name = filter_input(INPUT_POST, "user_client_name") ?: "";
|
||||
$user_role = filter_input(INPUT_POST, "user_role") ?: "";
|
||||
$user_active = filter_input(INPUT_POST, "user_active", FILTER_VALIDATE_BOOLEAN) ?: false;
|
||||
|
||||
$users = $this->getUser($user_serial);
|
||||
|
||||
if ($users->count() == 0) {
|
||||
$this->logError("Invalid User ({$user_serial}): " . __METHOD__);
|
||||
}
|
||||
|
||||
// Update the User
|
||||
|
||||
$SQL = "update users
|
||||
set user_name = :user_name,
|
||||
user_email = :user_email,
|
||||
user_client_name = :user_client_name,
|
||||
user_role = :user_role,
|
||||
user_active = :user_active,
|
||||
user_changer = :user_changer,
|
||||
user_changed = :user_changed
|
||||
where user_serial = :user_serial";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":user_serial", $user_serial);
|
||||
$statement->bindValue(":user_name", $user_name);
|
||||
$statement->bindValue(":user_email", $user_email);
|
||||
$statement->bindValue(":user_client_name", $user_client_name);
|
||||
$statement->bindValue(":user_role", $user_role);
|
||||
$statement->bindValue(":user_active", $user_active, PDO::PARAM_BOOL);
|
||||
$statement->bindValue(":user_changer", $this->current_user_name);
|
||||
$statement->bindValue(":user_changed", $this->getTimestamp());
|
||||
|
||||
$statement->execute();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// ====================
|
||||
// Return a User Object
|
||||
// ====================
|
||||
|
||||
public function getUser($user_serial = 0) {
|
||||
|
||||
$SQL = "select view_users.*
|
||||
from view_users
|
||||
where user_serial = {$user_serial}";
|
||||
|
||||
return $this->getTable("users", $SQL);
|
||||
}
|
||||
|
||||
// ====================
|
||||
// Return a User Object
|
||||
// ====================
|
||||
|
||||
public function getUserByUserName($user_name) {
|
||||
|
||||
$SQL = "select view_users.*
|
||||
from view_users
|
||||
where user_id = '{$user_name}'
|
||||
or user_client_name = '{$user_name}'";
|
||||
|
||||
return $this->getTable("user", $SQL);
|
||||
}
|
||||
|
||||
// ======================
|
||||
// Return a User's Serial
|
||||
// ======================
|
||||
|
||||
public function getUserSerial($user_id = "") {
|
||||
|
||||
$users = $this->getUserByUserId($user_id);
|
||||
|
||||
return ($users->count() === 0) ? 0 : (integer) $users->record->user_serial;
|
||||
}
|
||||
|
||||
// =====================
|
||||
// Return a Users Object
|
||||
// =====================
|
||||
|
||||
public function getUsers() {
|
||||
|
||||
$SQL = "select view_users.*
|
||||
from view_users";
|
||||
|
||||
return $this->getTable("users", $SQL);
|
||||
}
|
||||
|
||||
// ==========================
|
||||
// Return a Users Page Object
|
||||
// ==========================
|
||||
|
||||
public function getUsersPage() {
|
||||
|
||||
// Find Criteria
|
||||
|
||||
$find_user = filter_input(INPUT_POST, "find_user") ?: "";
|
||||
$find_user = $this->sanitizeString($find_user);
|
||||
|
||||
$find_words = implode("|", explode(" ", $find_user));
|
||||
|
||||
// Record Count
|
||||
|
||||
$connection = $this->connect();
|
||||
|
||||
$SQL = "select count(*) as count
|
||||
from view_users
|
||||
where user_name regexp :user_name
|
||||
or user_client_name regexp :user_client_name
|
||||
or user_email regexp :user_email
|
||||
or user_role regexp :user_role";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":user_name", $find_words);
|
||||
$statement->bindValue(":user_client_name", $find_words);
|
||||
$statement->bindValue(":user_email", $find_words);
|
||||
$statement->bindValue(":user_role", $find_words);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$recordset = $statement->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$count = (count($recordset) > 0) ? (integer) $recordset["count"] : (integer) 0;
|
||||
|
||||
// Pagination
|
||||
|
||||
$pagination = filter_input(INPUT_POST, "pagination") ?: "";
|
||||
|
||||
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 = ($count / $this->pagination_size);
|
||||
break;
|
||||
}
|
||||
|
||||
$offset = (($this->pagination_page * $this->pagination_size) - $this->pagination_size);
|
||||
$start = ($offset + 1);
|
||||
$end = min($count, (($start + $this->pagination_size) - 1));
|
||||
|
||||
// Data
|
||||
|
||||
$SQL = "select view_users.*
|
||||
from view_users
|
||||
where user_name regexp :user_name
|
||||
or user_client_name regexp :user_client_name
|
||||
or user_email regexp :user_email
|
||||
or user_role regexp :user_role
|
||||
limit {$this->pagination_size}
|
||||
offset {$offset}";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":user_name", $find_words);
|
||||
$statement->bindValue(":user_client_name", $find_words);
|
||||
$statement->bindValue(":user_email", $find_words);
|
||||
$statement->bindValue(":user_role", $find_words);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$users = $this->getTableXML("users", $statement);
|
||||
|
||||
// Insert Pagination Attributes
|
||||
|
||||
$users->addAttribute("count", $count);
|
||||
$users->addAttribute("start", $start);
|
||||
$users->addAttribute("end", $end);
|
||||
$users->addAttribute("page", $this->pagination_page);
|
||||
|
||||
$_SESSION[self::PAGINATION_PAGE] = $this->pagination_page;
|
||||
|
||||
return $users;
|
||||
}
|
||||
|
||||
// ===========================
|
||||
// Return an User Object(AJAX)
|
||||
// ===========================
|
||||
|
||||
public function getUser_AJAX($user_name = "") {
|
||||
|
||||
$user_name = filter_input(INPUT_POST, "user_name") ?: $user_name;
|
||||
|
||||
$users = $this->getUserByUserName($user_name);
|
||||
|
||||
// Create the User Object.
|
||||
|
||||
$User = array();
|
||||
|
||||
$User["exists"] = ($users->count() > 0) ? true : false;
|
||||
|
||||
if ($_SESSION[self::AJAX]) {
|
||||
echo json_encode($User);
|
||||
} else {
|
||||
return $User;
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================
|
||||
// Determine if a User Exists
|
||||
// ==========================
|
||||
|
||||
public function userExists() {
|
||||
|
||||
$user_serial = filter_input(INPUT_POST, "user_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$user_id = filter_input(INPUT_POST, "user_id") ?: "";
|
||||
|
||||
$user_id = strtolower(trim(preg_replace("/\s+/", " ", $user_id)));
|
||||
|
||||
$SQL = "select user_id
|
||||
from view_users
|
||||
where user_serial != :user_serial
|
||||
and user_id = :user_id";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":user_serial", $user_serial);
|
||||
$statement->bindValue(":user_id", $user_id);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$recordset = $statement->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$exists = (count($recordset) > 0) ? true : false;
|
||||
|
||||
echo json_encode($exists);
|
||||
}
|
||||
|
||||
// =============================
|
||||
// Determine if a User is Active
|
||||
// =============================
|
||||
|
||||
public function userActive() {
|
||||
|
||||
$user_serial = (integer) filter_input(INPUT_POST, "user_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$SQL = "select request_serial
|
||||
from requests
|
||||
where request_user = {$user_serial}";
|
||||
|
||||
$requests = $this->getTable("requests", $SQL);
|
||||
|
||||
$active = ($requests->count() > 0) ? true : $active;
|
||||
|
||||
echo json_encode($active);
|
||||
}
|
||||
|
||||
// ========================
|
||||
// Login to the application
|
||||
// ========================
|
||||
|
||||
public function login() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$XSLParms["BTN_SUBMIT"] = "main.php?action=Users.login&step=authenticate";
|
||||
$XSLParms["INVALID_SIGNIN"] = "FALSE";
|
||||
|
||||
echo $this->applyXSL("", $this->getXSL("./system/signIn"), $XSLParms);
|
||||
exit();
|
||||
|
||||
break;
|
||||
|
||||
case "authenticate":
|
||||
|
||||
$user_name = filter_input(INPUT_POST, "user_name") ?: "";
|
||||
$user_password = filter_input(INPUT_POST, "user_password") ?: "";
|
||||
|
||||
// The User must exist in the Users Table
|
||||
|
||||
$user = $this->getUserByUserName($user_name);
|
||||
|
||||
// Automatically deny authentication if user is inactive
|
||||
|
||||
if ($user->record->user_active == 0) {
|
||||
|
||||
$XSLParms["BTN_SUBMIT"] = "main.php?action=Users.signIn&step=authenticate";
|
||||
$XSLParms["INVALID_SIGNIN"] = "TRUE";
|
||||
|
||||
echo $this->applyXSL("", $this->getXSL("./system/signIn"), $XSLParms);
|
||||
die();
|
||||
}
|
||||
|
||||
if ($user->count() > 0) {
|
||||
|
||||
$stored_hashed_password = $user->record->user_password;
|
||||
|
||||
// Verify Password
|
||||
|
||||
if (password_verify($user_password, $stored_hashed_password)) {
|
||||
|
||||
$this->initializeSession();
|
||||
|
||||
$_SESSION[self::USER_AUTHENTICATED] = true;
|
||||
$_SESSION[self::USER_SERIAL] = (integer) $user->record->user_serial;
|
||||
$_SESSION[self::USER_ID] = (string) $user->record->user_id;
|
||||
$_SESSION[self::USER_NAME] = (string) $user->record->user_name;
|
||||
$_SESSION[self::USER_EMAIL] = (string) $user->record->user_email;
|
||||
$_SESSION[self::USER_CLIENT_NAME] = (string) $user->record->user_client_name;
|
||||
$_SESSION[self::USER_ROLE] = (string) $user->record->user_role;
|
||||
|
||||
$this->current_user_id = $_SESSION[self::USER_ID] ?? "";
|
||||
$this->current_user_serial = $_SESSION[self::USER_SERIAL] ?? 0;
|
||||
$this->current_user_name = $_SESSION[self::USER_NAME] ?? "";
|
||||
$this->current_user_email = $_SESSION[self::USER_EMAIL] ?? "";
|
||||
|
||||
// Determine if this is a System Administrator
|
||||
|
||||
if (count($this->getSettings()->xpath("//SystemAdministrator[. = '{$user_name}']")) > 0) {
|
||||
|
||||
$_SESSION[self::USER_ROLE] = "System Administrator";
|
||||
}
|
||||
|
||||
// Create Journal Entry and finish
|
||||
(new Journal())->journalEntry("{$_SESSION[self::USER_NAME]} logged in ({$_SESSION[self::USER_ROLE]}).");
|
||||
|
||||
$this->updateLogin();
|
||||
|
||||
header("Location: ./");
|
||||
exit();
|
||||
} else {
|
||||
|
||||
$XSLParms["BTN_SUBMIT"] = "main.php?action=Users.signIn&step=authenticate";
|
||||
$XSLParms["INVALID_SIGNIN"] = "TRUE";
|
||||
|
||||
echo $this->applyXSL("", $this->getXSL("./system/signIn"), $XSLParms);
|
||||
die();
|
||||
}
|
||||
} else {
|
||||
|
||||
$XSLParms["BTN_SUBMIT"] = "main.php?action=Users.signIn&step=authenticate";
|
||||
$XSLParms["INVALID_SIGNIN"] = "TRUE";
|
||||
|
||||
echo $this->applyXSL("", $this->getXSL("./system/signIn"), $XSLParms);
|
||||
die();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// User NOT Validated.
|
||||
header("Location: ./");
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
// ===============
|
||||
// Change Password
|
||||
// ===============
|
||||
|
||||
public function changePassword() {
|
||||
|
||||
$step = filter_input(INPUT_POST, "step") ?: "prompt";
|
||||
|
||||
switch ($step) {
|
||||
|
||||
case "prompt":
|
||||
|
||||
$popovers = (new Popovers())->getPopovers();
|
||||
$XML = $this->mergeXML($popovers, "<XML/>");
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("./system/changePassword"));
|
||||
$this->displayContent($content);
|
||||
|
||||
break;
|
||||
|
||||
case "change":
|
||||
|
||||
$user_serial = $_SESSION[self::USER_SERIAL];
|
||||
$user_new_password = filter_input(INPUT_POST, "user_new_password") ?: "";
|
||||
$user_verify_password = filter_input(INPUT_POST, "user_verify_password") ?: "";
|
||||
|
||||
if (!$user_new_password == $user_verify_password) {
|
||||
$this->initializeSession();
|
||||
}
|
||||
|
||||
$user_new_hashed_password = password_hash($user_new_password, PASSWORD_DEFAULT);
|
||||
|
||||
// Update User Password
|
||||
|
||||
$connection = $this->connect();
|
||||
|
||||
$SQL = "update users
|
||||
set user_password = :user_password,
|
||||
user_change_password = :user_change_password,
|
||||
user_changer = :user_changer,
|
||||
user_changed = :user_changed
|
||||
where user_serial = :user_serial";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":user_serial", $user_serial);
|
||||
$statement->bindValue(":user_password", $user_new_hashed_password);
|
||||
$statement->bindValue(":user_change_password", 0);
|
||||
$statement->bindValue(":user_changer", $this->current_user_name);
|
||||
$statement->bindValue(":user_changed", $this->getTimestamp());
|
||||
|
||||
if (!$statement->execute()) {
|
||||
$this->debug($statement->errorInfo()[2]);
|
||||
}
|
||||
|
||||
(new Journal())->journalEntry("{$_SESSION[self::USER_NAME]} changed their password.");
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$this->displayHome();
|
||||
}
|
||||
}
|
||||
|
||||
// ==============
|
||||
// Reset Password
|
||||
// ==============
|
||||
|
||||
public function resetPassword() {
|
||||
|
||||
$reset = false;
|
||||
|
||||
$user_serial = filter_input(INPUT_POST, "user_serial") ?: "";
|
||||
|
||||
$user = $this->getUser($user_serial);
|
||||
|
||||
$user_name = $user->record->user_name;
|
||||
|
||||
$user_random_password = $this->generateRandomPassword();
|
||||
$user_temp_password = password_hash($user_random_password, PASSWORD_DEFAULT);
|
||||
|
||||
// Update User Password
|
||||
|
||||
$connection = $this->connect();
|
||||
|
||||
$SQL = "update users
|
||||
set user_password = :user_password,
|
||||
user_change_password = :user_change_password
|
||||
where user_serial = :user_serial";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":user_serial", $user_serial);
|
||||
$statement->bindValue(":user_password", $user_temp_password);
|
||||
$statement->bindValue(":user_change_password", 1);
|
||||
|
||||
if (!$statement->execute()) {
|
||||
$this->debug($statement->errorInfo()[2]);
|
||||
} else {
|
||||
$reset = true;
|
||||
}
|
||||
|
||||
// Send User Credentials
|
||||
|
||||
(new Email())->emailUserPasswordResetLink($user, $user_random_password);
|
||||
|
||||
(new Journal())->journalEntry("{$_SESSION[self::USER_NAME]} reset {$user_name}'s password.");
|
||||
|
||||
echo json_encode($reset);
|
||||
}
|
||||
|
||||
// ===============================================
|
||||
// Update the Login timestamp for the current User
|
||||
// ===============================================
|
||||
|
||||
public function updateLogin() {
|
||||
|
||||
$SQL = "update users
|
||||
set user_login = :user_login
|
||||
where user_serial = :user_serial";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":user_login", $this->getTimestamp());
|
||||
$statement->bindValue(":user_serial", $this->current_user_serial);
|
||||
|
||||
$statement->execute();
|
||||
}
|
||||
|
||||
// ====================
|
||||
// Update Active Status
|
||||
// ====================
|
||||
|
||||
public function updateActiveStatus() {
|
||||
|
||||
$user_serial = filter_input(INPUT_POST, "user_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
$user_active = filter_input(INPUT_POST, "user_active", FILTER_SANITIZE_NUMBER_INT) ?: 0;
|
||||
|
||||
$SQL = "update users
|
||||
set user_active = :user_active,
|
||||
user_changed = :user_changed,
|
||||
user_changer = :user_changer
|
||||
where user_serial = :user_serial";
|
||||
|
||||
$statement = $this->connect()->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":user_serial", $user_serial);
|
||||
$statement->bindValue(":user_active", $user_active);
|
||||
$statement->bindValue(":user_changed", $this->getTimestamp());
|
||||
$statement->bindValue(":user_changer", $this->current_user_name);
|
||||
|
||||
if (!$statement->execute()) {
|
||||
error_log($statement->errorInfo()[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
class VoterHistory 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;
|
||||
}
|
||||
|
||||
// ===========
|
||||
// View Voters
|
||||
// ===========
|
||||
|
||||
public function viewVoters() {
|
||||
|
||||
$voters = $this->getVoterHistoryPage();
|
||||
$popovers = (new Popovers())->getPopovers();
|
||||
|
||||
$XML = $this->mergeXML($voters, "<XML/>");
|
||||
$XML = $this->mergeXML($popovers, $XML);
|
||||
|
||||
echo $XML;
|
||||
die();
|
||||
|
||||
$content = $this->applyXSL($XML, $this->getXSL("viewVoters"));
|
||||
|
||||
$this->displayContent($content);
|
||||
}
|
||||
|
||||
// ============================
|
||||
// Return a Voters Page Object
|
||||
// ============================
|
||||
|
||||
public function getVotersPage() {
|
||||
|
||||
// Find Criteria
|
||||
|
||||
$find_voter = filter_input(INPUT_POST, "find_voter") ?: "";
|
||||
$find_voter = $this->sanitizeString($find_voter);
|
||||
|
||||
$find_words = implode("|", explode(" ", $find_voter));
|
||||
|
||||
// Record Count
|
||||
|
||||
$connection = $this->connect();
|
||||
|
||||
$SQL = "select count(*) as count
|
||||
from view_voterhistory";
|
||||
// where voter_name_first regexp :voter_name_first";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":voter_name_first", $find_words);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$recordset = $statement->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$count = (count($recordset) > 0) ? (integer) $recordset["count"] : (integer) 0;
|
||||
|
||||
// Pagination
|
||||
|
||||
$pagination = filter_input(INPUT_POST, "pagination") ?: "";
|
||||
|
||||
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 = ($count / $this->pagination_size);
|
||||
break;
|
||||
}
|
||||
|
||||
$offset = (($this->pagination_page * $this->pagination_size) - $this->pagination_size);
|
||||
$start = ($offset + 1);
|
||||
$end = min($count, (($start + $this->pagination_size) - 1));
|
||||
|
||||
// Data
|
||||
|
||||
$SQL = "select view_voters.*
|
||||
from view_voters
|
||||
-- where voter_name_first regexp :voter_name_first
|
||||
order by voter_name_first
|
||||
limit {$this->pagination_size}
|
||||
offset {$offset}";
|
||||
|
||||
$statement = $connection->prepare($SQL);
|
||||
|
||||
$statement->bindValue(":voter_name_first", $find_words);
|
||||
|
||||
$statement->execute();
|
||||
|
||||
$voters = $this->getTableXML("voters", $statement);
|
||||
|
||||
// Insert Pagination Attributes
|
||||
|
||||
$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;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,545 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,389 @@
|
||||
<?php
|
||||
|
||||
// ===============================
|
||||
// FWC Commercial License Import
|
||||
// ===============================
|
||||
|
||||
$options = getopt("", [
|
||||
"base-dir::",
|
||||
"commercial-dir::",
|
||||
"full-reload::",
|
||||
]);
|
||||
|
||||
$baseDir = normalizePath($options["base-dir"] ?? (__DIR__ . "/../../data/fwcdata"));
|
||||
$currentDir = normalizePath($options["commercial-dir"] ?? ($baseDir . "/licenses/current/commercial"));
|
||||
$fullReload = true; // true = truncate license table before importing all current files
|
||||
|
||||
if (isset($options["full-reload"])) {
|
||||
$fullReload = filter_var($options["full-reload"], FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE) ?? true;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
$databaseConfig = getDatabaseConfig();
|
||||
$dbHost = $databaseConfig["host"];
|
||||
$dbName = $databaseConfig["name"];
|
||||
$dbUser = $databaseConfig["user"];
|
||||
$dbPass = $databaseConfig["pass"];
|
||||
|
||||
$pdo = new PDO("mysql:host={$dbHost};dbname={$dbName};charset=utf8mb4", $dbUser, $dbPass, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::MYSQL_ATTR_LOCAL_INFILE => true]);
|
||||
|
||||
$files = glob($currentDir . DIRECTORY_SEPARATOR . "*.txt");
|
||||
|
||||
if (empty($files)) {
|
||||
throw new Exception("No .txt files found in {$currentDir}");
|
||||
}
|
||||
|
||||
$importBatchCode = createUuid();
|
||||
|
||||
echo "Import batch: {$importBatchCode}" . PHP_EOL;
|
||||
|
||||
if ($fullReload) {
|
||||
echo "Truncating fwc_commercial_licenses..." . PHP_EOL;
|
||||
$pdo->exec("TRUNCATE TABLE fwc_commercial_licenses");
|
||||
}
|
||||
|
||||
$hasFailures = false;
|
||||
|
||||
foreach ($files as $filePath) {
|
||||
|
||||
$sourceFile = basename($filePath);
|
||||
$fileSize = filesize($filePath);
|
||||
|
||||
echo "Importing {$sourceFile}..." . PHP_EOL;
|
||||
|
||||
$licenseCode = getLicenseCode($sourceFile);
|
||||
$importSerial = createImportRecord($pdo, $importBatchCode, $sourceFile, $licenseCode, $filePath, $fileSize);
|
||||
|
||||
try {
|
||||
|
||||
updateImportStatus($pdo, $importSerial, "running");
|
||||
|
||||
$beforeCount = getLicenseCount($pdo);
|
||||
|
||||
$loadedRows = loadFile($pdo, $filePath, $sourceFile, $importBatchCode);
|
||||
|
||||
$afterCount = getLicenseCount($pdo);
|
||||
$recordsImported = max(0, $afterCount - $beforeCount);
|
||||
|
||||
completeImport($pdo, $importSerial, $recordsImported);
|
||||
|
||||
echo "Loaded {$loadedRows} rows from {$sourceFile}" . PHP_EOL;
|
||||
} catch (Exception $e) {
|
||||
|
||||
$hasFailures = true;
|
||||
|
||||
failImport($pdo, $importSerial, $e->getMessage());
|
||||
|
||||
echo "ERROR importing {$sourceFile}: " . $e->getMessage() . PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
if ($hasFailures) {
|
||||
sendWebHookAlert("FWC commercial license reload completed with errors.", "Script Alert", "ff9900");
|
||||
echo "Import completed with errors." . PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
echo "Import complete." . PHP_EOL;
|
||||
sendWebHookAlert("FWC commercial license reload successful.");
|
||||
} catch (Exception $e) {
|
||||
|
||||
echo "Import failed: " . $e->getMessage() . PHP_EOL;
|
||||
sendWebHookAlert("FWC commercial license reload failed: " . $e->getMessage(), "Script Alert", "ff0000");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// =======================
|
||||
// Load File into MySQL
|
||||
// =======================
|
||||
|
||||
function loadFile(PDO $pdo, string $filePath, string $sourceFile, string $importBatchCode): int {
|
||||
|
||||
$filePathSql = $pdo->quote($filePath);
|
||||
$sourceFileSql = $pdo->quote($sourceFile);
|
||||
$licenseCodeSql = $pdo->quote(getLicenseCode($sourceFile));
|
||||
$importBatchCodeSql = $pdo->quote($importBatchCode);
|
||||
|
||||
$sql = "LOAD DATA LOCAL INFILE {$filePathSql}
|
||||
INTO TABLE fwc_commercial_licenses
|
||||
CHARACTER SET utf8mb4
|
||||
FIELDS TERMINATED BY '\\t'
|
||||
LINES TERMINATED BY '\\n'
|
||||
IGNORE 1 LINES
|
||||
|
||||
( @LicenseNumber,
|
||||
@ApplicantId,
|
||||
@FloridaResidency,
|
||||
@IssuedTo,
|
||||
@LicenseScope,
|
||||
@LicenseBeginDate,
|
||||
@LicenseExpireDate,
|
||||
@CompanyOrLastName,
|
||||
@FirstName,
|
||||
@MiddleInit,
|
||||
@Suffix,
|
||||
@EmailAddress,
|
||||
@County,
|
||||
@MailStreet1,
|
||||
@MailStreet2,
|
||||
@MailCity,
|
||||
@MailState,
|
||||
@MailZipCode,
|
||||
@MailZip4,
|
||||
@ApplicantPhone,
|
||||
@EndorsementNumber,
|
||||
@EndorsementExpirationDate,
|
||||
@TotalTagQty )
|
||||
SET
|
||||
commercial_license_source_file = {$sourceFileSql},
|
||||
commercial_license_code = {$licenseCodeSql},
|
||||
commercial_license_number = TRIM(@LicenseNumber),
|
||||
commercial_license_applicant_id = CASE
|
||||
WHEN TRIM(@ApplicantId) REGEXP '^[0-9]+$' THEN TRIM(@ApplicantId)
|
||||
ELSE NULL
|
||||
END,
|
||||
commercial_license_florida_residency = TRIM(@FloridaResidency),
|
||||
commercial_license_issued_to = TRIM(@IssuedTo),
|
||||
commercial_license_scope = TRIM(@LicenseScope),
|
||||
commercial_license_begin_date = COALESCE(STR_TO_DATE(NULLIF(TRIM(@LicenseBeginDate), ''), '%Y-%m-%d %H:%i:%s'),
|
||||
STR_TO_DATE(NULLIF(TRIM(@LicenseBeginDate), ''), '%Y-%m-%d')),
|
||||
commercial_license_expire_date = COALESCE(STR_TO_DATE(NULLIF(TRIM(@LicenseExpireDate), ''), '%Y-%m-%d %H:%i:%s'),
|
||||
STR_TO_DATE(NULLIF(TRIM(@LicenseExpireDate), ''), '%Y-%m-%d')),
|
||||
commercial_license_company_or_last_name = TRIM(@CompanyOrLastName),
|
||||
commercial_license_first_name = TRIM(@FirstName),
|
||||
commercial_license_middle_init = TRIM(@MiddleInit),
|
||||
commercial_license_suffix = TRIM(@Suffix),
|
||||
commercial_license_email_address = TRIM(@EmailAddress),
|
||||
commercial_license_county = TRIM(@County),
|
||||
commercial_license_mail_street1 = TRIM(@MailStreet1),
|
||||
commercial_license_mail_street2 = TRIM(@MailStreet2),
|
||||
commercial_license_mail_city = TRIM(@MailCity),
|
||||
commercial_license_mail_state = TRIM(@MailState),
|
||||
commercial_license_mail_zip_code = TRIM(@MailZipCode),
|
||||
commercial_license_mail_zip4 = TRIM(@MailZip4),
|
||||
commercial_license_applicant_phone = TRIM(@ApplicantPhone),
|
||||
commercial_license_endorsement_number = TRIM(@EndorsementNumber),
|
||||
commercial_license_endorsement_expiration_date = COALESCE(STR_TO_DATE(NULLIF(TRIM(@EndorsementExpirationDate), ''), '%Y-%m-%d %H:%i:%s'),
|
||||
STR_TO_DATE(NULLIF(TRIM(@EndorsementExpirationDate), ''), '%Y-%m-%d')),
|
||||
commercial_license_total_tag_qty = CASE
|
||||
WHEN TRIM(REPLACE(@TotalTagQty, '\\r', '')) REGEXP '^[0-9]+$' THEN TRIM(REPLACE(@TotalTagQty, '\\r', ''))
|
||||
ELSE NULL
|
||||
END,
|
||||
commercial_license_import_batch_code = {$importBatchCodeSql}";
|
||||
|
||||
return (int) $pdo->exec($sql);
|
||||
}
|
||||
|
||||
// ===============
|
||||
// Import Tracking
|
||||
// ===============
|
||||
|
||||
function createImportRecord(PDO $pdo, string $batchCode, string $sourceFile, string $licenseCode, string $filePath, int $fileSize): int {
|
||||
|
||||
$sql = " INSERT INTO fwc_commercial_license_imports (
|
||||
import_batch_code,
|
||||
source_file,
|
||||
license_code,
|
||||
file_path,
|
||||
file_size,
|
||||
import_status,
|
||||
started_at )
|
||||
|
||||
VALUES ( :import_batch_code,
|
||||
:source_file,
|
||||
:license_code,
|
||||
:file_path,
|
||||
:file_size,
|
||||
'queued',
|
||||
NOW())";
|
||||
|
||||
$statement = $pdo->prepare($sql);
|
||||
|
||||
$statement->execute([":import_batch_code" => $batchCode, ":source_file" => $sourceFile, ":license_code" => $licenseCode, ":file_path" => $filePath, ":file_size" => $fileSize]);
|
||||
|
||||
return (int) $pdo->lastInsertId();
|
||||
}
|
||||
|
||||
function updateImportStatus(PDO $pdo, int $importSerial, string $status): void {
|
||||
|
||||
$sql = "UPDATE fwc_commercial_license_imports
|
||||
SET import_status = :status
|
||||
WHERE import_serial = :import_serial";
|
||||
|
||||
$statement = $pdo->prepare($sql);
|
||||
|
||||
$statement->execute([":status" => $status, ":import_serial" => $importSerial]);
|
||||
}
|
||||
|
||||
function completeImport(PDO $pdo, int $importSerial, int $recordsImported): void {
|
||||
|
||||
$sql = "UPDATE fwc_commercial_license_imports
|
||||
SET import_status = 'complete',
|
||||
records_imported = :records_imported,
|
||||
completed_at = NOW()
|
||||
WHERE import_serial = :import_serial";
|
||||
|
||||
$statement = $pdo->prepare($sql);
|
||||
|
||||
$statement->execute([":records_imported" => $recordsImported, ":import_serial" => $importSerial]);
|
||||
}
|
||||
|
||||
function failImport(PDO $pdo, int $importSerial, string $message): void {
|
||||
|
||||
$sql = "UPDATE fwc_commercial_license_imports
|
||||
SET import_status = 'failed',
|
||||
error_message = :error_message,
|
||||
completed_at = NOW()
|
||||
WHERE import_serial = :import_serial";
|
||||
|
||||
$statement = $pdo->prepare($sql);
|
||||
|
||||
$statement->execute([":error_message" => $message, ":import_serial" => $importSerial]);
|
||||
}
|
||||
|
||||
// =======
|
||||
// Helpers
|
||||
// =======
|
||||
|
||||
function getLicenseCount(PDO $pdo): int {
|
||||
|
||||
return (int) $pdo->query("SELECT COUNT(*) FROM fwc_commercial_licenses")->fetchColumn();
|
||||
}
|
||||
|
||||
function getLicenseCode(string $sourceFile): string {
|
||||
|
||||
$fileName = strtolower(pathinfo($sourceFile, PATHINFO_FILENAME));
|
||||
|
||||
$licenseCodePatterns = [
|
||||
"closedseasonspinylobsterplaneandvessel" => "CSV",
|
||||
"closedseasonspinylobster" => "CS",
|
||||
"depredationpermit" => "DP",
|
||||
"freshwatercommercialfishing" => "FCL",
|
||||
"nonresidentfreshwaterretaildealers" => "FRD",
|
||||
"nonresidentfreshwaterwholesalebuyers" => "FWB",
|
||||
"nonresidentfreshwaterwholesaledealers" => "FWD",
|
||||
"stjohnsriverliveshrimp" => "LS",
|
||||
"retailcentral" => "RC",
|
||||
"residentfreshwaterfishandfrogdealers" => "RFD",
|
||||
"retailother" => "RO",
|
||||
"sardinelikefish" => "SL",
|
||||
"saltwaterproducts" => "SP",
|
||||
"wholesaledealer" => "WD",
|
||||
];
|
||||
|
||||
foreach ($licenseCodePatterns as $pattern => $licenseCode) {
|
||||
if (strpos($fileName, $pattern) !== false) {
|
||||
return $licenseCode;
|
||||
}
|
||||
}
|
||||
|
||||
return strtoupper(substr($fileName, 0, 10));
|
||||
}
|
||||
|
||||
function createUuid(): string {
|
||||
|
||||
$data = random_bytes(16);
|
||||
|
||||
$data[6] = chr(ord($data[6]) & 0x0f | 0x40);
|
||||
$data[8] = chr(ord($data[8]) & 0x3f | 0x80);
|
||||
|
||||
return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
|
||||
}
|
||||
|
||||
function normalizePath(string $path): string {
|
||||
|
||||
$realPath = realpath($path);
|
||||
|
||||
return $realPath === false ? rtrim($path, DIRECTORY_SEPARATOR) : $realPath;
|
||||
}
|
||||
|
||||
function getDatabaseConfig(): array {
|
||||
|
||||
$config = [
|
||||
"host" => getenv("FWC_DB_HOST") ?: "",
|
||||
"name" => getenv("FWC_DB_NAME") ?: "",
|
||||
"user" => getenv("FWC_DB_USER") ?: "",
|
||||
"pass" => getenv("FWC_DB_PASS") ?: "",
|
||||
];
|
||||
|
||||
if ($config["host"] !== "" && $config["name"] !== "" && $config["user"] !== "" && $config["pass"] !== "") {
|
||||
return $config;
|
||||
}
|
||||
|
||||
$settingsPath = __DIR__ . "/../../xml/settings.xml";
|
||||
|
||||
if (!file_exists($settingsPath)) {
|
||||
throw new Exception("Database settings not found. Set FWC_DB_HOST, FWC_DB_NAME, FWC_DB_USER, and FWC_DB_PASS or create {$settingsPath}");
|
||||
}
|
||||
|
||||
$settings = new SimpleXMLElement(file_get_contents($settingsPath));
|
||||
|
||||
$config = [
|
||||
"host" => trim((string) $settings->DatabaseServer),
|
||||
"name" => trim((string) $settings->DatabaseName),
|
||||
"user" => trim((string) $settings->DatabaseUser),
|
||||
"pass" => trim((string) $settings->DatabasePassword),
|
||||
];
|
||||
|
||||
foreach ($config as $key => $value) {
|
||||
if ($value === "") {
|
||||
throw new Exception("Database setting {$key} is missing in {$settingsPath}");
|
||||
}
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
function sendWebHookAlert(string $message, string $title = "Script Alert", string $alerttype = "1fff00"): void {
|
||||
|
||||
$webhookUrl = getenv("FWC_WEBHOOK_URL") ?: "";
|
||||
|
||||
if ($webhookUrl === "") {
|
||||
$settingsPath = __DIR__ . "/../../xml/settings.xml";
|
||||
|
||||
if (file_exists($settingsPath)) {
|
||||
$settings = new SimpleXMLElement(file_get_contents($settingsPath));
|
||||
$webhookUrl = trim((string) $settings->DiscordWebHookURL);
|
||||
}
|
||||
}
|
||||
|
||||
if (trim($webhookUrl) === "") {
|
||||
echo "Webhook alert skipped: FWC_WEBHOOK_URL is not set." . PHP_EOL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!function_exists("curl_init")) {
|
||||
echo "Webhook alert skipped: PHP curl extension is not available." . PHP_EOL;
|
||||
return;
|
||||
}
|
||||
|
||||
$data = [
|
||||
'embeds' => [[
|
||||
'title' => $title,
|
||||
'description' => $message,
|
||||
'color' => hexdec($alerttype),
|
||||
'footer' => [
|
||||
'text' => 'OSITS System Notification',
|
||||
],
|
||||
'timestamp' => date('c'),
|
||||
]]
|
||||
];
|
||||
|
||||
$jsonData = json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
||||
|
||||
$ch = curl_init($webhookUrl);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
|
||||
if ($response === false) {
|
||||
echo "Webhook alert failed: " . curl_error($ch) . PHP_EOL;
|
||||
}
|
||||
|
||||
curl_close($ch);
|
||||
}
|
||||
@@ -0,0 +1,347 @@
|
||||
<?php
|
||||
|
||||
// ===============================
|
||||
// FWC Recreational License Import
|
||||
// ===============================
|
||||
|
||||
$options = getopt("", [
|
||||
"base-dir::",
|
||||
"recreational-dir::",
|
||||
"full-reload::",
|
||||
]);
|
||||
|
||||
$baseDir = normalizePath($options["base-dir"] ?? (__DIR__ . "/../../data/fwcdata"));
|
||||
$currentDir = normalizePath($options["recreational-dir"] ?? ($baseDir . "/licenses/current/recreational"));
|
||||
$fullReload = true; // true = truncate license table before importing all current files
|
||||
|
||||
if (isset($options["full-reload"])) {
|
||||
$fullReload = filter_var($options["full-reload"], FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE) ?? true;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
$databaseConfig = getDatabaseConfig();
|
||||
$dbHost = $databaseConfig["host"];
|
||||
$dbName = $databaseConfig["name"];
|
||||
$dbUser = $databaseConfig["user"];
|
||||
$dbPass = $databaseConfig["pass"];
|
||||
|
||||
$pdo = new PDO("mysql:host={$dbHost};dbname={$dbName};charset=utf8mb4", $dbUser, $dbPass, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::MYSQL_ATTR_LOCAL_INFILE => true]);
|
||||
|
||||
$files = glob($currentDir . DIRECTORY_SEPARATOR . "*.txt");
|
||||
|
||||
if (empty($files)) {
|
||||
throw new Exception("No .txt files found in {$currentDir}");
|
||||
}
|
||||
|
||||
$importBatchCode = createUuid();
|
||||
|
||||
echo "Import batch: {$importBatchCode}" . PHP_EOL;
|
||||
|
||||
if ($fullReload) {
|
||||
echo "Truncating fwc_recreational_licenses..." . PHP_EOL;
|
||||
$pdo->exec("TRUNCATE TABLE fwc_recreational_licenses");
|
||||
}
|
||||
|
||||
$hasFailures = false;
|
||||
|
||||
foreach ($files as $filePath) {
|
||||
|
||||
$sourceFile = basename($filePath);
|
||||
$fileSize = filesize($filePath);
|
||||
|
||||
echo "Importing {$sourceFile}..." . PHP_EOL;
|
||||
|
||||
$importSerial = createImportRecord($pdo, $importBatchCode, $sourceFile, $filePath, $fileSize);
|
||||
|
||||
try {
|
||||
|
||||
updateImportStatus($pdo, $importSerial, "running");
|
||||
|
||||
$beforeCount = getLicenseCount($pdo);
|
||||
|
||||
$loadedRows = loadFile($pdo, $filePath, $sourceFile, $importBatchCode);
|
||||
|
||||
purgeOutOfStateRecords($pdo);
|
||||
|
||||
$afterCount = getLicenseCount($pdo);
|
||||
$recordsImported = max(0, $afterCount - $beforeCount);
|
||||
|
||||
completeImport($pdo, $importSerial, $recordsImported);
|
||||
|
||||
echo "Loaded {$loadedRows} rows; retained {$recordsImported} Florida records from {$sourceFile}" . PHP_EOL;
|
||||
} catch (Exception $e) {
|
||||
|
||||
$hasFailures = true;
|
||||
|
||||
failImport($pdo, $importSerial, $e->getMessage());
|
||||
|
||||
echo "ERROR importing {$sourceFile}: " . $e->getMessage() . PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
if ($hasFailures) {
|
||||
sendWebHookAlert("FWC recreational license reload completed with errors.", "Script Alert", "ff9900");
|
||||
echo "Import completed with errors." . PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
echo "Import complete." . PHP_EOL;
|
||||
sendWebHookAlert("FWC recreational license reload successful.");
|
||||
} catch (Exception $e) {
|
||||
|
||||
echo "Import failed: " . $e->getMessage() . PHP_EOL;
|
||||
sendWebHookAlert("FWC recreational license reload failed: " . $e->getMessage(), "Script Alert", "ff0000");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// =======================
|
||||
// Load File into MySQL
|
||||
// =======================
|
||||
|
||||
function loadFile(PDO $pdo, string $filePath, string $sourceFile, string $importBatchCode): int {
|
||||
|
||||
$filePathSql = $pdo->quote($filePath);
|
||||
$sourceFileSql = $pdo->quote($sourceFile);
|
||||
$importBatchCodeSql = $pdo->quote($importBatchCode);
|
||||
|
||||
$sql = "LOAD DATA LOCAL INFILE {$filePathSql}
|
||||
INTO TABLE fwc_recreational_licenses
|
||||
CHARACTER SET utf8mb4
|
||||
FIELDS TERMINATED BY '\\t'
|
||||
LINES TERMINATED BY '\\n'
|
||||
IGNORE 1 LINES
|
||||
|
||||
( @lastName,
|
||||
@firstName,
|
||||
@middleName,
|
||||
@street1,
|
||||
@city,
|
||||
@state,
|
||||
@zipCode,
|
||||
@phoneNumber,
|
||||
@emailAddress,
|
||||
@Gender,
|
||||
@Ethnicity,
|
||||
@LicenseType,
|
||||
@LicenseExpireDate,
|
||||
@LicenseStartDate,
|
||||
@AgeAtTimeOfRun,
|
||||
@County )
|
||||
SET
|
||||
license_source_file = {$sourceFileSql},
|
||||
license_last_name = TRIM(@lastName),
|
||||
license_first_name = TRIM(@firstName),
|
||||
license_middle_name = TRIM(@middleName),
|
||||
license_street1 = TRIM(@street1),
|
||||
license_city = TRIM(@city),
|
||||
license_state = TRIM(@state),
|
||||
license_zip_code = TRIM(@zipCode),
|
||||
license_phone_number = TRIM(@phoneNumber),
|
||||
license_email_address = TRIM(@emailAddress),
|
||||
license_gender = TRIM(@Gender),
|
||||
license_ethnicity = TRIM(@Ethnicity),
|
||||
license_type = TRIM(@LicenseType),
|
||||
license_expire_date = COALESCE(STR_TO_DATE(NULLIF(TRIM(@LicenseExpireDate), ''), '%Y-%m-%d %H:%i:%s'),
|
||||
STR_TO_DATE(NULLIF(TRIM(@LicenseExpireDate), ''), '%Y-%m-%d')),
|
||||
license_start_date = COALESCE(STR_TO_DATE(NULLIF(TRIM(@LicenseStartDate), ''), '%Y-%m-%d %H:%i:%s'),
|
||||
STR_TO_DATE(NULLIF(TRIM(@LicenseStartDate), ''), '%Y-%m-%d')),
|
||||
license_age_at_time_of_run = CASE
|
||||
WHEN TRIM(@AgeAtTimeOfRun) REGEXP '^[0-9]+$' THEN TRIM(@AgeAtTimeOfRun)
|
||||
ELSE NULL
|
||||
END,
|
||||
license_county = TRIM(REPLACE(@County, '\\r', '')),
|
||||
import_batch_code = {$importBatchCodeSql}";
|
||||
|
||||
return (int) $pdo->exec($sql);
|
||||
}
|
||||
|
||||
// ===============
|
||||
// Import Tracking
|
||||
// ===============
|
||||
|
||||
function createImportRecord(PDO $pdo, string $batchCode, string $sourceFile, string $filePath, int $fileSize): int {
|
||||
|
||||
$sql = " INSERT INTO fwc_recreational_license_imports (
|
||||
import_batch_code,
|
||||
source_file,
|
||||
file_path,
|
||||
file_size,
|
||||
import_status,
|
||||
started_at )
|
||||
|
||||
VALUES ( :import_batch_code,
|
||||
:source_file,
|
||||
:file_path,
|
||||
:file_size,
|
||||
'queued',
|
||||
NOW())";
|
||||
|
||||
$statement = $pdo->prepare($sql);
|
||||
|
||||
$statement->execute([":import_batch_code" => $batchCode, ":source_file" => $sourceFile, ":file_path" => $filePath, ":file_size" => $fileSize]);
|
||||
|
||||
return (int) $pdo->lastInsertId();
|
||||
}
|
||||
|
||||
function updateImportStatus(PDO $pdo, int $importSerial, string $status): void {
|
||||
|
||||
$sql = "UPDATE fwc_recreational_license_imports
|
||||
SET import_status = :status
|
||||
WHERE import_serial = :import_serial";
|
||||
|
||||
$statement = $pdo->prepare($sql);
|
||||
|
||||
$statement->execute([":status" => $status, ":import_serial" => $importSerial]);
|
||||
}
|
||||
|
||||
function completeImport(PDO $pdo, int $importSerial, int $recordsImported): void {
|
||||
|
||||
$sql = "UPDATE fwc_recreational_license_imports
|
||||
SET import_status = 'complete',
|
||||
records_imported = :records_imported,
|
||||
completed_at = NOW()
|
||||
WHERE import_serial = :import_serial";
|
||||
|
||||
$statement = $pdo->prepare($sql);
|
||||
|
||||
$statement->execute([":records_imported" => $recordsImported, ":import_serial" => $importSerial]);
|
||||
}
|
||||
|
||||
function failImport(PDO $pdo, int $importSerial, string $message): void {
|
||||
|
||||
$sql = "UPDATE fwc_recreational_license_imports
|
||||
SET import_status = 'failed',
|
||||
error_message = :error_message,
|
||||
completed_at = NOW()
|
||||
WHERE import_serial = :import_serial";
|
||||
|
||||
$statement = $pdo->prepare($sql);
|
||||
|
||||
$statement->execute([":error_message" => $message, ":import_serial" => $importSerial]);
|
||||
}
|
||||
|
||||
function purgeOutOfStateRecords(PDO $pdo): void {
|
||||
|
||||
$sql = "delete from fwc_recreational_licenses where license_state != 'FL'";
|
||||
|
||||
$statement = $pdo->prepare($sql);
|
||||
|
||||
$statement->execute();
|
||||
}
|
||||
|
||||
// =======
|
||||
// Helpers
|
||||
// =======
|
||||
|
||||
function getLicenseCount(PDO $pdo): int {
|
||||
|
||||
return (int) $pdo->query("SELECT COUNT(*) FROM fwc_recreational_licenses")->fetchColumn();
|
||||
}
|
||||
|
||||
function createUuid(): string {
|
||||
|
||||
$data = random_bytes(16);
|
||||
|
||||
$data[6] = chr(ord($data[6]) & 0x0f | 0x40);
|
||||
$data[8] = chr(ord($data[8]) & 0x3f | 0x80);
|
||||
|
||||
return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
|
||||
}
|
||||
|
||||
function normalizePath(string $path): string {
|
||||
|
||||
$realPath = realpath($path);
|
||||
|
||||
return $realPath === false ? rtrim($path, DIRECTORY_SEPARATOR) : $realPath;
|
||||
}
|
||||
|
||||
function getDatabaseConfig(): array {
|
||||
|
||||
$config = [
|
||||
"host" => getenv("FWC_DB_HOST") ?: "",
|
||||
"name" => getenv("FWC_DB_NAME") ?: "",
|
||||
"user" => getenv("FWC_DB_USER") ?: "",
|
||||
"pass" => getenv("FWC_DB_PASS") ?: "",
|
||||
];
|
||||
|
||||
if ($config["host"] !== "" && $config["name"] !== "" && $config["user"] !== "" && $config["pass"] !== "") {
|
||||
return $config;
|
||||
}
|
||||
|
||||
$settingsPath = __DIR__ . "/../../xml/settings.xml";
|
||||
|
||||
if (!file_exists($settingsPath)) {
|
||||
throw new Exception("Database settings not found. Set FWC_DB_HOST, FWC_DB_NAME, FWC_DB_USER, and FWC_DB_PASS or create {$settingsPath}");
|
||||
}
|
||||
|
||||
$settings = new SimpleXMLElement(file_get_contents($settingsPath));
|
||||
|
||||
$config = [
|
||||
"host" => trim((string) $settings->DatabaseServer),
|
||||
"name" => trim((string) $settings->DatabaseName),
|
||||
"user" => trim((string) $settings->DatabaseUser),
|
||||
"pass" => trim((string) $settings->DatabasePassword),
|
||||
];
|
||||
|
||||
foreach ($config as $key => $value) {
|
||||
if ($value === "") {
|
||||
throw new Exception("Database setting {$key} is missing in {$settingsPath}");
|
||||
}
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
function sendWebHookAlert(string $message, string $title = "Script Alert", string $alerttype = "1fff00"): void {
|
||||
|
||||
$webhookUrl = getenv("FWC_WEBHOOK_URL") ?: "";
|
||||
|
||||
if ($webhookUrl === "") {
|
||||
$settingsPath = __DIR__ . "/../../xml/settings.xml";
|
||||
|
||||
if (file_exists($settingsPath)) {
|
||||
$settings = new SimpleXMLElement(file_get_contents($settingsPath));
|
||||
$webhookUrl = trim((string) $settings->DiscordWebHookURL);
|
||||
}
|
||||
}
|
||||
|
||||
if (trim($webhookUrl) === "") {
|
||||
echo "Webhook alert skipped: FWC_WEBHOOK_URL is not set." . PHP_EOL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!function_exists("curl_init")) {
|
||||
echo "Webhook alert skipped: PHP curl extension is not available." . PHP_EOL;
|
||||
return;
|
||||
}
|
||||
|
||||
$data = [
|
||||
'embeds' => [[
|
||||
'title' => $title,
|
||||
'description' => $message,
|
||||
'color' => hexdec($alerttype),
|
||||
'footer' => [
|
||||
'text' => 'OSITS System Notification',
|
||||
],
|
||||
'timestamp' => date('c'),
|
||||
]]
|
||||
];
|
||||
|
||||
$jsonData = json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
||||
|
||||
$ch = curl_init($webhookUrl);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
|
||||
if ($response === false) {
|
||||
echo "Webhook alert failed: " . curl_error($ch) . PHP_EOL;
|
||||
}
|
||||
|
||||
curl_close($ch);
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
<?php
|
||||
|
||||
// ====================
|
||||
// Import Voter History
|
||||
// ====================
|
||||
|
||||
class Import_VoterHistory {
|
||||
|
||||
// Variables
|
||||
|
||||
private $log = "";
|
||||
private $settings = "";
|
||||
private $connection = "";
|
||||
|
||||
// ==================
|
||||
// Class Constructor.
|
||||
// ==================
|
||||
|
||||
public function __construct() {
|
||||
|
||||
// Open the Log
|
||||
|
||||
$this->log = fopen("../scripts/import_voter_history.log", "w+");
|
||||
|
||||
if ($this->log === false) {
|
||||
|
||||
error_log("VoterVue : Unable to open log file");
|
||||
exit();
|
||||
}
|
||||
|
||||
$this->log(str_repeat("*", 50));
|
||||
|
||||
// Get Settings
|
||||
|
||||
$this->settings = new SimpleXMLElement((file_exists("../xml/settings.xml") ? file_get_contents("../xml/settings.xml") : "<settings/>"));
|
||||
|
||||
if ($this->settings->count() === 0) {
|
||||
|
||||
error_log("VoterVue : Unable to initialize settings");
|
||||
exit();
|
||||
}
|
||||
|
||||
// Open Database Connections
|
||||
|
||||
$this->connection = $this->connect();
|
||||
}
|
||||
|
||||
// ==============================================
|
||||
// Return a VoterVue Database Database Connection
|
||||
// ==============================================
|
||||
|
||||
public function connect() {
|
||||
|
||||
try {
|
||||
|
||||
$host = (string) $this->settings->DatabaseServer;
|
||||
$database = (string) $this->settings->DatabaseName;
|
||||
$user = (string) $this->settings->DatabaseUser;
|
||||
$password = (string) $this->settings->DatabasePassword;
|
||||
|
||||
$connection = new PDO("mysql:host={$host};dbname={$database};charset=utf8", $user, $password);
|
||||
|
||||
$connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
|
||||
$connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
} catch (PDOException | Exception $e) {
|
||||
|
||||
trigger_error($e->getMessage());
|
||||
}
|
||||
|
||||
return $connection;
|
||||
}
|
||||
|
||||
// =============================
|
||||
// Log a message to the Log File
|
||||
// =============================
|
||||
|
||||
private function log($message = "") {
|
||||
|
||||
fwrite($this->log, date("Y-m-d H:i A") . " : " . "{$message} \n");
|
||||
}
|
||||
|
||||
// ===================
|
||||
// Process Parcel Data
|
||||
// ===================
|
||||
|
||||
public function process() {
|
||||
|
||||
$this->log("Starting Voter History Import Process");
|
||||
|
||||
$this->importVoterHistory();
|
||||
|
||||
$this->log("Voter History Import Process Completed");
|
||||
}
|
||||
|
||||
// ====================
|
||||
// Import Voter History
|
||||
// ====================
|
||||
|
||||
private function importVoterHistory() {
|
||||
|
||||
$this->log("Processing Voter History Records");
|
||||
|
||||
$path = '/data/ositssrc/projects/votervue_raw_data/20251210_Voter_History_20251210';
|
||||
$files = glob("{$path}/*.txt");
|
||||
sort($files);
|
||||
|
||||
$SQL = "INSERT IGNORE INTO voterhistory
|
||||
(
|
||||
voterhistory_county_code,
|
||||
voterhistory_voter_id,
|
||||
voterhistory_election_date,
|
||||
voterhistory_election_type,
|
||||
voterhistory_history_code
|
||||
)
|
||||
VALUES ( ?, ?, ?, ?, ? )";
|
||||
|
||||
$statement = $this->connection->prepare($SQL);
|
||||
|
||||
$counter = 0;
|
||||
$batchCounter = 0;
|
||||
$batchSize = 50000;
|
||||
|
||||
foreach ($files as $file) {
|
||||
|
||||
$this->log("Importing history file: {$file}");
|
||||
|
||||
$fh = fopen($file, 'r');
|
||||
|
||||
if ($fh === false) {
|
||||
$this->log("Unable to open {$file}");
|
||||
continue;
|
||||
}
|
||||
|
||||
$lineNum = 0;
|
||||
|
||||
try {
|
||||
|
||||
// Start transaction for this file
|
||||
$this->connection->beginTransaction();
|
||||
|
||||
while (($line = fgets($fh)) !== false) {
|
||||
$lineNum++;
|
||||
|
||||
$line = rtrim($line, "\r\n");
|
||||
if ($line === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$cols = explode("\t", $line);
|
||||
|
||||
if (count($cols) < 5) {
|
||||
$this->log("Skipped malformed line {$lineNum} in {$file} (cols=" . count($cols) . ")");
|
||||
continue;
|
||||
}
|
||||
|
||||
[$county_code, $voter_id, $election_date, $election_type, $history_code] = $cols;
|
||||
|
||||
$statement->execute([
|
||||
$this->normalize($county_code),
|
||||
$this->normalize($voter_id),
|
||||
$this->parseDate($election_date),
|
||||
$this->normalize($election_type),
|
||||
$this->normalize($history_code)
|
||||
]);
|
||||
|
||||
$counter++;
|
||||
$batchCounter++;
|
||||
|
||||
// Commit every batchSize rows
|
||||
if ($batchCounter >= $batchSize) {
|
||||
$this->connection->commit();
|
||||
$this->connection->beginTransaction();
|
||||
$batchCounter = 0;
|
||||
|
||||
$this->log("Processed {$counter} history records...");
|
||||
}
|
||||
}
|
||||
|
||||
// Final commit for this file
|
||||
$this->connection->commit();
|
||||
$batchCounter = 0;
|
||||
} catch (Throwable $e) {
|
||||
|
||||
// Roll back any open transaction for this file
|
||||
if ($this->connection->inTransaction()) {
|
||||
$this->connection->rollBack();
|
||||
}
|
||||
|
||||
$this->log("Insert failed {$file}:{$lineNum} - " . $e->getMessage());
|
||||
}
|
||||
|
||||
fclose($fh);
|
||||
}
|
||||
|
||||
$this->log("Completed voter history import. Total records processed: {$counter}");
|
||||
}
|
||||
|
||||
// =================================
|
||||
// Return a $this->normalized String
|
||||
// =================================
|
||||
|
||||
private function normalize(?string $value): ?string {
|
||||
|
||||
$value = trim((string) $value);
|
||||
|
||||
return ($value === '' || $value === '*') ? null : $value;
|
||||
}
|
||||
|
||||
// ====================
|
||||
// Return a Parsed Date
|
||||
// ====================
|
||||
|
||||
private function parseDate(?string $value): ?string {
|
||||
|
||||
$value = $this->normalize($value);
|
||||
if ($value === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$dt = DateTime::createFromFormat('m/d/Y', $value);
|
||||
|
||||
return $dt ? $dt->format('Y-m-d') : null;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,277 @@
|
||||
<?php
|
||||
|
||||
// ====================
|
||||
// Import Voter Records
|
||||
// ====================
|
||||
|
||||
class Import_VoterRecords {
|
||||
|
||||
// Variables
|
||||
|
||||
private $log = "";
|
||||
private $settings = "";
|
||||
private $connection = "";
|
||||
|
||||
// ==================
|
||||
// Class Constructor.
|
||||
// ==================
|
||||
|
||||
public function __construct() {
|
||||
|
||||
// Open the Log
|
||||
|
||||
$this->log = fopen("../scripts/import_voter_records.log", "w+");
|
||||
|
||||
if ($this->log === false) {
|
||||
|
||||
error_log("VoterVue : Unable to open log file");
|
||||
exit();
|
||||
}
|
||||
|
||||
$this->log(str_repeat("*", 50));
|
||||
|
||||
// Get Settings
|
||||
|
||||
$this->settings = new SimpleXMLElement((file_exists("../xml/settings.xml") ? file_get_contents("../xml/settings.xml") : "<settings/>"));
|
||||
|
||||
if ($this->settings->count() === 0) {
|
||||
|
||||
error_log("VoterVue : Unable to initialize settings");
|
||||
exit();
|
||||
}
|
||||
|
||||
// Open Database Connections
|
||||
|
||||
$this->connection = $this->connect();
|
||||
}
|
||||
|
||||
// ================================================
|
||||
// Return a New DEC-DR Database Database Connection
|
||||
// ================================================
|
||||
|
||||
public function connect() {
|
||||
|
||||
try {
|
||||
|
||||
$host = (string) $this->settings->DatabaseServer;
|
||||
$database = (string) $this->settings->DatabaseName;
|
||||
$user = (string) $this->settings->DatabaseUser;
|
||||
$password = (string) $this->settings->DatabasePassword;
|
||||
|
||||
$connection = new PDO("mysql:host={$host};dbname={$database};charset=utf8", $user, $password);
|
||||
|
||||
$connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
|
||||
$connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
} catch (PDOException | Exception $e) {
|
||||
|
||||
trigger_error($e->getMessage());
|
||||
}
|
||||
|
||||
return $connection;
|
||||
}
|
||||
|
||||
// =============================
|
||||
// Log a message to the Log File
|
||||
// =============================
|
||||
|
||||
private function log($message = "") {
|
||||
|
||||
fwrite($this->log, date("Y-m-d H:i A") . " : " . "{$message} \n");
|
||||
}
|
||||
|
||||
// ===================
|
||||
// Process Parcel Data
|
||||
// ===================
|
||||
|
||||
public function process() {
|
||||
|
||||
$this->log("Starting Voter Record Import Process");
|
||||
|
||||
$this->importVoterRecords();
|
||||
|
||||
$this->log("Voter Record Import Process Complete");
|
||||
}
|
||||
|
||||
// ====================
|
||||
// Import Voter Records
|
||||
// ====================
|
||||
|
||||
private function importVoterRecords() {
|
||||
|
||||
$this->log("Processing Voter Records");
|
||||
|
||||
$voter_record_file_path = '/data/ositssrc/projects/votervue_raw_data/20251210_Voter_Detail_20251210';
|
||||
$voter_history_files = glob("{$voter_record_file_path}/*.txt");
|
||||
sort($voter_history_files);
|
||||
|
||||
$SQL = "INSERT INTO voters
|
||||
( voter_county_code,
|
||||
voter_id,
|
||||
voter_name_last,
|
||||
voter_name_suffix,
|
||||
voter_name_first,
|
||||
voter_name_middle,
|
||||
voter_public_records_exempt,
|
||||
voter_residence_address_1,
|
||||
voter_residence_address_2,
|
||||
voter_residence_city,
|
||||
voter_residence_state,
|
||||
voter_residence_zipcode,
|
||||
voter_mailing_address_1,
|
||||
voter_mailing_address_2,
|
||||
voter_mailing_address_3,
|
||||
voter_mailing_city,
|
||||
voter_mailing_state,
|
||||
voter_mailing_zipcode,
|
||||
voter_mailing_country,
|
||||
voter_gender,
|
||||
voter_race,
|
||||
voter_birth_date,
|
||||
voter_registration_date,
|
||||
voter_party_affiliation,
|
||||
voter_precinct,
|
||||
voter_precinct_group,
|
||||
voter_precinct_split,
|
||||
voter_precinct_suffix,
|
||||
voter_voter_status,
|
||||
voter_congressional_district,
|
||||
voter_house_district,
|
||||
voter_senate_district,
|
||||
voter_county_commission_district,
|
||||
voter_school_board_district,
|
||||
voter_daytime_area_code,
|
||||
voter_daytime_phone_number,
|
||||
voter_daytime_phone_extension,
|
||||
voter_email_address )
|
||||
VALUES
|
||||
( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
|
||||
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
|
||||
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
|
||||
?, ?, ?, ?, ? )";
|
||||
|
||||
$statement = $this->connection->prepare($SQL);
|
||||
|
||||
$counter = 0;
|
||||
|
||||
foreach ($voter_history_files as $file) {
|
||||
|
||||
$this->log("Importing file: {$file}");
|
||||
|
||||
$voterhistory = fopen($file, 'r');
|
||||
|
||||
if ($voterhistory === false) {
|
||||
$this->log("Unable to open {$file}");
|
||||
echo "❌ Unable to open {$file}\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
$lineNum = 0;
|
||||
|
||||
while (($line = fgets($voterhistory)) !== false) {
|
||||
$lineNum++;
|
||||
|
||||
$line = rtrim($line, "\r\n");
|
||||
if ($line === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$cols = explode("\t", $line);
|
||||
|
||||
if (count($cols) < 38) {
|
||||
$this->log("Skipped malformed line {$lineNum} in {$file} (cols=" . count($cols) . ")");
|
||||
continue;
|
||||
}
|
||||
|
||||
[$county_code, $voter_id, $name_last, $name_suffix, $name_first, $name_middle, $public_exempt, $res_addr1, $res_addr2, $res_city, $res_state, $res_zip,
|
||||
$mail_addr1, $mail_addr2, $mail_addr3, $mail_city, $mail_state, $mail_zip, $mail_country, $gender, $race, $birth_date, $reg_date, $party, $precinct,
|
||||
$precinct_group, $precinct_split, $precinct_suffix, $status, $cd, $hd, $sd, $ccd, $sbd, $area, $phone, $ext, $email] = $cols;
|
||||
|
||||
try {
|
||||
|
||||
$statement->execute([
|
||||
$this->normalize($county_code),
|
||||
$this->normalize($voter_id),
|
||||
$this->normalize($name_last),
|
||||
$this->normalize($name_suffix),
|
||||
$this->normalize($name_first),
|
||||
$this->normalize($name_middle),
|
||||
$this->normalize($public_exempt),
|
||||
$this->normalize($res_addr1),
|
||||
$this->normalize($res_addr2),
|
||||
$this->normalize($res_city),
|
||||
$this->normalize($res_state),
|
||||
$this->normalize($res_zip),
|
||||
$this->normalize($mail_addr1),
|
||||
$this->normalize($mail_addr2),
|
||||
$this->normalize($mail_addr3),
|
||||
$this->normalize($mail_city),
|
||||
$this->normalize($mail_state),
|
||||
$this->normalize($mail_zip),
|
||||
$this->normalize($mail_country),
|
||||
$this->normalize($gender),
|
||||
$this->normalize($race),
|
||||
$this->parseDate($birth_date),
|
||||
$this->parseDate($reg_date),
|
||||
$this->normalize($party),
|
||||
$this->normalize($precinct),
|
||||
$this->normalize($precinct_group),
|
||||
$this->normalize($precinct_split),
|
||||
$this->normalize($precinct_suffix),
|
||||
$this->normalize($status),
|
||||
$this->normalize($cd),
|
||||
$this->normalize($hd),
|
||||
$this->normalize($sd),
|
||||
$this->normalize($ccd),
|
||||
$this->normalize($sbd),
|
||||
$this->normalize($area),
|
||||
$this->normalize($phone),
|
||||
$this->normalize($ext),
|
||||
$this->normalize($email)
|
||||
]);
|
||||
|
||||
$counter++;
|
||||
|
||||
if (($counter % 10) === 0) {
|
||||
$this->log("Processed {$counter} records...");
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
$this->log("Insert failed {$file}:{$lineNum} - " . $e->getMessage());
|
||||
echo "❌ Insert failed {$file}:{$lineNum} → {$e->getMessage()}\n";
|
||||
}
|
||||
}
|
||||
|
||||
fclose($voterhistory);
|
||||
}
|
||||
|
||||
$this->log("Completed voter import. Total records processed: {$counter}");
|
||||
}
|
||||
|
||||
// =================================
|
||||
// Return a $this->normalized String
|
||||
// =================================
|
||||
|
||||
private function normalize(?string $value): ?string {
|
||||
|
||||
$value = trim((string) $value);
|
||||
|
||||
return ($value === '' || $value === '*') ? null : $value;
|
||||
}
|
||||
|
||||
// ====================
|
||||
// Return a Parsed Date
|
||||
// ====================
|
||||
|
||||
private function parseDate(?string $value): ?string {
|
||||
|
||||
$value = $this->normalize($value);
|
||||
if ($value === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$dt = DateTime::createFromFormat('m/d/Y', $value);
|
||||
|
||||
return $dt ? $dt->format('Y-m-d') : null;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
Reference in New Issue
Block a user