i finally committed i guess

Signed-off-by: boris <boris@borishub.co.uk>
This commit is contained in:
boris
2025-03-15 01:59:16 +00:00
parent 8de2b7f29e
commit 709596eea2
113 changed files with 25075 additions and 54344 deletions

586
Models/FacilityDataSet.php Normal file → Executable file
View File

@@ -12,76 +12,6 @@ class FacilityDataSet
$this->_dbHandle = $this->_dbInstance->getDbConnection();
}
/**
* @param $data
* @return bool
* Broken last minute, dont have time to fix.
* add / update facility to database from array of columns
*/
public function addFacility($data): bool
{
$userQuery = "
SELECT ecoUser.id FROM ecoUser
WHERE ecoUser.username = :contributor;
";
$catQuery = "
SELECT ecoCategories.id FROM ecoCategories
WHERE ecoCategories.name = :category;
";
$sqlQuery = "
INSERT OR REPLACE INTO ecoFacilities
(id,
title,
category,
description,
houseNumber,
streetName,
county,
town,
postcode,
lng,
lat,
contributor)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, -1, -1, ?)
;";
// gets contributor name
$stmt = $this->_dbHandle->prepare($userQuery);
$stmt->bindParam(':contributor', $data->contributor, PDO::PARAM_STR);
$stmt = $this->_dbHandle->prepare($userQuery);
$stmt->execute();
$data['contributor'] = (int)$stmt->fetch(PDO::FETCH_ASSOC);
// gets category ID
$stmt = $this->_dbHandle->prepare($catQuery);
$stmt->bindParam(':category', $data->category, PDO::PARAM_STR);
$stmt = $this->_dbHandle->prepare($catQuery);
$stmt->execute();
$data['category'] = (int)$stmt->fetch(PDO::FETCH_ASSOC);
// run main query and bind updated parameters
$stmt = $this->_dbHandle->prepare($sqlQuery);
// Ensures only one value is returned per column name
$stmt->setFetchMode(\PDO::FETCH_ASSOC);
if (isset($data['id'])) {
$stmt->bindParam(1, $data['id']);
}
$stmt->bindParam(2, $data['title'], PDO::PARAM_STR);
$stmt->bindParam(3, $data['category'], PDO::PARAM_INT);
$stmt->bindParam(4, $data['description'], PDO::PARAM_STR);
$stmt->bindParam(5, $data['houseNumber'], PDO::PARAM_STR);
$stmt->bindParam(6, $data['streetName'], PDO::PARAM_STR);
$stmt->bindParam(7, $data['county'], PDO::PARAM_STR);
$stmt->bindParam(8, $data['town'], PDO::PARAM_STR);
$stmt->bindParam(9, $data['postcode'], PDO::PARAM_STR);
$stmt->bindParam(10, $data['contributor'], PDO::PARAM_INT);
$stmt->execute();
// var_dump($stmt);
// var_dump($this->_dbHandle->errorInfo());
return !($stmt->rowCount());
}
/**
* @param $id
* @return bool
@@ -89,114 +19,444 @@ class FacilityDataSet
*/
public function deleteFacility($id): bool
{
$sqlQuery = "DELETE FROM ecoFacilities WHERE ecoFacilities.id = :id;";
$stmt = $this->_dbHandle->prepare($sqlQuery);
$stmt->bindValue(':id', (int)$id, \PDO::PARAM_INT);
$stmt->execute();
var_dump($stmt);
echo $stmt->rowCount();
return !($stmt->rowCount() == 0);
try {
// Start transaction
$this->_dbHandle->beginTransaction();
// Delete related status records first
$statusQuery = "DELETE FROM ecoFacilityStatus WHERE facilityid = :id;";
$statusStmt = $this->_dbHandle->prepare($statusQuery);
$statusStmt->bindValue(':id', (int)$id, \PDO::PARAM_INT);
$statusStmt->execute();
// Delete the facility
$facilityQuery = "DELETE FROM ecoFacilities WHERE id = :id;";
$facilityStmt = $this->_dbHandle->prepare($facilityQuery);
$facilityStmt->bindValue(':id', (int)$id, \PDO::PARAM_INT);
$facilityStmt->execute();
// Commit transaction
$this->_dbHandle->commit();
return $facilityStmt->rowCount() > 0;
} catch (PDOException $e) {
// Rollback on error
$this->_dbHandle->rollBack();
error_log("Error deleting facility: " . $e->getMessage());
return false;
}
}
/**
* @return array|false Returns array of facilities or false on error
* Fetch all facility records with related data
*/
public function fetchAll(): array|false
{
try {
error_log('Starting fetchAll...');
$query = "
SELECT DISTINCT ecoFacilities.id,
ecoFacilities.title,
COALESCE(GROUP_CONCAT(ecoFacilityStatus.statusComment, '; '), '') AS status,
ecoCategories.name AS category,
ecoFacilities.description,
ecoFacilities.houseNumber,
ecoFacilities.streetName,
ecoFacilities.county,
ecoFacilities.town,
ecoFacilities.postcode,
ecoFacilities.lng,
ecoFacilities.lat,
COALESCE(ecoUser.username, 'Unknown') AS contributor
FROM ecoFacilities
LEFT JOIN ecoCategories ON ecoCategories.id = ecoFacilities.category
LEFT JOIN ecoUser ON ecoUser.id = ecoFacilities.contributor
LEFT JOIN ecoFacilityStatus ON ecoFacilityStatus.facilityid = ecoFacilities.id
GROUP BY ecoFacilities.id, ecoFacilities.title, ecoCategories.name,
ecoFacilities.description, ecoFacilities.streetName,
ecoFacilities.county, ecoFacilities.town, ecoFacilities.postcode,
ecoUser.username
ORDER BY ecoFacilities.id ASC;
";
error_log('Preparing query...');
$dataStmt = $this->_dbHandle->prepare($query);
error_log('Executing query...');
$dataStmt->execute();
error_log('Fetching results...');
$results = $dataStmt->fetchAll(PDO::FETCH_ASSOC);
if ($results === false) {
error_log('Query returned false');
return false;
}
error_log('Query successful. Row count: ' . count($results));
return $results;
} catch (PDOException $e) {
error_log("Database error in fetchAll: " . $e->getMessage());
error_log("SQL State: " . $e->getCode());
error_log("Stack trace: " . $e->getTraceAsString());
return false;
} catch (Exception $e) {
error_log("General error in fetchAll: " . $e->getMessage());
error_log("Stack trace: " . $e->getTraceAsString());
return false;
}
}
/**
* @param $filterArray
* @param $sortArray
* @return array
* Fetch all records depending on filters, and sort by defined column
* Creates a new facility in the database
* @param array $data Facility data
* @return array|false The created facility data or false on failure
*/
public function fetchAll($filterArray, $sortArray): array
public function createFacility($data)
{
// Define columns for filtering and sorting
$filterColumns = [
0 => 'ecoFacilityStatus.statusComment',
1 => 'ecoFacilities.title',
2 => 'ecoCategories.name',
3 => 'ecoFacilities.description',
4 => 'ecoFacilities.streetName',
5 => 'ecoFacilities.county',
6 => 'ecoFacilities.town',
7 => 'ecoFacilities.postcode',
8 => 'ecoUser.username'
];
try {
$this->_dbHandle->beginTransaction();
$sortColumns = [
0 => 'ecoFacilityStatus.statusComment',
1 => 'ecoFacilities.title',
2 => 'ecoCategories.name',
3 => 'ecoFacilities.description',
4 => 'ecoFacilities.streetName',
5 => 'ecoFacilities.county',
6 => 'ecoFacilities.town',
7 => 'ecoFacilities.postcode',
8 => 'ecoUser.username'
];
// Validate coordinates
if (!is_numeric($data['lng']) || !is_numeric($data['lat']) ||
$data['lng'] < -180 || $data['lng'] > 180 ||
$data['lat'] < -90 || $data['lat'] > 90) {
throw new Exception('Invalid coordinates provided');
}
// Validate and select the filter column
$selectedFilterColumn = $filterColumns[$filterArray['category']] ?? 'ecoFacilities.title';
// Validate and select the sort column
$selectedSortColumn = $sortColumns[$sortArray['sort']] ?? 'ecoFacilities.title';
// Validate sort direction
$direction = strtolower($sortArray['dir']) === 'desc' ? 'DESC' : 'ASC';
// Base query for filtering and sorting
$baseQuery = "
FROM ecoFacilities
LEFT JOIN ecoCategories ON ecoCategories.id = ecoFacilities.category
LEFT JOIN ecoUser ON ecoUser.id = ecoFacilities.contributor
LEFT JOIN ecoFacilityStatus ON ecoFacilityStatus.facilityid = ecoFacilities.id
WHERE {$selectedFilterColumn} LIKE :term
";
// Get contributor ID
$contributorId = $this->getContributorId($data['contributor']);
if (!$contributorId) {
throw new Exception('Invalid contributor name');
}
// Get category ID
$categoryId = $this->getCategoryId($data['category']);
if (!$categoryId) {
// If category doesn't exist, create it
$categoryId = $this->createCategory($data['category']);
if (!$categoryId) {
throw new Exception('Failed to create category: ' . $data['category']);
}
}
// Query to count total results
$countQuery = "SELECT COUNT(DISTINCT ecoFacilities.id) AS total {$baseQuery}";
// Insert facility
$sql = "INSERT INTO ecoFacilities (title, category, description, houseNumber,
streetName, county, town, postcode, lng, lat, contributor)
VALUES (:title, :category, :description, :houseNumber,
:streetName, :county, :town, :postcode, :longitude, :latitude, :contributor)";
$stmt = $this->_dbHandle->prepare($sql);
$params = [
':title' => $data['title'],
':category' => $categoryId,
':description' => $data['description'],
':houseNumber' => $data['houseNumber'],
':streetName' => $data['streetName'],
':county' => $data['county'],
':town' => $data['town'],
':postcode' => $data['postcode'],
':longitude' => $data['lng'],
':latitude' => $data['lat'],
':contributor' => $contributorId
];
// Query to fetch filtered and sorted results
$dataQuery = "
SELECT DISTINCT ecoFacilities.id,
ecoFacilities.title,
GROUP_CONCAT(ecoFacilityStatus.statusComment, ', ') AS status,
ecoCategories.name AS category,
ecoFacilities.description,
ecoFacilities.houseNumber,
ecoFacilities.streetName,
ecoFacilities.county,
ecoFacilities.town,
ecoFacilities.postcode,
ecoFacilities.lng,
ecoFacilities.lat,
ecoUser.username AS contributor
{$baseQuery}
GROUP BY ecoFacilities.id, ecoFacilities.title, ecoCategories.name,
ecoFacilities.description, ecoFacilities.streetName,
ecoFacilities.county, ecoFacilities.town, ecoFacilities.postcode,
ecoUser.username
ORDER BY {$selectedSortColumn} {$direction};
";
// Surround 'term' with % to allow usage with LIKE
$filterArray['term'] = '%' . $filterArray['term'] . '%' ?? '%';
// Prepare and execute the count query
$countStmt = $this->_dbHandle->prepare($countQuery);
$countStmt->bindValue(':term', $filterArray['term'], PDO::PARAM_STR);
$countStmt->execute();
// Set total results to output of count statement
$totalResults = (int)$countStmt->fetchColumn();
error_log("Executing SQL with params: " . print_r($params, true));
if (!$stmt->execute($params)) {
throw new Exception('Failed to insert facility: ' . implode(', ', $stmt->errorInfo()));
}
// Prepare and execute the data query
$dataStmt = $this->_dbHandle->prepare($dataQuery);
$dataStmt->bindValue(':term', $filterArray['term'], PDO::PARAM_STR);
$dataStmt->execute();
$facilityId = $this->_dbHandle->lastInsertId();
$this->_dbHandle->commit();
// Fetch results into FacilityData objects
$dataSet = [];
while ($row = $dataStmt->fetch()) {
$dataSet[] = new FacilityData($row);
// Return the created facility
return $this->getFacilityById($facilityId);
} catch (Exception $e) {
$this->_dbHandle->rollBack();
error_log("Error in createFacility: " . $e->getMessage());
throw $e;
}
}
return [
'dataset' => $dataSet,
'count' => $totalResults
];
private function createCategory($categoryName)
{
try {
$sql = "INSERT INTO ecoCategories (name) VALUES (:name)";
$stmt = $this->_dbHandle->prepare($sql);
$stmt->execute([':name' => $categoryName]);
return $this->_dbHandle->lastInsertId();
} catch (Exception $e) {
error_log("Error creating category: " . $e->getMessage());
return false;
}
}
/**
* Updates an existing facility in the database
* @param int $id Facility ID
* @param array $data Updated facility data
* @return array|false The updated facility data or false on failure
*/
public function updateFacility($id, $data) {
try {
// Start transaction
$this->_dbHandle->beginTransaction();
// Validate coordinates
if (!is_numeric($data['lng']) || !is_numeric($data['lat']) ||
$data['lng'] < -180 || $data['lng'] > 180 ||
$data['lat'] < -90 || $data['lat'] > 90) {
throw new Exception('Invalid coordinates');
}
// Get Contributor ID
$query = "SELECT ecoUser.id FROM ecoUser WHERE ecoUser.username = :contributor;";
$stmt = $this->_dbHandle->prepare($query);
$stmt->bindValue(':contributor', $data['contributor']);
$stmt->execute();
$contributorResult = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$contributorResult) {
throw new Exception('Invalid contributor username');
}
$contributorId = $contributorResult['id'];
// Get Category ID
$query = "SELECT ecoCategories.id FROM ecoCategories WHERE ecoCategories.name = :category;";
$stmt = $this->_dbHandle->prepare($query);
$stmt->bindValue(':category', $data['category']);
$stmt->execute();
$categoryResult = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$categoryResult) {
throw new Exception('Invalid category name');
}
$categoryId = $categoryResult['id'];
// Update facility
$query = "
UPDATE ecoFacilities
SET title = :title,
category = :category,
description = :description,
houseNumber = :houseNumber,
streetName = :streetName,
county = :county,
town = :town,
postcode = :postcode,
lng = :lng,
lat = :lat,
contributor = :contributor
WHERE id = :id
";
$stmt = $this->_dbHandle->prepare($query);
$params = [
':title' => $data['title'],
':category' => $categoryId,
':description' => $data['description'],
':houseNumber' => $data['houseNumber'],
':streetName' => $data['streetName'],
':county' => $data['county'],
':town' => $data['town'],
':postcode' => $data['postcode'],
':lng' => $data['lng'],
':lat' => $data['lat'],
':contributor' => $contributorId,
':id' => $id
];
error_log("Executing update query with params: " . print_r($params, true));
if (!$stmt->execute($params)) {
throw new Exception('Failed to update facility: ' . implode(', ', $stmt->errorInfo()));
}
if ($stmt->rowCount() > 0) {
$this->_dbHandle->commit();
return $this->getFacilityById($id);
}
$this->_dbHandle->rollBack();
return false;
} catch (Exception $e) {
$this->_dbHandle->rollBack();
error_log("Error updating facility: " . $e->getMessage());
return false;
}
}
/**
* Gets a facility by its ID
* @param int $id Facility ID
* @return array|false The facility data or false if not found
*/
public function getFacilityById($id) {
try {
$query = "
SELECT DISTINCT ecoFacilities.id,
ecoFacilities.title,
COALESCE(GROUP_CONCAT(ecoFacilityStatus.statusComment, ';'), '') AS status,
ecoCategories.name AS category,
ecoFacilities.description,
ecoFacilities.houseNumber,
ecoFacilities.streetName,
ecoFacilities.county,
ecoFacilities.town,
ecoFacilities.postcode,
ecoFacilities.lng,
ecoFacilities.lat,
COALESCE(ecoUser.username, 'Unknown') AS contributor
FROM ecoFacilities
LEFT JOIN ecoCategories ON ecoCategories.id = ecoFacilities.category
LEFT JOIN ecoUser ON ecoUser.id = ecoFacilities.contributor
LEFT JOIN ecoFacilityStatus ON ecoFacilityStatus.facilityid = ecoFacilities.id
WHERE ecoFacilities.id = ?
GROUP BY ecoFacilities.id, ecoFacilities.title, ecoCategories.name,
ecoFacilities.description, ecoFacilities.streetName,
ecoFacilities.county, ecoFacilities.town, ecoFacilities.postcode,
ecoUser.username;
";
$stmt = $this->_dbHandle->prepare($query);
$stmt->execute([$id]);
return $stmt->fetch(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
error_log("Error getting facility: " . $e->getMessage());
return false;
}
}
private function getContributorId($username)
{
try {
$query = "SELECT ecoUser.id FROM ecoUser WHERE ecoUser.username = :username;";
$stmt = $this->_dbHandle->prepare($query);
$stmt->bindValue(':username', $username);
$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);
return $result ? $result['id'] : false;
} catch (Exception $e) {
error_log("Error getting contributor ID: " . $e->getMessage());
return false;
}
}
private function getCategoryId($categoryName)
{
try {
$query = "SELECT ecoCategories.id FROM ecoCategories WHERE ecoCategories.name = :name;";
$stmt = $this->_dbHandle->prepare($query);
$stmt->bindValue(':name', $categoryName);
$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);
return $result ? $result['id'] : false;
} catch (Exception $e) {
error_log("Error getting category ID: " . $e->getMessage());
return false;
}
}
/**
* Adds a new status comment to a facility
* @param int $facilityId The ID of the facility
* @param string $statusComment The status comment to add
* @return bool True if successful, false otherwise
*/
public function addFacilityStatus($facilityId, $statusComment)
{
try {
// Log input parameters
error_log("Adding facility status - Facility ID: " . $facilityId . ", Comment: " . $statusComment);
// Start transaction
$this->_dbHandle->beginTransaction();
// Insert new status comment
$query = "INSERT INTO ecoFacilityStatus (facilityId, statusComment) VALUES (:facilityId, :statusComment)";
$stmt = $this->_dbHandle->prepare($query);
// Log the prepared statement
error_log("Prepared statement: " . $query);
// Bind values and log them
$stmt->bindValue(':facilityId', (int)$facilityId, PDO::PARAM_INT);
$stmt->bindValue(':statusComment', $statusComment);
error_log("Bound values - Facility ID: " . (int)$facilityId . ", Comment: " . $statusComment);
if (!$stmt->execute()) {
$errorInfo = $stmt->errorInfo();
error_log("SQL Error: " . print_r($errorInfo, true));
throw new Exception('Failed to insert status comment: ' . implode(', ', $errorInfo));
}
$this->_dbHandle->commit();
error_log("Successfully added facility status");
return true;
} catch (Exception $e) {
$this->_dbHandle->rollBack();
error_log("Error adding facility status: " . $e->getMessage());
error_log("Stack trace: " . $e->getTraceAsString());
return false;
}
}
/**
* Gets all status comments for a facility
* @param int $facilityId The ID of the facility
* @return array Array of status comments with their IDs
*/
public function getFacilityStatuses($facilityId)
{
try {
$query = "SELECT id, statusComment FROM ecoFacilityStatus WHERE facilityId = :facilityId ORDER BY id DESC";
$stmt = $this->_dbHandle->prepare($query);
$stmt->bindValue(':facilityId', (int)$facilityId, PDO::PARAM_INT);
$stmt->execute();
return $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (Exception $e) {
error_log("Error getting facility statuses: " . $e->getMessage());
return [];
}
}
/**
* Updates an existing status comment
* @param int $statusId The ID of the status comment
* @param string $statusComment The updated status comment
* @return bool True if successful, false otherwise
*/
public function updateFacilityStatus($statusId, $statusComment)
{
try {
$query = "UPDATE ecoFacilityStatus SET statusComment = :statusComment WHERE id = :statusId";
$stmt = $this->_dbHandle->prepare($query);
$stmt->bindValue(':statusId', (int)$statusId, PDO::PARAM_INT);
$stmt->bindValue(':statusComment', $statusComment);
return $stmt->execute();
} catch (Exception $e) {
error_log("Error updating facility status: " . $e->getMessage());
return false;
}
}
/**
* Deletes a specific status comment
* @param int $statusId The ID of the status comment to delete
* @return bool True if successful, false otherwise
*/
public function deleteFacilityStatus($statusId)
{
try {
$query = "DELETE FROM ecoFacilityStatus WHERE id = :statusId";
$stmt = $this->_dbHandle->prepare($query);
$stmt->bindValue(':statusId', (int)$statusId, PDO::PARAM_INT);
return $stmt->execute();
} catch (Exception $e) {
error_log("Error deleting facility status: " . $e->getMessage());
return false;
}
}
}