Fix: Updated ContactController to use Response::error(), injected DB connection into ContactModel, added GET route for contact page in index.php

This commit is contained in:
essae 2025-05-13 00:36:15 -04:00
parent e4ff1f0a59
commit 761c41d3bb
42 changed files with 612 additions and 661 deletions

View File

@ -2,8 +2,8 @@
namespace WizdomNetworks\WizeWeb\Controllers; namespace WizdomNetworks\WizeWeb\Controllers;
use WizdomNetworks\WizeWeb\Core\View; use WizdomNetworks\WizeWeb\Core\View;
use WizdomNetworks\WizeWeb\Utils\Logger; use WizdomNetworks\WizeWeb\Utilities\Logger;
use WizdomNetworks\WizeWeb\Utils\ErrorHandler; use WizdomNetworks\WizeWeb\Utilities\ErrorHandler;
class AboutController class AboutController
{ {

View File

@ -2,8 +2,8 @@
namespace WizdomNetworks\WizeWeb\Controllers; namespace WizdomNetworks\WizeWeb\Controllers;
use WizdomNetworks\WizeWeb\Core\View; use WizdomNetworks\WizeWeb\Core\View;
use WizdomNetworks\WizeWeb\Utils\Logger; use WizdomNetworks\WizeWeb\Utilities\Logger;
use WizdomNetworks\WizeWeb\Utils\ErrorHandler; use WizdomNetworks\WizeWeb\Utilities\ErrorHandler;
class ClientsController class ClientsController
{ {

View File

@ -1,89 +1,93 @@
<?php <?php
/** /**
* ============================================
* File: ContactController.php * File: ContactController.php
* Version: 1.2
* Path: /app/Controllers/ContactController.php * Path: /app/Controllers/ContactController.php
* Purpose: Handles form submissions from the Arsha contact form * Purpose: Handles contact form display and submission logic.
* Version: 1.1 * Project: Wizdom Networks Website
* Author: Wizdom Networks
* Usage: Routed via Router to handle POST /contact
* ============================================
*/ */
namespace WizdomNetworks\WizeWeb\Controllers; namespace WizdomNetworks\WizeWeb\Controllers;
use WizdomNetworks\WizeWeb\Core\View; use WizdomNetworks\WizeWeb\Core\View;
use WizdomNetworks\WizeWeb\Utilities\Logger; use WizdomNetworks\WizeWeb\Utilities\Logger;
use WizdomNetworks\WizeWeb\Utilities\ErrorHandler;
use WizdomNetworks\WizeWeb\Utilities\EmailUtility;
use WizdomNetworks\WizeWeb\Utilities\Sanitizer;
use WizdomNetworks\WizeWeb\Utilities\Validator; use WizdomNetworks\WizeWeb\Utilities\Validator;
use WizdomNetworks\WizeWeb\Utilities\Response; use WizdomNetworks\WizeWeb\Utilities\Response;
use WizdomNetworks\WizeWeb\Utilities\SubmissionCheck; use WizdomNetworks\WizeWeb\Utilities\Sanitizer;
use WizdomNetworks\WizeWeb\Utilities\Database; use WizdomNetworks\WizeWeb\Models\ContactModel;
use PHPMailer\PHPMailer\PHPMailer; use Exception;
use PHPMailer\PHPMailer\Exception;
class ContactController class ContactController
{ {
/**
* Display the contact form page.
*
* @return void
*/
public function index(): void
{
View::render('pages/contact');
}
/**
* Handle contact form submission.
*
* @return void
*/
public function submit(): void public function submit(): void
{ {
try { try {
$firstName = Sanitizer::sanitizeString($_POST['first_name'] ?? ''); if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
$lastName = Sanitizer::sanitizeString($_POST['last_name'] ?? ''); Response::badRequest('Invalid request method.');
$email = Sanitizer::sanitizeEmail($_POST['email'] ?? '');
$phone = Sanitizer::sanitizePhone($_POST['phone'] ?? '');
$message = Sanitizer::sanitizeText($_POST['message'] ?? '');
if (!$firstName || !$lastName || !$email || !$phone || !$message) {
Response::jsonError('All fields must be filled out.');
return;
} }
if (!Validator::isValidEmail($email)) { $data = $_POST;
Response::jsonError('Please provide a valid email address.');
return; // Validate required fields
$requiredFields = ['first_name', 'last_name', 'email', 'message'];
foreach ($requiredFields as $field) {
if (empty($data[$field])) {
Response::badRequest("Missing required field: $field");
}
} }
// Check if email has submitted recently // Sanitize input
if (SubmissionCheck::isDuplicateContactEmail($email)) { $firstName = Sanitizer::sanitizeString($data['first_name']);
$lastDate = SubmissionCheck::getLastContactSubmissionDate($email); $lastName = Sanitizer::sanitizeString($data['last_name']);
Response::jsonError("This email already submitted a message on $lastDate. Please wait a week before sending another or contact us directly."); $email = Sanitizer::sanitizeString($data['email']);
return; $message = Sanitizer::sanitizeString($data['message']);
// Validate email format
if (!Validator::isEmail($email)) {
Response::badRequest('Invalid email address.');
} }
$db = Database::getConnection(); $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
$stmt = $db->prepare("INSERT INTO contact_messages (first_name, last_name, email, phone, message, ip_address, user_agent) $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? 'unknown';
VALUES (?, ?, ?, ?, ?, ?, ?)");
$stmt->execute([ // Insert into database
$firstName, $contact = new ContactModel();
$lastName, $result = $contact->save([
$email, 'first_name' => $firstName,
$phone, 'last_name' => $lastName,
$message, 'email' => $email,
$_SERVER['REMOTE_ADDR'] ?? 'unknown', 'message' => $message,
$_SERVER['HTTP_USER_AGENT'] ?? 'unknown' 'ip_address' => $ip,
'user_agent' => $userAgent,
]); ]);
Logger::info("Contact form submitted by $firstName $lastName <$email>"); if (!$result) {
Logger::logError("Failed to save contact form submission for email: $email");
Response::serverError('An error occurred while submitting your message. Please try again later.');
}
// Send internal notification email Response::json([
EmailUtility::sendInternalContactAlert([ 'success' => true,
'first_name' => $firstName, 'message' => 'Your message has been successfully submitted. Thank you!'
'last_name' => $lastName,
'email' => $email,
'phone' => $phone,
'message' => $message
]); ]);
} catch (Exception $e) {
// Send confirmation to user Logger::logError("Exception during contact form submission: " . $e->getMessage());
EmailUtility::sendContactConfirmation($email, $firstName); Response::serverError('A server error occurred. Please try again later.');
Response::jsonSuccess('Thank you. We will be in touch shortly.');
} catch (\Throwable $e) {
ErrorHandler::exception($e);
Response::jsonError('An internal error occurred. Please try again later.');
} }
} }
} }

View File

@ -2,8 +2,8 @@
namespace WizdomNetworks\WizeWeb\Controllers; namespace WizdomNetworks\WizeWeb\Controllers;
use WizdomNetworks\WizeWeb\Core\View; use WizdomNetworks\WizeWeb\Core\View;
use WizdomNetworks\WizeWeb\Utils\Logger; use WizdomNetworks\WizeWeb\Utilities\Logger;
use WizdomNetworks\WizeWeb\Utils\ErrorHandler; use WizdomNetworks\WizeWeb\Utilities\ErrorHandler;
class EmergencySupportController class EmergencySupportController
{ {

View File

@ -2,8 +2,8 @@
namespace WizdomNetworks\WizeWeb\Controllers; namespace WizdomNetworks\WizeWeb\Controllers;
use WizdomNetworks\WizeWeb\Core\View; use WizdomNetworks\WizeWeb\Core\View;
use WizdomNetworks\WizeWeb\Utils\Logger; use WizdomNetworks\WizeWeb\Utilities\Logger;
use WizdomNetworks\WizeWeb\Utils\ErrorHandler; use WizdomNetworks\WizeWeb\Utilities\ErrorHandler;
class HelpDeskController class HelpDeskController
{ {

View File

@ -2,8 +2,8 @@
namespace WizdomNetworks\WizeWeb\Controllers; namespace WizdomNetworks\WizeWeb\Controllers;
use WizdomNetworks\WizeWeb\Core\View; use WizdomNetworks\WizeWeb\Core\View;
use WizdomNetworks\WizeWeb\Utils\Logger; use WizdomNetworks\WizeWeb\Utilities\Logger;
use WizdomNetworks\WizeWeb\Utils\ErrorHandler; use WizdomNetworks\WizeWeb\Utilities\ErrorHandler;
class HomeController class HomeController
{ {

View File

@ -2,8 +2,8 @@
namespace WizdomNetworks\WizeWeb\Controllers; namespace WizdomNetworks\WizeWeb\Controllers;
use WizdomNetworks\WizeWeb\Core\View; use WizdomNetworks\WizeWeb\Core\View;
use WizdomNetworks\WizeWeb\Utils\Logger; use WizdomNetworks\WizeWeb\Utilities\Logger;
use WizdomNetworks\WizeWeb\Utils\ErrorHandler; use WizdomNetworks\WizeWeb\Utilities\ErrorHandler;
class ITConsultingController class ITConsultingController
{ {

View File

@ -7,7 +7,7 @@
namespace WizdomNetworks\WizeWeb\Controllers; namespace WizdomNetworks\WizeWeb\Controllers;
use WizdomNetworks\WizeWeb\Core\View; use WizdomNetworks\WizeWeb\Core\View;
use WizdomNetworks\WizeWeb\Utils\Logger; use WizdomNetworks\WizeWeb\Utilities\Logger;
class LandingController class LandingController
{ {

View File

@ -2,8 +2,8 @@
namespace WizdomNetworks\WizeWeb\Controllers; namespace WizdomNetworks\WizeWeb\Controllers;
use WizdomNetworks\WizeWeb\Core\View; use WizdomNetworks\WizeWeb\Core\View;
use WizdomNetworks\WizeWeb\Utils\Logger; use WizdomNetworks\WizeWeb\Utilities\Logger;
use WizdomNetworks\WizeWeb\Utils\ErrorHandler; use WizdomNetworks\WizeWeb\Utilities\ErrorHandler;
class ManagedServicesController class ManagedServicesController
{ {

View File

@ -2,8 +2,8 @@
namespace WizdomNetworks\WizeWeb\Controllers; namespace WizdomNetworks\WizeWeb\Controllers;
use WizdomNetworks\WizeWeb\Core\View; use WizdomNetworks\WizeWeb\Core\View;
use WizdomNetworks\WizeWeb\Utils\Logger; use WizdomNetworks\WizeWeb\Utilities\Logger;
use WizdomNetworks\WizeWeb\Utils\ErrorHandler; use WizdomNetworks\WizeWeb\Utilities\ErrorHandler;
class OnlineBrandManagementController class OnlineBrandManagementController
{ {

View File

@ -2,8 +2,8 @@
namespace WizdomNetworks\WizeWeb\Controllers; namespace WizdomNetworks\WizeWeb\Controllers;
use WizdomNetworks\WizeWeb\Core\View; use WizdomNetworks\WizeWeb\Core\View;
use WizdomNetworks\WizeWeb\Utils\Logger; use WizdomNetworks\WizeWeb\Utilities\Logger;
use WizdomNetworks\WizeWeb\Utils\ErrorHandler; use WizdomNetworks\WizeWeb\Utilities\ErrorHandler;
class ProjectManagementController class ProjectManagementController
{ {

View File

@ -2,8 +2,8 @@
namespace WizdomNetworks\WizeWeb\Controllers; namespace WizdomNetworks\WizeWeb\Controllers;
use WizdomNetworks\WizeWeb\Core\View; use WizdomNetworks\WizeWeb\Core\View;
use WizdomNetworks\WizeWeb\Utils\Logger; use WizdomNetworks\WizeWeb\Utilities\Logger;
use WizdomNetworks\WizeWeb\Utils\ErrorHandler; use WizdomNetworks\WizeWeb\Utilities\ErrorHandler;
class ServicesController class ServicesController
{ {

View File

@ -2,8 +2,8 @@
namespace WizdomNetworks\WizeWeb\Controllers; namespace WizdomNetworks\WizeWeb\Controllers;
use WizdomNetworks\WizeWeb\Core\View; use WizdomNetworks\WizeWeb\Core\View;
use WizdomNetworks\WizeWeb\Utils\Logger; use WizdomNetworks\WizeWeb\Utilities\Logger;
use WizdomNetworks\WizeWeb\Utils\ErrorHandler; use WizdomNetworks\WizeWeb\Utilities\ErrorHandler;
class TestimonialsController class TestimonialsController
{ {

View File

@ -2,8 +2,8 @@
namespace WizdomNetworks\WizeWeb\Core; namespace WizdomNetworks\WizeWeb\Core;
use WizdomNetworks\WizeWeb\Utils\Logger; use WizdomNetworks\WizeWeb\Utilities\Logger;
use WizdomNetworks\WizeWeb\Utils\ErrorHandler; use WizdomNetworks\WizeWeb\Utilities\ErrorHandler;
/** /**
* Base Controller * Base Controller

View File

@ -12,8 +12,8 @@
namespace WizdomNetworks\WizeWeb\Core; namespace WizdomNetworks\WizeWeb\Core;
use WizdomNetworks\WizeWeb\Utils\Logger; use WizdomNetworks\WizeWeb\Utilities\Logger;
use WizdomNetworks\WizeWeb\Utils\ErrorHandler; use WizdomNetworks\WizeWeb\Utilities\ErrorHandler;
class Router class Router
{ {

View File

@ -12,8 +12,8 @@
namespace WizdomNetworks\WizeWeb\Core; namespace WizdomNetworks\WizeWeb\Core;
use WizdomNetworks\WizeWeb\Utils\Logger; use WizdomNetworks\WizeWeb\Utilities\Logger;
use WizdomNetworks\WizeWeb\Utils\ErrorHandler; use WizdomNetworks\WizeWeb\Utilities\ErrorHandler;
/** /**
* View Renderer * View Renderer

View File

@ -2,8 +2,8 @@
namespace WizdomNetworks\WizeWeb\Models; namespace WizdomNetworks\WizeWeb\Models;
use WizdomNetworks\WizeWeb\Utils\Logger; use WizdomNetworks\WizeWeb\Utilities\Logger;
use WizdomNetworks\WizeWeb\Utils\ErrorHandler; use WizdomNetworks\WizeWeb\Utilities\ErrorHandler;
/** /**
* Client Model * Client Model

View File

@ -2,8 +2,8 @@
namespace WizdomNetworks\WizeWeb\Models; namespace WizdomNetworks\WizeWeb\Models;
use WizdomNetworks\WizeWeb\Utils\Logger; use WizdomNetworks\WizeWeb\Utilities\Logger;
use WizdomNetworks\WizeWeb\Utils\ErrorHandler; use WizdomNetworks\WizeWeb\Utilities\ErrorHandler;
/** /**
* Contact Model * Contact Model

View File

@ -2,8 +2,8 @@
namespace WizdomNetworks\WizeWeb\Models; namespace WizdomNetworks\WizeWeb\Models;
use WizdomNetworks\WizeWeb\Utils\Logger; use WizdomNetworks\WizeWeb\Utilities\Logger;
use WizdomNetworks\WizeWeb\Utils\ErrorHandler; use WizdomNetworks\WizeWeb\Utilities\ErrorHandler;
/** /**
* Service Model * Service Model

View File

@ -2,8 +2,8 @@
namespace WizdomNetworks\WizeWeb\Models; namespace WizdomNetworks\WizeWeb\Models;
use WizdomNetworks\WizeWeb\Utils\Logger; use WizdomNetworks\WizeWeb\Utilities\Logger;
use WizdomNetworks\WizeWeb\Utils\ErrorHandler; use WizdomNetworks\WizeWeb\Utilities\ErrorHandler;
/** /**
* Service Model * Service Model

View File

@ -1,6 +1,6 @@
<?php <?php
namespace WizdomNetworks\WizeWeb\Utils; namespace WizdomNetworks\WizeWeb\Utilities;
/** /**
* Utility class to inspect declared classes and autoloading in the application. * Utility class to inspect declared classes and autoloading in the application.

View File

@ -1,8 +1,8 @@
<?php <?php
namespace WizdomNetworks\WizeWeb\Utils; namespace WizdomNetworks\WizeWeb\Utilities;
use WizdomNetworks\WizeWeb\Utils\Logger; use WizdomNetworks\WizeWeb\Utilities\Logger;
/** /**
* ErrorHandler Utility * ErrorHandler Utility
@ -60,6 +60,7 @@ class ErrorHandler
); );
Logger::error($message); Logger::error($message);
http_response_code(500); http_response_code(500);
echo "$message";
echo "An internal error occurred. Please try again later."; echo "An internal error occurred. Please try again later.";
exit; exit;
} }

View File

@ -1,8 +1,8 @@
<?php <?php
namespace WizdomNetworks\WizeWeb\Utils; namespace WizdomNetworks\WizeWeb\Utilities;
use WizdomNetworks\WizeWeb\Utils\ErrorHandler; use WizdomNetworks\WizeWeb\Utilities\ErrorHandler;
/** /**
* Logger Utility * Logger Utility

View File

@ -1,9 +1,9 @@
<?php <?php
namespace WizdomNetworks\WizeWeb\Utils; namespace WizdomNetworks\WizeWeb\Utilities;
use WizdomNetworks\WizeWeb\Utils\Logger; use WizdomNetworks\WizeWeb\Utilities\Logger;
use WizdomNetworks\WizeWeb\Utils\ErrorHandler; use WizdomNetworks\WizeWeb\Utilities\ErrorHandler;
/** /**
* NamespaceUpdater Utility * NamespaceUpdater Utility

View File

@ -0,0 +1,244 @@
<?php
namespace WizdomNetworks\WizeWeb\Utilities;
use WizdomNetworks\WizeWeb\Utilities\Logger;
class QueueUtility
{
private string $queueDir;
public function __construct(string $queueDir)
{
$this->queueDir = $queueDir;
// Ensure the queue directory exists
if (!is_dir($this->queueDir)) {
mkdir($this->queueDir, 0755, true);
Logger::logInfo("Queue directory created at: $this->queueDir");
}
}
/**
* Add a task to the queue with priority and expiration.
*
* @param string $queueName The name of the queue.
* @param array $task The task to enqueue.
* @param int $priority The priority of the task (lower value = higher priority).
* @param int $ttl Time-to-live in seconds (0 for no expiration).
* @return bool True if the task is added successfully, false otherwise.
*/
public function enqueue(string $queueName, array $task, int $priority = 0, int $ttl = 0): bool
{
$queueFile = $this->queueDir . "/$queueName.queue";
$expiry = $ttl > 0 ? time() + $ttl : 0;
try {
$taskData = serialize(['priority' => $priority, 'expiry' => $expiry, 'task' => $task]);
file_put_contents($queueFile, $taskData . PHP_EOL, FILE_APPEND | LOCK_EX);
Logger::logInfo("Task added to queue: $queueName with priority $priority and expiry $expiry");
return true;
} catch (\Throwable $e) {
Logger::logError("Failed to enqueue task: " . $e->getMessage());
return false;
}
}
/**
* Retrieve and remove the next task from the queue, considering priority and expiration.
*
* @param string $queueName The name of the queue.
* @return array|null The next task, or null if the queue is empty.
*/
public function dequeue(string $queueName): ?array
{
$queueFile = $this->queueDir . "/$queueName.queue";
if (!file_exists($queueFile)) {
Logger::logInfo("Queue file does not exist: $queueFile");
return null;
}
try {
$lines = file($queueFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
if (empty($lines)) {
unlink($queueFile);
Logger::logInfo("Queue is empty: $queueName");
return null;
}
// Sort tasks by priority and expiration
$tasks = array_map('unserialize', $lines);
usort($tasks, function ($a, $b) {
return $a['priority'] <=> $b['priority'] ?: $a['expiry'] <=> $b['expiry'];
});
// Find the next valid task
$updatedLines = [];
$nextTask = null;
foreach ($tasks as $taskData) {
if ($taskData['expiry'] > 0 && $taskData['expiry'] < time()) {
Logger::logInfo("Skipping expired task in queue: $queueName");
continue;
}
if ($nextTask === null) {
$nextTask = $taskData['task'];
} else {
$updatedLines[] = serialize($taskData);
}
}
file_put_contents($queueFile, implode(PHP_EOL, $updatedLines) . PHP_EOL, LOCK_EX);
return $nextTask;
} catch (\Throwable $e) {
Logger::logError("Failed to dequeue task: " . $e->getMessage());
return null;
}
}
/**
* Retry a failed task by re-adding it to the queue.
*
* @param string $queueName The name of the queue.
* @param array $task The task to retry.
* @param int $priority The priority of the task.
* @param int $retryLimit The maximum number of retries allowed.
* @param int $currentRetry The current retry count (default: 0).
* @return bool True if the task is retried successfully, false otherwise.
*/
public function retryTask(string $queueName, array $task, int $priority = 0, int $retryLimit = 3, int $currentRetry = 0): bool
{
if ($currentRetry >= $retryLimit) {
Logger::logWarning("Task moved to dead letter queue after exceeding retry limit: $queueName");
$this->enqueue("dead_letter_$queueName", $task, $priority);
return false;
}
Logger::logInfo("Retrying task in queue: $queueName, attempt: " . ($currentRetry + 1));
return $this->enqueue($queueName, $task, $priority);
}
/**
* Get the status of a queue.
*
* @param string $queueName The name of the queue.
* @return array|null Queue statistics or null if the queue does not exist.
*/
public function getQueueStats(string $queueName): ?array
{
$queueFile = $this->queueDir . "/$queueName.queue";
if (!file_exists($queueFile)) {
return null;
}
$lines = file($queueFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$tasks = array_map('unserialize', $lines);
return [
'total_tasks' => count($tasks),
'last_modified' => date('Y-m-d H:i:s', filemtime($queueFile)),
'oldest_task' => $tasks[0]['task'] ?? null,
];
}
/**
* Clear all tasks in a queue.
*
* @param string $queueName The name of the queue.
* @return bool True if the queue is cleared successfully, false otherwise.
*/
public function clearQueue(string $queueName): bool
{
$queueFile = $this->queueDir . "/$queueName.queue";
if (!file_exists($queueFile)) {
Logger::logInfo("Queue file does not exist: $queueFile");
return false;
}
try {
unlink($queueFile);
Logger::logInfo("Queue cleared: $queueName");
return true;
} catch (\Throwable $e) {
Logger::logError("Failed to clear queue: " . $e->getMessage());
return false;
}
}
/**
* List all available queues.
*
* @return array List of queue names.
*/
public function listQueues(): array
{
$files = glob($this->queueDir . '/*.queue');
return array_map(function ($file) {
return basename($file, '.queue');
}, $files);
}
/**
* Clear all queues in the directory.
*
* @return bool True if all queues are cleared successfully, false otherwise.
*/
public function clearAllQueues(): bool
{
try {
$files = glob($this->queueDir . '/*.queue');
foreach ($files as $file) {
unlink($file);
}
Logger::logInfo("All queues cleared.");
return true;
} catch (\Throwable $e) {
Logger::logError("Failed to clear all queues: " . $e->getMessage());
return false;
}
}
/**
* Retrieve and remove a batch of tasks from the queue.
*
* @param string $queueName The name of the queue.
* @param int $batchSize The number of tasks to dequeue.
* @return array List of tasks.
*/
public function dequeueBatch(string $queueName, int $batchSize = 10): array
{
$queueFile = "$this->queueDir/$queueName.queue";
if (!file_exists($queueFile)) {
Logger::logInfo("Queue file does not exist: $queueFile");
return [];
}
try {
$lines = file($queueFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
if (empty($lines)) {
unlink($queueFile);
Logger::logInfo("Queue is empty: $queueName");
return [];
}
$tasks = array_map('unserialize', $lines);
usort($tasks, fn($a, $b) => $a['priority'] <=> $b['priority']);
$batch = array_splice($tasks, 0, $batchSize);
file_put_contents($queueFile, implode(PHP_EOL, array_map('serialize', $tasks)) . PHP_EOL);
return array_map(fn($task) => $task['task'], $batch);
} catch (Throwable $e) {
Logger::logError("Failed to dequeue batch: " . $e->getMessage());
return [];
}
}
}
?>

View File

@ -1,86 +1,98 @@
<?php <?php
/**
* ============================================
* File: Sanitizer.php
* Path: /app/Utils/
* Purpose: Utility class for sanitizing all user input securely
* Version: 1.1
* Author: Wizdom Networks (merged from HelpDesk+ and WizdomWeb)
* Usage: Called wherever input data needs cleaning before use or DB insertion
* ============================================
*/
namespace WizdomNetworks\WizeWeb\Utilities; namespace WizdomNetworks\WizeWeb\Utilities;
use WizdomNetworks\WizeWeb\Utilities\Logger; use WizdomNetworks\WizeWeb\Utilities\Logger;
use WizdomNetworks\WizeWeb\Utilities\ErrorHandler; use WizdomNetworks\WizeWeb\Utilities\ErrorHandler;
/**
* Sanitizer Utility
*
* Provides secure, traceable input sanitation with modern and recursive handling.
*/
class Sanitizer class Sanitizer
{ {
/** /**
* Basic string sanitization (removes HTML and encodes entities) * Sanitizes a string using modern techniques.
*/ */
public static function sanitizeString(string $value): string public static function sanitizeString(string $value): string
{
return self::sanitizeInput($value); // alias to avoid deprecated filters
}
/**
* Performs chained sanitation: trim, strip_tags, htmlspecialchars.
*/
public static function sanitizeInput(string $value): string
{ {
try { try {
$sanitized = htmlspecialchars(strip_tags(trim($value)), ENT_QUOTES, 'UTF-8'); $sanitized = htmlspecialchars(strip_tags(trim($value)));
Logger::debug("Sanitized string: Original: $value | Sanitized: $sanitized"); Logger::info("Sanitized input: Original: $value | Sanitized: $sanitized");
return $sanitized; return $sanitized;
} catch (\Throwable $e) { } catch (\Throwable $e) {
Logger::error("Failed to sanitize input: $value");
ErrorHandler::exception($e); ErrorHandler::exception($e);
return ''; return '';
} }
} }
/** /**
* Deep sanitize string using multiple layers (chained method) * Alias to sanitizeInput() for semantic clarity.
*/ */
public static function sanitizeChained(string $value): string public static function sanitizeChained(string $value): string
{ {
return htmlspecialchars(strip_tags(trim(filter_var($value, FILTER_SANITIZE_STRING))), ENT_QUOTES, 'UTF-8'); return self::sanitizeInput($value);
} }
/** /**
* Sanitize input with tag stripping and encoding * Sanitizes an email address.
*/
public static function sanitizeInput(string $value): string
{
return htmlspecialchars(strip_tags(trim($value)), ENT_QUOTES, 'UTF-8');
}
/**
* Sanitize email
*/ */
public static function sanitizeEmail(string $value): string public static function sanitizeEmail(string $value): string
{ {
$sanitized = filter_var(trim($value), FILTER_SANITIZE_EMAIL); try {
Logger::debug("Sanitized email: Original: $value | Sanitized: $sanitized"); $sanitized = filter_var($value, FILTER_SANITIZE_EMAIL);
return $sanitized; Logger::info("Sanitized email: Original: $value | Sanitized: $sanitized");
return $sanitized;
} catch (\Throwable $e) {
Logger::error("Failed to sanitize email: $value");
ErrorHandler::exception($e);
return '';
}
} }
/** /**
* Sanitize URL * Sanitizes a URL.
*/ */
public static function sanitizeURL(string $value): string public static function sanitizeURL(string $value): string
{ {
$sanitized = filter_var(trim($value), FILTER_SANITIZE_URL); try {
Logger::debug("Sanitized URL: Original: $value | Sanitized: $sanitized"); $sanitized = filter_var($value, FILTER_SANITIZE_URL);
return $sanitized; Logger::info("Sanitized URL: Original: $value | Sanitized: $sanitized");
return $sanitized;
} catch (\Throwable $e) {
Logger::error("Failed to sanitize URL: $value");
ErrorHandler::exception($e);
return '';
}
} }
/** /**
* Recursively sanitize array * Recursively sanitizes a nested array using sanitizeInput.
*/ */
public static function sanitizeArray(array $data): array public static function sanitizeArray(array $values): array
{ {
$clean = []; try {
foreach ($data as $key => $value) { $sanitizedArray = array_map(function ($item) {
if (is_array($value)) { return is_array($item)
$clean[$key] = self::sanitizeArray($value); ? self::sanitizeArray($item)
} else { : self::sanitizeInput((string)$item);
$clean[$key] = self::sanitizeString((string) $value); }, $values);
} Logger::info("Sanitized array: Original: " . json_encode($values) . " | Sanitized: " . json_encode($sanitizedArray));
return $sanitizedArray;
} catch (\Throwable $e) {
Logger::error("Failed to sanitize array: " . json_encode($values));
ErrorHandler::exception($e);
return [];
} }
return $clean;
} }
} }

View File

@ -1,9 +1,9 @@
<?php <?php
namespace WizdomNetworks\WizeWeb\Utils; namespace WizdomNetworks\WizeWeb\Utilities;
use WizdomNetworks\WizeWeb\Utils\Logger; use WizdomNetworks\WizeWeb\Utilities\Logger;
use WizdomNetworks\WizeWeb\Utils\ErrorHandler; use WizdomNetworks\WizeWeb\Utilities\ErrorHandler;
/** /**
* StructureGenerator Utility * StructureGenerator Utility

View File

@ -1,78 +0,0 @@
<?php
namespace WizdomNetworks\WizeWeb\Utils;
use PDO;
use PDOException;
/**
* Database Utility
*
* A utility for managing database connections and queries.
*
* Integrates logging for connection status and query execution.
*/
class Database
{
/**
* @var PDO|null The PDO instance for database connection.
*/
private ?PDO $connection = null;
/**
* Database constructor.
*
* Initializes the database connection.
*/
public function __construct()
{
$this->connect();
}
/**
* Establishes a connection to the database.
*/
private function connect(): void
{
$dsn = sprintf('mysql:host=%s;dbname=%s;charset=utf8mb4', $_ENV['DB_HOST'], $_ENV['DB_NAME']);
try {
$this->connection = new PDO($dsn, $_ENV['DB_USER'], $_ENV['DB_PASSWORD']);
$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Logger::info('Database connection established successfully.');
} catch (PDOException $e) {
Logger::error('Database connection failed: ' . $e->getMessage());
throw $e;
}
}
/**
* Executes a query and returns the result.
*
* @param string $query The SQL query to execute.
* @param array $params Parameters for prepared statements (optional).
* @return array The query result.
*/
public function query(string $query, array $params = []): array
{
try {
$stmt = $this->connection->prepare($query);
$stmt->execute($params);
Logger::info('Query executed successfully: ' . $query);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
Logger::error('Query failed: ' . $query . ' | Error: ' . $e->getMessage());
throw $e;
}
}
/**
* Retrieves the PDO connection instance.
*
* @return PDO The PDO instance.
*/
public function getConnection(): PDO
{
return $this->connection;
}
}

View File

@ -1,97 +0,0 @@
<?php
namespace WizdomNetworks\WizeWeb\Utils;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
use WizdomNetworks\WizeWeb\Utils\Logger;
use WizdomNetworks\WizeWeb\Utils\ErrorHandler;
/**
* Mailer Utility
*
* A utility class for sending emails using PHPMailer.
*
* Integrates logging for email success and failure events.
*/
class Mailer
{
/**
* @var PHPMailer The PHPMailer instance used for sending emails.
*/
protected PHPMailer $mailer;
/**
* Mailer constructor.
*
* Initializes the PHPMailer instance and configures it based on environment variables.
*
* @throws Exception If PHPMailer configuration fails.
*/
public function __construct()
{
try {
$this->mailer = new PHPMailer(true);
$this->configure();
} catch (Exception $e) {
Logger::error('Failed to initialize Mailer: ' . $e->getMessage());
ErrorHandler::exception($e);
throw $e;
}
}
/**
* Configures the PHPMailer instance.
*
* Reads email configuration from environment variables such as MAIL_HOST, MAIL_USER, MAIL_PASSWORD, etc.
*
* @throws Exception If any configuration errors occur.
*/
protected function configure(): void
{
try {
$this->mailer->isSMTP();
$this->mailer->Host = $_ENV['MAIL_HOST'];
$this->mailer->SMTPAuth = true;
$this->mailer->Username = $_ENV['MAIL_USER'];
$this->mailer->Password = $_ENV['MAIL_PASSWORD'];
$this->mailer->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$this->mailer->Port = (int) $_ENV['MAIL_PORT'];
$this->mailer->setFrom($_ENV['MAIL_FROM_EMAIL'], $_ENV['MAIL_FROM_NAME']);
Logger::info('Mailer configured successfully.');
} catch (Exception $e) {
Logger::error('Mailer configuration failed: ' . $e->getMessage());
ErrorHandler::exception($e);
throw $e;
}
}
/**
* Sends an email.
*
* @param string $to The recipient's email address.
* @param string $subject The email subject.
* @param string $body The HTML content of the email.
* @param string $altBody The plain-text alternative content of the email (optional).
*
* @return bool True if the email was sent successfully, false otherwise.
*/
public function send(string $to, string $subject, string $body, string $altBody = ''): bool
{
try {
$this->mailer->clearAddresses();
$this->mailer->addAddress($to);
$this->mailer->Subject = $subject;
$this->mailer->Body = $body;
$this->mailer->AltBody = $altBody;
$this->mailer->send();
Logger::info("Email sent successfully to $to with subject: $subject.");
return true;
} catch (Exception $e) {
Logger::error("Failed to send email to $to: " . $e->getMessage());
ErrorHandler::exception($e);
return false;
}
}
}

View File

@ -1,91 +0,0 @@
<?php
namespace WizdomNetworks\WizeWeb\Utils;
use WizdomNetworks\WizeWeb\Utils\Logger;
use WizdomNetworks\WizeWeb\Utils\ErrorHandler;
/**
* Sanitizer Utility
*
* Provides methods for sanitizing various types of data, including strings, emails, URLs, and arrays.
* Logs sanitized data for debugging and traceability.
*/
class Sanitizer
{
/**
* Sanitizes a string by removing harmful characters.
*
* @param string $value The string to sanitize.
* @return string The sanitized string.
*/
public static function sanitizeString(string $value): string
{
try {
$sanitized = filter_var($value, FILTER_SANITIZE_STRING);
Logger::info("Sanitized string: Original: $value | Sanitized: $sanitized");
return $sanitized;
} catch (\Throwable $e) {
Logger::error("Failed to sanitize string: $value");
ErrorHandler::exception($e);
return '';
}
}
/**
* Sanitizes an email address.
*
* @param string $value The email address to sanitize.
* @return string The sanitized email address.
*/
public static function sanitizeEmail(string $value): string
{
try {
$sanitized = filter_var($value, FILTER_SANITIZE_EMAIL);
Logger::info("Sanitized email: Original: $value | Sanitized: $sanitized");
return $sanitized;
} catch (\Throwable $e) {
Logger::error("Failed to sanitize email: $value");
ErrorHandler::exception($e);
return '';
}
}
/**
* Sanitizes a URL.
*
* @param string $value The URL to sanitize.
* @return string The sanitized URL.
*/
public static function sanitizeURL(string $value): string
{
try {
$sanitized = filter_var($value, FILTER_SANITIZE_URL);
Logger::info("Sanitized URL: Original: $value | Sanitized: $sanitized");
return $sanitized;
} catch (\Throwable $e) {
Logger::error("Failed to sanitize URL: $value");
ErrorHandler::exception($e);
return '';
}
}
/**
* Sanitizes an array of strings.
*
* @param array $values The array of strings to sanitize.
* @return array The sanitized array.
*/
public static function sanitizeArray(array $values): array
{
try {
$sanitizedArray = filter_var_array($values, FILTER_SANITIZE_STRING);
Logger::info("Sanitized array: Original: " . json_encode($values) . " | Sanitized: " . json_encode($sanitizedArray));
return $sanitizedArray;
} catch (\Throwable $e) {
Logger::error("Failed to sanitize array: " . json_encode($values));
ErrorHandler::exception($e);
return [];
}
}
}

View File

@ -1,238 +0,0 @@
<?php
namespace WizdomNetworks\WizeWeb\Utils;
use WizdomNetworks\WizeWeb\Utils\Logger;
use WizdomNetworks\WizeWeb\Utils\ErrorHandler;
/**
* Validator Utility
*
* Provides methods for validating user input.
*/
class Validator
{
/**
* Check if a value is non-empty.
*
* @param string $value The value to check.
* @return bool True if the value is not empty, false otherwise.
*/
public static function isRequired(string $value): bool
{
try {
Logger::info("[DEBUG] Checking if value is required: $value");
$isValid = !empty(trim($value));
if (!$isValid) {
Logger::warning("[WARNING] Value is required but empty.");
}
return $isValid;
} catch (\Throwable $e) {
ErrorHandler::exception($e);
return false;
}
}
/**
* Validate an email address.
*
* @param string $email The email address to validate.
* @return bool True if the email is valid, false otherwise.
*/
public static function isEmail(string $email): bool
{
try {
Logger::info("[DEBUG] Validating email address: $email");
$isValid = filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
if (!$isValid) {
Logger::warning("[WARNING] Invalid email address: $email");
}
return $isValid;
} catch (\Throwable $e) {
ErrorHandler::exception($e);
return false;
}
}
/**
* Validate a URL.
*
* @param string $url The URL to validate.
* @return bool True if the URL is valid, false otherwise.
*/
public static function isURL(string $url): bool
{
try {
Logger::info("[DEBUG] Validating URL: $url");
$isValid = filter_var($url, FILTER_VALIDATE_URL) !== false;
if (!$isValid) {
Logger::warning("[WARNING] Invalid URL: $url");
}
return $isValid;
} catch (\Throwable $e) {
ErrorHandler::exception($e);
return false;
}
}
/**
* Check if a string matches a given regular expression.
*
* @param string $string The string to validate.
* @param string $pattern The regular expression to match.
* @return bool True if the string matches the pattern, false otherwise.
*/
public static function matchesRegex(string $string, string $pattern): bool
{
try {
Logger::info("[DEBUG] Validating string against regex: Pattern=$pattern");
$isValid = preg_match($pattern, $string) === 1;
if (!$isValid) {
Logger::warning("[WARNING] String does not match regex: $string");
}
return $isValid;
} catch (\Throwable $e) {
ErrorHandler::exception($e);
return false;
}
}
/**
* Check if a string has a minimum length.
*
* @param string $string The string to check.
* @param int $minLength The minimum length.
* @return bool True if the string meets the minimum length, false otherwise.
*/
public static function hasMinLength(string $string, int $minLength): bool
{
try {
Logger::info("[DEBUG] Checking if string has minimum length: $minLength");
$isValid = strlen(trim($string)) >= $minLength;
if (!$isValid) {
Logger::warning("[WARNING] String is shorter than minimum length: $string");
}
return $isValid;
} catch (\Throwable $e) {
ErrorHandler::exception($e);
return false;
}
}
/**
* Check if a string has a maximum length.
*
* @param string $string The string to check.
* @param int $maxLength The maximum length.
* @return bool True if the string meets the maximum length, false otherwise.
*/
public static function hasMaxLength(string $string, int $maxLength): bool
{
try {
Logger::info("[DEBUG] Checking if string has maximum length: $maxLength");
$isValid = strlen(trim($string)) <= $maxLength;
if (!$isValid) {
Logger::warning("[WARNING] String exceeds maximum length: $string");
}
return $isValid;
} catch (\Throwable $e) {
ErrorHandler::exception($e);
return false;
}
}
/**
* Validate a string length.
*
* @param string $input The string to validate.
* @param int $min Minimum length.
* @param int $max Maximum length.
* @return bool True if the string length is valid, false otherwise.
*/
public static function validateStringLength(string $input, int $min, int $max): bool
{
try {
Logger::info("[DEBUG] Validating string length: Input='$input', Min=$min, Max=$max");
$length = strlen($input);
$isValid = $length >= $min && $length <= $max;
if (!$isValid) {
Logger::warning("[WARNING] Invalid string length: $length (Expected between $min and $max)");
}
return $isValid;
} catch (\Throwable $e) {
ErrorHandler::exception($e);
return false;
}
}
/**
* Validate a boolean value.
*
* @param mixed $input The input to validate as a boolean.
* @return bool True if the input is a valid boolean, false otherwise.
*/
public static function validateBoolean($input): bool
{
try {
Logger::info("[DEBUG] Validating boolean input: $input");
$isValid = is_bool(filter_var($input, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE));
if (!$isValid) {
Logger::warning("[WARNING] Invalid boolean input: $input");
}
return $isValid;
} catch (\Throwable $e) {
ErrorHandler::exception($e);
return false;
}
}
/**
* Validate a date format.
*
* @param string $date The date string to validate.
* @param string $format The expected date format (e.g., 'Y-m-d').
* @return bool True if the date matches the format, false otherwise.
*/
public static function validateDate(string $date, string $format = 'Y-m-d'): bool
{
try {
Logger::info("[DEBUG] Validating date: $date with format: $format");
$dateTime = \DateTime::createFromFormat($format, $date);
$isValid = $dateTime && $dateTime->format($format) === $date;
if (!$isValid) {
Logger::warning("[WARNING] Invalid date: $date (Expected format: $format)");
}
return $isValid;
} catch (\Throwable $e) {
ErrorHandler::exception($e);
return false;
}
}
}

32
copy-email-utilities.sh Executable file
View File

@ -0,0 +1,32 @@
#!/bin/bash
# Set source and destination paths
SRC_UTILS="../dev.helpdeskplus.ca-main/app/Utilities"
DEST_UTILS="./app/Utils"
SRC_TEMPLATES="../dev.helpdeskplus.ca-main/resources/templates/emails"
DEST_TEMPLATES="./resources/templates/emails"
# Create destination folders if they don't exist
mkdir -p "$DEST_UTILS"
mkdir -p "$DEST_TEMPLATES"
echo "🔁 Copying utility files..."
# List of utility files to copy and update namespaces in
FILES=("EmailUtility.php" "TemplateUtility.php" "QueueUtility.php")
for FILE in "${FILES[@]}"; do
if [ -f "$SRC_UTILS/$FILE" ]; then
echo " 📁 $FILE -> $DEST_UTILS"
sed 's|App\\Utilities|WizdomNetworks\\WizeWeb\\Utilities|g' "$SRC_UTILS/$FILE" > "$DEST_UTILS/$FILE"
else
echo " ⚠️ $FILE not found in $SRC_UTILS"
fi
done
echo "📄 Copying email templates..."
cp -r "$SRC_TEMPLATES"/* "$DEST_TEMPLATES"/
echo "✅ Done. All utilities and templates copied."

Binary file not shown.

After

Width:  |  Height:  |  Size: 700 KiB

View File

@ -5,7 +5,7 @@ ini_set('display_startup_errors', 1);
error_reporting(E_ALL); error_reporting(E_ALL);
// File: public/index.php // File: public/index.php
// Version: v1.2 // Version: v1.3
// Purpose: Application entry point with Arsha one-pager routing // Purpose: Application entry point with Arsha one-pager routing
// Project: Wizdom Networks Website // Project: Wizdom Networks Website
@ -13,10 +13,10 @@ require_once __DIR__ . '/../vendor/autoload.php';
use Dotenv\Dotenv; use Dotenv\Dotenv;
use WizdomNetworks\WizeWeb\Core\Router; use WizdomNetworks\WizeWeb\Core\Router;
use WizdomNetworks\WizeWeb\Utils\Logger; use WizdomNetworks\WizeWeb\Utilities\Logger;
use WizdomNetworks\WizeWeb\Utils\ErrorHandler; use WizdomNetworks\WizeWeb\Utilities\ErrorHandler;
use WizdomNetworks\WizeWeb\Controllers\LandingController; use WizdomNetworks\WizeWeb\Controllers\LandingController;
use WizdomNetworks\WizeWeb\Controllers\ContactController; // <-- Missing use WizdomNetworks\WizeWeb\Controllers\ContactController; //
$dotenv = Dotenv::createImmutable(__DIR__ . '/../'); $dotenv = Dotenv::createImmutable(__DIR__ . '/../');
$dotenv->load(); $dotenv->load();
@ -30,8 +30,10 @@ $router->add('', LandingController::class, 'index');
$router->add('/', LandingController::class, 'index'); $router->add('/', LandingController::class, 'index');
$router->add('index.php', LandingController::class, 'index'); $router->add('index.php', LandingController::class, 'index');
// Contact form submission // Contact form
$router->add('/contact', ContactController::class, 'submit', 'POST'); $router->add('/contact', ContactController::class, 'index', 'GET'); // Show contact form
$router->add('/contact', ContactController::class, 'submit', 'POST'); // Handle submission
// Optional: fallback for /contact without leading slash (rare case) // Optional: fallback for /contact without leading slash (rare case)
// $router->add('contact', ContactController::class, 'submit', 'POST'); // $router->add('contact', ContactController::class, 'submit', 'POST');

View File

@ -0,0 +1,4 @@
<?php
// Placeholder for email template

View File

@ -0,0 +1,66 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Email from HelpDesk+</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
margin: 0;
padding: 0;
}
.email-container {
max-width: 600px;
margin: 20px auto;
background: #ffffff;
padding: 20px;
border-radius: 5px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.email-header {
text-align: center;
background-color: #0056b3;
color: white;
padding: 10px 0;
border-radius: 5px 5px 0 0;
}
.email-content {
padding: 20px;
font-size: 16px;
line-height: 1.6;
color: #333;
}
.email-footer {
text-align: center;
padding: 10px 0;
font-size: 14px;
color: #777;
}
</style>
</head>
<body>
<div class="email-container">
<div class="email-header">
<h1>HelpDesk+</h1>
</div>
<div class="email-content">
<p>Dear {{name}},</p>
<p>Thank you for reaching out to HelpDesk+. Weve received your message and will get back to you shortly. Heres what you submitted:</p>
<blockquote>
<p><strong>Message:</strong> {{message}}</p>
</blockquote>
<p>If you have any further questions or concerns, feel free to reply to this email.</p>
<p>Best regards,<br>The HelpDesk+ Team</p>
</div>
<div class="email-footer">
&copy; 2025 HelpDesk+. All rights reserved.
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,7 @@
<p>An error occurred during a contact form submission:</p>
<ul>
<li><strong>Error:</strong> {{error}}</li>
<li><strong>Form Data:</strong> <pre>{{formData}}</pre></li>
</ul>
<p>Stack Trace:</p>
<pre>{{trace}}</pre>

View File

@ -0,0 +1,66 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Email from HelpDesk+</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
margin: 0;
padding: 0;
}
.email-container {
max-width: 600px;
margin: 20px auto;
background: #ffffff;
padding: 20px;
border-radius: 5px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.email-header {
text-align: center;
background-color: #0056b3;
color: white;
padding: 10px 0;
border-radius: 5px 5px 0 0;
}
.email-content {
padding: 20px;
font-size: 16px;
line-height: 1.6;
color: #333;
}
.email-footer {
text-align: center;
padding: 10px 0;
font-size: 14px;
color: #777;
}
</style>
</head>
<body>
<div class="email-container">
<div class="email-header">
<h1>HelpDesk+</h1>
</div>
<div class="email-content">
<p>Dear {{name}},</p>
<p>Thank you for reaching out to HelpDesk+. Weve received your message and will get back to you shortly. Heres what you submitted:</p>
<blockquote>
<p><strong>Message:</strong> {{message}}</p>
</blockquote>
<p>If you have any further questions or concerns, feel free to reply to this email.</p>
<p>Best regards,<br>The HelpDesk+ Team</p>
</div>
<div class="email-footer">
&copy; 2025 HelpDesk+. All rights reserved.
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,17 @@
<!-- File: thankyou.php -->
<section id="contact" class="contact">
<div class="container" data-aos="fade-up">
<div class="section-title">
<h2>Thank You</h2>
<p>Weve received your message.</p>
</div>
<div class="row justify-content-center">
<div class="col-lg-8">
<div class="alert alert-success p-4 text-center">
<h4>Thanks <?= htmlspecialchars($name ?? ''); ?>, your message has been submitted!</h4>
<p>You will receive a confirmation email shortly. We aim to respond within 1 business day.</p>
</div>
</div>
</div>
</div>
</section>

View File

@ -2,7 +2,7 @@
require_once __DIR__ . '/../vendor/autoload.php'; require_once __DIR__ . '/../vendor/autoload.php';
use WizdomNetworks\WizeWeb\Utils\StructureGenerator; use WizdomNetworks\WizeWeb\Utilities\StructureGenerator;
if (PHP_SAPI === 'cli') { if (PHP_SAPI === 'cli') {
if ($argc !== 2) { if ($argc !== 2) {

View File

@ -2,7 +2,7 @@
require_once __DIR__ . '/../vendor/autoload.php'; require_once __DIR__ . '/../vendor/autoload.php';
use WizdomNetworks\WizeWeb\Utils\NamespaceUpdater; use WizdomNetworks\WizeWeb\Utilities\NamespaceUpdater;
if (PHP_SAPI === 'cli') { if (PHP_SAPI === 'cli') {
global $argc, $argv; global $argc, $argv;

View File

@ -8,8 +8,8 @@
*/ */
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use WizdomNetworks\WizeWeb\Utils\Logger; use WizdomNetworks\WizeWeb\Utilities\Logger;
use WizdomNetworks\WizeWeb\Utils\Validator; use WizdomNetworks\WizeWeb\Utilities\Validator;
class ComponentTests extends TestCase class ComponentTests extends TestCase
{ {