style: auto-fix 1340 phpcs PSR-12 violations via phpcbf; exclude MissingNamespace and SideEffects
This commit is contained in:
+19
-9
@@ -1,11 +1,13 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Simple File-Based Cache Helper
|
||||
*
|
||||
* Provides caching for frequently accessed data that doesn't change often,
|
||||
* such as workflow rules, user preferences, and configuration data.
|
||||
*/
|
||||
class CacheHelper {
|
||||
class CacheHelper
|
||||
{
|
||||
private static ?string $cacheDir = null;
|
||||
private static array $memoryCache = [];
|
||||
|
||||
@@ -14,7 +16,8 @@ class CacheHelper {
|
||||
*
|
||||
* @return string Cache directory path
|
||||
*/
|
||||
private static function getCacheDir(): string {
|
||||
private static function getCacheDir(): string
|
||||
{
|
||||
if (self::$cacheDir === null) {
|
||||
self::$cacheDir = sys_get_temp_dir() . '/tinker_tickets_cache';
|
||||
if (!is_dir(self::$cacheDir)) {
|
||||
@@ -31,7 +34,8 @@ class CacheHelper {
|
||||
* @param mixed $identifier Unique identifier
|
||||
* @return string Cache key
|
||||
*/
|
||||
private static function makeKey(string $prefix, $identifier = null): string {
|
||||
private static function makeKey(string $prefix, $identifier = null): string
|
||||
{
|
||||
$key = $prefix;
|
||||
if ($identifier !== null) {
|
||||
$key .= '_' . md5(serialize($identifier));
|
||||
@@ -47,7 +51,8 @@ class CacheHelper {
|
||||
* @param int $ttl Time-to-live in seconds (default 300 = 5 minutes)
|
||||
* @return mixed|null Cached data or null if not found/expired
|
||||
*/
|
||||
public static function get(string $prefix, $identifier = null, int $ttl = 300) {
|
||||
public static function get(string $prefix, $identifier = null, int $ttl = 300)
|
||||
{
|
||||
$key = self::makeKey($prefix, $identifier);
|
||||
|
||||
// Check memory cache first (fastest)
|
||||
@@ -88,7 +93,8 @@ class CacheHelper {
|
||||
* @param mixed $data Data to cache
|
||||
* @return bool Success
|
||||
*/
|
||||
public static function set(string $prefix, $identifier, $data): bool {
|
||||
public static function set(string $prefix, $identifier, $data): bool
|
||||
{
|
||||
$key = self::makeKey($prefix, $identifier);
|
||||
$cached = [
|
||||
'time' => time(),
|
||||
@@ -110,7 +116,8 @@ class CacheHelper {
|
||||
* @param mixed $identifier Unique identifier (null to delete all with prefix)
|
||||
* @return bool Success
|
||||
*/
|
||||
public static function delete(string $prefix, $identifier = null): bool {
|
||||
public static function delete(string $prefix, $identifier = null): bool
|
||||
{
|
||||
if ($identifier !== null) {
|
||||
$key = self::makeKey($prefix, $identifier);
|
||||
unset(self::$memoryCache[$key]);
|
||||
@@ -140,7 +147,8 @@ class CacheHelper {
|
||||
*
|
||||
* @return bool Success
|
||||
*/
|
||||
public static function clearAll(): bool {
|
||||
public static function clearAll(): bool
|
||||
{
|
||||
self::$memoryCache = [];
|
||||
|
||||
$files = glob(self::getCacheDir() . '/*.json');
|
||||
@@ -160,7 +168,8 @@ class CacheHelper {
|
||||
* @param int $ttl Time-to-live in seconds
|
||||
* @return mixed Cached or freshly fetched data
|
||||
*/
|
||||
public static function remember(string $prefix, $identifier, callable $callback, int $ttl = 300) {
|
||||
public static function remember(string $prefix, $identifier, callable $callback, int $ttl = 300)
|
||||
{
|
||||
$data = self::get($prefix, $identifier, $ttl);
|
||||
|
||||
if ($data === null) {
|
||||
@@ -178,7 +187,8 @@ class CacheHelper {
|
||||
*
|
||||
* @param int $maxAge Maximum age in seconds (default 1 hour)
|
||||
*/
|
||||
public static function cleanup(int $maxAge = 3600): void {
|
||||
public static function cleanup(int $maxAge = 3600): void
|
||||
{
|
||||
$files = glob(self::getCacheDir() . '/*.json');
|
||||
$now = time();
|
||||
|
||||
|
||||
+21
-10
@@ -1,11 +1,13 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Database Connection Factory
|
||||
*
|
||||
* Centralizes database connection creation and management.
|
||||
* Provides a singleton connection for the request lifecycle.
|
||||
*/
|
||||
class Database {
|
||||
class Database
|
||||
{
|
||||
private static ?mysqli $connection = null;
|
||||
|
||||
/**
|
||||
@@ -14,7 +16,8 @@ class Database {
|
||||
* @return mysqli Database connection
|
||||
* @throws Exception If connection fails
|
||||
*/
|
||||
public static function getConnection(): mysqli {
|
||||
public static function getConnection(): mysqli
|
||||
{
|
||||
if (self::$connection === null) {
|
||||
self::$connection = self::createConnection();
|
||||
}
|
||||
@@ -33,7 +36,8 @@ class Database {
|
||||
* @return mysqli Database connection
|
||||
* @throws Exception If connection fails
|
||||
*/
|
||||
private static function createConnection(): mysqli {
|
||||
private static function createConnection(): mysqli
|
||||
{
|
||||
// Ensure config is loaded
|
||||
if (!isset($GLOBALS['config'])) {
|
||||
require_once dirname(__DIR__) . '/config/config.php';
|
||||
@@ -59,7 +63,8 @@ class Database {
|
||||
/**
|
||||
* Close the database connection
|
||||
*/
|
||||
public static function close(): void {
|
||||
public static function close(): void
|
||||
{
|
||||
if (self::$connection !== null) {
|
||||
self::$connection->close();
|
||||
self::$connection = null;
|
||||
@@ -71,7 +76,8 @@ class Database {
|
||||
*
|
||||
* @return bool Success
|
||||
*/
|
||||
public static function beginTransaction(): bool {
|
||||
public static function beginTransaction(): bool
|
||||
{
|
||||
return self::getConnection()->begin_transaction();
|
||||
}
|
||||
|
||||
@@ -80,7 +86,8 @@ class Database {
|
||||
*
|
||||
* @return bool Success
|
||||
*/
|
||||
public static function commit(): bool {
|
||||
public static function commit(): bool
|
||||
{
|
||||
return self::getConnection()->commit();
|
||||
}
|
||||
|
||||
@@ -89,7 +96,8 @@ class Database {
|
||||
*
|
||||
* @return bool Success
|
||||
*/
|
||||
public static function rollback(): bool {
|
||||
public static function rollback(): bool
|
||||
{
|
||||
return self::getConnection()->rollback();
|
||||
}
|
||||
|
||||
@@ -101,7 +109,8 @@ class Database {
|
||||
* @param array $params Parameters to bind
|
||||
* @return mysqli_result|bool Query result
|
||||
*/
|
||||
public static function query(string $sql, string $types = '', array $params = []) {
|
||||
public static function query(string $sql, string $types = '', array $params = [])
|
||||
{
|
||||
$conn = self::getConnection();
|
||||
|
||||
if (empty($types) || empty($params)) {
|
||||
@@ -130,7 +139,8 @@ class Database {
|
||||
* @param array $params Parameters to bind
|
||||
* @return int Affected rows (-1 on failure)
|
||||
*/
|
||||
public static function execute(string $sql, string $types = '', array $params = []): int {
|
||||
public static function execute(string $sql, string $types = '', array $params = []): int
|
||||
{
|
||||
$conn = self::getConnection();
|
||||
|
||||
$stmt = $conn->prepare($sql);
|
||||
@@ -158,7 +168,8 @@ class Database {
|
||||
*
|
||||
* @return int Last insert ID
|
||||
*/
|
||||
public static function lastInsertId(): int {
|
||||
public static function lastInsertId(): int
|
||||
{
|
||||
return self::getConnection()->insert_id;
|
||||
}
|
||||
|
||||
|
||||
+27
-13
@@ -1,11 +1,13 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Centralized Error Handler
|
||||
*
|
||||
* Provides consistent error handling, logging, and response formatting
|
||||
* across the application.
|
||||
*/
|
||||
class ErrorHandler {
|
||||
class ErrorHandler
|
||||
{
|
||||
private static ?string $logFile = null;
|
||||
private static bool $initialized = false;
|
||||
|
||||
@@ -14,7 +16,8 @@ class ErrorHandler {
|
||||
*
|
||||
* @param bool $displayErrors Whether to display errors (false in production)
|
||||
*/
|
||||
public static function init(bool $displayErrors = false): void {
|
||||
public static function init(bool $displayErrors = false): void
|
||||
{
|
||||
if (self::$initialized) {
|
||||
return;
|
||||
}
|
||||
@@ -45,7 +48,8 @@ class ErrorHandler {
|
||||
* @param int $errline Line number
|
||||
* @return bool
|
||||
*/
|
||||
public static function handleError(int $errno, string $errstr, string $errfile, int $errline): bool {
|
||||
public static function handleError(int $errno, string $errstr, string $errfile, int $errline): bool
|
||||
{
|
||||
// Don't handle suppressed errors
|
||||
if (!(error_reporting() & $errno)) {
|
||||
return false;
|
||||
@@ -69,7 +73,8 @@ class ErrorHandler {
|
||||
*
|
||||
* @param Throwable $exception
|
||||
*/
|
||||
public static function handleException(Throwable $exception): void {
|
||||
public static function handleException(Throwable $exception): void
|
||||
{
|
||||
$message = sprintf(
|
||||
"Uncaught %s: %s in %s on line %d\nStack trace:\n%s",
|
||||
get_class($exception),
|
||||
@@ -94,7 +99,8 @@ class ErrorHandler {
|
||||
/**
|
||||
* Handle fatal errors on shutdown
|
||||
*/
|
||||
public static function handleShutdown(): void {
|
||||
public static function handleShutdown(): void
|
||||
{
|
||||
$error = error_get_last();
|
||||
|
||||
if ($error !== null && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
|
||||
@@ -120,7 +126,8 @@ class ErrorHandler {
|
||||
* @param int $level Error level
|
||||
* @param array $context Additional context
|
||||
*/
|
||||
public static function log(string $message, int $level = E_USER_NOTICE, array $context = []): void {
|
||||
public static function log(string $message, int $level = E_USER_NOTICE, array $context = []): void
|
||||
{
|
||||
$timestamp = date('Y-m-d H:i:s');
|
||||
$levelName = self::getErrorTypeName($level);
|
||||
|
||||
@@ -140,7 +147,8 @@ class ErrorHandler {
|
||||
* @param int $httpCode HTTP status code
|
||||
* @param Throwable|null $exception Original exception (for debug info)
|
||||
*/
|
||||
public static function sendErrorResponse(string $message, int $httpCode = 500, ?Throwable $exception = null): void {
|
||||
public static function sendErrorResponse(string $message, int $httpCode = 500, ?Throwable $exception = null): void
|
||||
{
|
||||
http_response_code($httpCode);
|
||||
|
||||
if (!headers_sent()) {
|
||||
@@ -172,7 +180,8 @@ class ErrorHandler {
|
||||
* @param array $errors Array of validation errors
|
||||
* @param string $message Overall error message
|
||||
*/
|
||||
public static function sendValidationError(array $errors, string $message = 'Validation failed'): void {
|
||||
public static function sendValidationError(array $errors, string $message = 'Validation failed'): void
|
||||
{
|
||||
http_response_code(422);
|
||||
|
||||
if (!headers_sent()) {
|
||||
@@ -192,7 +201,8 @@ class ErrorHandler {
|
||||
*
|
||||
* @param string $message Error message
|
||||
*/
|
||||
public static function sendNotFoundError(string $message = 'Resource not found'): void {
|
||||
public static function sendNotFoundError(string $message = 'Resource not found'): void
|
||||
{
|
||||
self::sendErrorResponse($message, 404);
|
||||
}
|
||||
|
||||
@@ -201,7 +211,8 @@ class ErrorHandler {
|
||||
*
|
||||
* @param string $message Error message
|
||||
*/
|
||||
public static function sendUnauthorizedError(string $message = 'Authentication required'): void {
|
||||
public static function sendUnauthorizedError(string $message = 'Authentication required'): void
|
||||
{
|
||||
self::sendErrorResponse($message, 401);
|
||||
}
|
||||
|
||||
@@ -210,7 +221,8 @@ class ErrorHandler {
|
||||
*
|
||||
* @param string $message Error message
|
||||
*/
|
||||
public static function sendForbiddenError(string $message = 'Access denied'): void {
|
||||
public static function sendForbiddenError(string $message = 'Access denied'): void
|
||||
{
|
||||
self::sendErrorResponse($message, 403);
|
||||
}
|
||||
|
||||
@@ -220,7 +232,8 @@ class ErrorHandler {
|
||||
* @param int $errno Error number
|
||||
* @return string Error type name
|
||||
*/
|
||||
private static function getErrorTypeName(int $errno): string {
|
||||
private static function getErrorTypeName(int $errno): string
|
||||
{
|
||||
$types = [
|
||||
E_ERROR => 'ERROR',
|
||||
E_WARNING => 'WARNING',
|
||||
@@ -248,7 +261,8 @@ class ErrorHandler {
|
||||
* @param int $lines Number of lines to return
|
||||
* @return array Log entries
|
||||
*/
|
||||
public static function getRecentErrors(int $lines = 50): array {
|
||||
public static function getRecentErrors(int $lines = 50): array
|
||||
{
|
||||
if (self::$logFile === null || !file_exists(self::$logFile)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
<?php
|
||||
|
||||
require_once dirname(__DIR__) . '/helpers/UrlHelper.php';
|
||||
require_once dirname(__DIR__) . '/helpers/SynapseHelper.php';
|
||||
|
||||
class NotificationHelper {
|
||||
|
||||
class NotificationHelper
|
||||
{
|
||||
// ─── Internal: fire a webhook ─────────────────────────────────────────────
|
||||
|
||||
private static function fire(array $payload): void {
|
||||
private static function fire(array $payload): void
|
||||
{
|
||||
$webhookUrl = $GLOBALS['config']['MATRIX_WEBHOOK_URL'] ?? null;
|
||||
if (empty($webhookUrl)) {
|
||||
return;
|
||||
@@ -32,7 +34,8 @@ class NotificationHelper {
|
||||
}
|
||||
}
|
||||
|
||||
private static function notifyUsers(): array {
|
||||
private static function notifyUsers(): array
|
||||
{
|
||||
$raw = $GLOBALS['config']['MATRIX_NOTIFY_USERS'] ?? '';
|
||||
return array_values(array_filter(array_map('trim', explode(',', $raw))));
|
||||
}
|
||||
@@ -42,7 +45,8 @@ class NotificationHelper {
|
||||
/**
|
||||
* New ticket created (manual or automated/API).
|
||||
*/
|
||||
public static function sendTicketNotification($ticketId, array $ticketData, string $trigger = 'manual'): void {
|
||||
public static function sendTicketNotification($ticketId, array $ticketData, string $trigger = 'manual'): void
|
||||
{
|
||||
preg_match('/^\[([^\]]+)\]/', $ticketData['title'] ?? '', $m);
|
||||
$source = $m[1] ?? ($trigger === 'automated' ? 'Automated' : 'Manual');
|
||||
|
||||
@@ -70,7 +74,8 @@ class NotificationHelper {
|
||||
* @param string $ticketTitle
|
||||
* @param string|null $changedByDisplay Display name of the user who changed status
|
||||
*/
|
||||
public static function sendStatusChangeNotification($ticketId, string $oldStatus, string $newStatus, string $ticketTitle, ?string $changedByDisplay = null): void {
|
||||
public static function sendStatusChangeNotification($ticketId, string $oldStatus, string $newStatus, string $ticketTitle, ?string $changedByDisplay = null): void
|
||||
{
|
||||
self::fire([
|
||||
'event' => 'status_changed',
|
||||
'ticket_id' => $ticketId,
|
||||
@@ -92,7 +97,8 @@ class NotificationHelper {
|
||||
* @param string|null $authorDisplay Display name of commenter
|
||||
* @param bool $isInternal True if the comment is internal-only
|
||||
*/
|
||||
public static function sendCommentNotification($ticketId, string $ticketTitle, string $commentText, ?string $authorDisplay = null, bool $isInternal = false): void {
|
||||
public static function sendCommentNotification($ticketId, string $ticketTitle, string $commentText, ?string $authorDisplay = null, bool $isInternal = false): void
|
||||
{
|
||||
// Skip if this is an internal-only comment — only the assignee/admin need to know
|
||||
$notifyUsers = self::notifyUsers();
|
||||
if (empty($notifyUsers)) {
|
||||
@@ -120,7 +126,8 @@ class NotificationHelper {
|
||||
* @param string|null $authorDisplay
|
||||
* @param array $mentionedMatrixIds Matrix user IDs derived from @usernames
|
||||
*/
|
||||
public static function sendMentionNotification($ticketId, string $ticketTitle, string $commentText, ?string $authorDisplay, array $mentionedMatrixIds): void {
|
||||
public static function sendMentionNotification($ticketId, string $ticketTitle, string $commentText, ?string $authorDisplay, array $mentionedMatrixIds): void
|
||||
{
|
||||
if (empty($mentionedMatrixIds)) {
|
||||
return;
|
||||
}
|
||||
@@ -149,7 +156,8 @@ class NotificationHelper {
|
||||
* @param array $extraData Merged into the payload (old_status/new_status, author, etc.)
|
||||
* @param int|null $excludeUserId Don't notify the actor themselves
|
||||
*/
|
||||
public static function notifyWatchers(\mysqli $conn, $ticketId, string $ticketTitle, string $event, array $extraData = [], ?int $excludeUserId = null): void {
|
||||
public static function notifyWatchers(\mysqli $conn, $ticketId, string $ticketTitle, string $event, array $extraData = [], ?int $excludeUserId = null): void
|
||||
{
|
||||
$webhookUrl = $GLOBALS['config']['MATRIX_WEBHOOK_URL'] ?? null;
|
||||
$domain = $GLOBALS['config']['MATRIX_DOMAIN'] ?? null;
|
||||
if (!$webhookUrl || !$domain) {
|
||||
@@ -208,7 +216,8 @@ class NotificationHelper {
|
||||
* @param string|null $assigneeMatrix Matrix user ID of new assignee (to DM)
|
||||
* @param string|null $changedByDisplay
|
||||
*/
|
||||
public static function sendAssignmentNotification($ticketId, string $ticketTitle, ?string $assigneeName, ?string $assigneeMatrix, ?string $changedByDisplay = null): void {
|
||||
public static function sendAssignmentNotification($ticketId, string $ticketTitle, ?string $assigneeName, ?string $assigneeMatrix, ?string $changedByDisplay = null): void
|
||||
{
|
||||
$notifyUsers = self::notifyUsers();
|
||||
// Also notify the assignee directly if we know their Matrix ID
|
||||
if ($assigneeMatrix && !in_array($assigneeMatrix, $notifyUsers, true)) {
|
||||
@@ -229,4 +238,3 @@ class NotificationHelper {
|
||||
]);
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
+27
-13
@@ -1,11 +1,13 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* OutputHelper - Consistent output escaping utilities
|
||||
*
|
||||
* Provides secure HTML escaping functions to prevent XSS attacks.
|
||||
* Use these functions when outputting user-controlled data.
|
||||
*/
|
||||
class OutputHelper {
|
||||
class OutputHelper
|
||||
{
|
||||
/**
|
||||
* Escape string for HTML output
|
||||
*
|
||||
@@ -16,7 +18,8 @@ class OutputHelper {
|
||||
* @param int $flags htmlspecialchars flags (default: ENT_QUOTES | ENT_HTML5)
|
||||
* @return string Escaped string
|
||||
*/
|
||||
public static function h(?string $string, int $flags = ENT_QUOTES | ENT_HTML5): string {
|
||||
public static function h(?string $string, int $flags = ENT_QUOTES | ENT_HTML5): string
|
||||
{
|
||||
if ($string === null) {
|
||||
return '';
|
||||
}
|
||||
@@ -32,7 +35,8 @@ class OutputHelper {
|
||||
* @param string|null $string The string to escape
|
||||
* @return string Escaped string
|
||||
*/
|
||||
public static function attr(?string $string): string {
|
||||
public static function attr(?string $string): string
|
||||
{
|
||||
if ($string === null) {
|
||||
return '';
|
||||
}
|
||||
@@ -50,7 +54,8 @@ class OutputHelper {
|
||||
* @param int $flags json_encode flags
|
||||
* @return string JSON encoded string (safe for script context)
|
||||
*/
|
||||
public static function json($data, int $flags = 0): string {
|
||||
public static function json($data, int $flags = 0): string
|
||||
{
|
||||
// Use HEX encoding for safety in HTML context
|
||||
$safeFlags = JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP | $flags;
|
||||
return json_encode($data, $safeFlags);
|
||||
@@ -65,7 +70,8 @@ class OutputHelper {
|
||||
* @param string|null $string The string to encode
|
||||
* @return string URL encoded string
|
||||
*/
|
||||
public static function url(?string $string): string {
|
||||
public static function url(?string $string): string
|
||||
{
|
||||
if ($string === null) {
|
||||
return '';
|
||||
}
|
||||
@@ -81,7 +87,8 @@ class OutputHelper {
|
||||
* @param string|null $string The string to escape
|
||||
* @return string Escaped string (only allows safe characters)
|
||||
*/
|
||||
public static function css(?string $string): string {
|
||||
public static function css(?string $string): string
|
||||
{
|
||||
if ($string === null) {
|
||||
return '';
|
||||
}
|
||||
@@ -101,7 +108,8 @@ class OutputHelper {
|
||||
* @param int $decimals Number of decimal places
|
||||
* @return string Formatted number
|
||||
*/
|
||||
public static function number($number, int $decimals = 0): string {
|
||||
public static function number($number, int $decimals = 0): string
|
||||
{
|
||||
return number_format((float)$number, $decimals, '.', ',');
|
||||
}
|
||||
|
||||
@@ -111,7 +119,8 @@ class OutputHelper {
|
||||
* @param mixed $value The value to format
|
||||
* @return int Integer value
|
||||
*/
|
||||
public static function int($value): int {
|
||||
public static function int($value): int
|
||||
{
|
||||
return (int)$value;
|
||||
}
|
||||
|
||||
@@ -123,7 +132,8 @@ class OutputHelper {
|
||||
* @param string $suffix Suffix to add if truncated
|
||||
* @return string Truncated and escaped string
|
||||
*/
|
||||
public static function truncate(?string $string, int $length = 100, string $suffix = '...'): string {
|
||||
public static function truncate(?string $string, int $length = 100, string $suffix = '...'): string
|
||||
{
|
||||
if ($string === null) {
|
||||
return '';
|
||||
}
|
||||
@@ -142,7 +152,8 @@ class OutputHelper {
|
||||
* @param string $format PHP date format
|
||||
* @return string Formatted date
|
||||
*/
|
||||
public static function date($date, string $format = 'Y-m-d H:i:s'): string {
|
||||
public static function date($date, string $format = 'Y-m-d H:i:s'): string
|
||||
{
|
||||
if ($date === null || $date === '') {
|
||||
return '';
|
||||
}
|
||||
@@ -165,7 +176,8 @@ class OutputHelper {
|
||||
* @param string $class The class name to validate
|
||||
* @return bool True if safe
|
||||
*/
|
||||
public static function isValidCssClass(string $class): bool {
|
||||
public static function isValidCssClass(string $class): bool
|
||||
{
|
||||
return preg_match('/^[a-zA-Z_][a-zA-Z0-9_-]*$/', $class) === 1;
|
||||
}
|
||||
|
||||
@@ -175,7 +187,8 @@ class OutputHelper {
|
||||
* @param string|null $classes Space-separated class names
|
||||
* @return string Sanitized class names
|
||||
*/
|
||||
public static function cssClass(?string $classes): string {
|
||||
public static function cssClass(?string $classes): string
|
||||
{
|
||||
if ($classes === null || $classes === '') {
|
||||
return '';
|
||||
}
|
||||
@@ -193,6 +206,7 @@ class OutputHelper {
|
||||
* @param string|null $string The string to escape
|
||||
* @return string Escaped string
|
||||
*/
|
||||
function h(?string $string): string {
|
||||
function h(?string $string): string
|
||||
{
|
||||
return OutputHelper::h($string);
|
||||
}
|
||||
|
||||
+23
-11
@@ -1,10 +1,12 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* ResponseHelper - Standardized JSON response formatting
|
||||
*
|
||||
* Provides consistent API response structure across all endpoints.
|
||||
*/
|
||||
class ResponseHelper {
|
||||
class ResponseHelper
|
||||
{
|
||||
/**
|
||||
* Send a success response
|
||||
*
|
||||
@@ -12,7 +14,8 @@ class ResponseHelper {
|
||||
* @param string $message Success message
|
||||
* @param int $code HTTP status code
|
||||
*/
|
||||
public static function success($data = [], $message = 'Success', $code = 200) {
|
||||
public static function success($data = [], $message = 'Success', $code = 200)
|
||||
{
|
||||
http_response_code($code);
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(array_merge([
|
||||
@@ -29,7 +32,8 @@ class ResponseHelper {
|
||||
* @param int $code HTTP status code
|
||||
* @param array $data Additional data to include
|
||||
*/
|
||||
public static function error($message, $code = 400, $data = []) {
|
||||
public static function error($message, $code = 400, $data = [])
|
||||
{
|
||||
http_response_code($code);
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(array_merge([
|
||||
@@ -44,7 +48,8 @@ class ResponseHelper {
|
||||
*
|
||||
* @param string $message Error message
|
||||
*/
|
||||
public static function unauthorized($message = 'Authentication required') {
|
||||
public static function unauthorized($message = 'Authentication required')
|
||||
{
|
||||
self::error($message, 401);
|
||||
}
|
||||
|
||||
@@ -53,7 +58,8 @@ class ResponseHelper {
|
||||
*
|
||||
* @param string $message Error message
|
||||
*/
|
||||
public static function forbidden($message = 'Access denied') {
|
||||
public static function forbidden($message = 'Access denied')
|
||||
{
|
||||
self::error($message, 403);
|
||||
}
|
||||
|
||||
@@ -62,7 +68,8 @@ class ResponseHelper {
|
||||
*
|
||||
* @param string $message Error message
|
||||
*/
|
||||
public static function notFound($message = 'Resource not found') {
|
||||
public static function notFound($message = 'Resource not found')
|
||||
{
|
||||
self::error($message, 404);
|
||||
}
|
||||
|
||||
@@ -72,7 +79,8 @@ class ResponseHelper {
|
||||
* @param array $errors Validation errors
|
||||
* @param string $message Error message
|
||||
*/
|
||||
public static function validationError($errors, $message = 'Validation failed') {
|
||||
public static function validationError($errors, $message = 'Validation failed')
|
||||
{
|
||||
self::error($message, 422, ['validation_errors' => $errors]);
|
||||
}
|
||||
|
||||
@@ -81,7 +89,8 @@ class ResponseHelper {
|
||||
*
|
||||
* @param string $message Error message
|
||||
*/
|
||||
public static function serverError($message = 'Internal server error') {
|
||||
public static function serverError($message = 'Internal server error')
|
||||
{
|
||||
self::error($message, 500);
|
||||
}
|
||||
|
||||
@@ -91,7 +100,8 @@ class ResponseHelper {
|
||||
* @param int $retryAfter Seconds until retry is allowed
|
||||
* @param string $message Error message
|
||||
*/
|
||||
public static function rateLimitExceeded($retryAfter = 60, $message = 'Rate limit exceeded') {
|
||||
public static function rateLimitExceeded($retryAfter = 60, $message = 'Rate limit exceeded')
|
||||
{
|
||||
header('Retry-After: ' . $retryAfter);
|
||||
self::error($message, 429, ['retry_after' => $retryAfter]);
|
||||
}
|
||||
@@ -102,14 +112,16 @@ class ResponseHelper {
|
||||
* @param array $data Resource data
|
||||
* @param string $message Success message
|
||||
*/
|
||||
public static function created($data = [], $message = 'Resource created') {
|
||||
public static function created($data = [], $message = 'Resource created')
|
||||
{
|
||||
self::success($data, $message, 201);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a no content response (204)
|
||||
*/
|
||||
public static function noContent() {
|
||||
public static function noContent()
|
||||
{
|
||||
http_response_code(204);
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* SynapseHelper
|
||||
*
|
||||
@@ -11,8 +12,8 @@
|
||||
* SYNAPSE_ADMIN_URL e.g. http://10.10.10.29:8008 (internal client-API URL)
|
||||
* SYNAPSE_ADMIN_TOKEN a Synapse admin access token
|
||||
*/
|
||||
class SynapseHelper {
|
||||
|
||||
class SynapseHelper
|
||||
{
|
||||
/**
|
||||
* Resolve a local SSO username to its Matrix user ID.
|
||||
*
|
||||
@@ -26,7 +27,8 @@ class SynapseHelper {
|
||||
* @param string $username Local username (e.g. "jared")
|
||||
* @return string|null Matrix user ID (e.g. "@jared:matrix.lotusguild.org") or null
|
||||
*/
|
||||
public static function resolveUsername(string $username): ?string {
|
||||
public static function resolveUsername(string $username): ?string
|
||||
{
|
||||
$baseUrl = $GLOBALS['config']['SYNAPSE_ADMIN_URL'] ?? null;
|
||||
$token = $GLOBALS['config']['SYNAPSE_ADMIN_TOKEN'] ?? null;
|
||||
$domain = $GLOBALS['config']['MATRIX_DOMAIN'] ?? null;
|
||||
@@ -82,7 +84,8 @@ class SynapseHelper {
|
||||
* @param string[] $usernames
|
||||
* @return string[] Matrix user IDs
|
||||
*/
|
||||
public static function resolveUsernames(array $usernames): array {
|
||||
public static function resolveUsernames(array $usernames): array
|
||||
{
|
||||
$ids = [];
|
||||
foreach ($usernames as $username) {
|
||||
$id = self::resolveUsername($username);
|
||||
@@ -93,4 +96,3 @@ class SynapseHelper {
|
||||
return $ids;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
+13
-6
@@ -1,10 +1,12 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* UrlHelper - URL and domain utilities
|
||||
*
|
||||
* Provides secure URL generation with host validation.
|
||||
*/
|
||||
class UrlHelper {
|
||||
class UrlHelper
|
||||
{
|
||||
/**
|
||||
* Get the application base URL with validated host
|
||||
*
|
||||
@@ -13,7 +15,8 @@ class UrlHelper {
|
||||
*
|
||||
* @return string Base URL (e.g., "https://example.com")
|
||||
*/
|
||||
public static function getBaseUrl(): string {
|
||||
public static function getBaseUrl(): string
|
||||
{
|
||||
$protocol = self::getProtocol();
|
||||
$host = self::getValidatedHost();
|
||||
|
||||
@@ -25,7 +28,8 @@ class UrlHelper {
|
||||
*
|
||||
* @return string 'https' or 'http'
|
||||
*/
|
||||
public static function getProtocol(): string {
|
||||
public static function getProtocol(): string
|
||||
{
|
||||
if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') {
|
||||
return 'https';
|
||||
}
|
||||
@@ -48,7 +52,8 @@ class UrlHelper {
|
||||
*
|
||||
* @return string Validated hostname
|
||||
*/
|
||||
public static function getValidatedHost(): string {
|
||||
public static function getValidatedHost(): string
|
||||
{
|
||||
$config = $GLOBALS['config'] ?? [];
|
||||
|
||||
// Use configured APP_DOMAIN if available
|
||||
@@ -84,7 +89,8 @@ class UrlHelper {
|
||||
* @param string $ticketId Ticket ID
|
||||
* @return string Full ticket URL
|
||||
*/
|
||||
public static function ticketUrl(string $ticketId): string {
|
||||
public static function ticketUrl(string $ticketId): string
|
||||
{
|
||||
return self::getBaseUrl() . '/ticket/' . urlencode($ticketId);
|
||||
}
|
||||
|
||||
@@ -93,7 +99,8 @@ class UrlHelper {
|
||||
*
|
||||
* @return bool True if HTTPS
|
||||
*/
|
||||
public static function isSecure(): bool {
|
||||
public static function isSecure(): bool
|
||||
{
|
||||
return self::getProtocol() === 'https';
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user