Files
mivo/app/Models/Logo.php

146 lines
4.8 KiB
PHP

<?php
namespace App\Models;
use PDO;
use Exception;
class Logo {
protected $db;
protected $table = 'logos';
public function __construct() {
$this->db = \App\Core\Database::getInstance();
$this->initTable();
}
// Connect method removed as we use shared instance
private function initTable() {
$query = "CREATE TABLE IF NOT EXISTS {$this->table} (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
path TEXT NOT NULL,
type TEXT,
size INTEGER,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)";
$this->db->query($query);
}
public function generateId($length = 6) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}
public function getAll() {
$stmt = $this->db->query("SELECT * FROM {$this->table} ORDER BY created_at DESC");
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
public function getById($id) {
$stmt = $this->db->query("SELECT * FROM {$this->table} WHERE id = :id", ['id' => $id]);
return $stmt->fetch(PDO::FETCH_ASSOC);
}
public function add($file) {
// Security: Strict MIME Type Check
$finfo = new \finfo(FILEINFO_MIME_TYPE);
$mimeType = $finfo->file($file['tmp_name']);
$allowedMimes = [
'image/jpeg' => 'jpg',
'image/png' => 'png',
'image/gif' => 'gif',
'image/svg+xml' => 'svg',
'image/webp' => 'webp'
];
if (!array_key_exists($mimeType, $allowedMimes)) {
throw new Exception("Invalid file type: " . $mimeType);
}
// Use extension mapped from MIME type or sanitize original
// Better to trust MIME mapping for extensions to avoid double extension attacks
$extension = $allowedMimes[$mimeType];
// Generate Unique Short ID
do {
$id = $this->generateId();
$exists = $this->getById($id);
} while ($exists);
$uploadDir = ROOT . '/public/assets/img/logos/';
if (!file_exists($uploadDir)) {
mkdir($uploadDir, 0777, true);
}
$filename = $id . '.' . $extension;
$targetPath = $uploadDir . $filename;
if (move_uploaded_file($file['tmp_name'], $targetPath)) {
$this->db->query("INSERT INTO {$this->table} (id, name, path, type, size) VALUES (:id, :name, :path, :type, :size)", [
'id' => $id,
'name' => $file['name'],
'path' => '/assets/img/logos/' . $filename,
'type' => $extension,
'size' => $file['size']
]);
return $id;
}
return false;
}
public function syncFiles() {
// One-time sync: scan folder, if file not in DB, add it.
$logoDir = ROOT . '/public/assets/img/logos/';
if (!file_exists($logoDir)) return;
$files = glob($logoDir . '*.{jpg,jpeg,png,gif,svg}', GLOB_BRACE);
foreach ($files as $file) {
$filename = basename($file);
$extension = pathinfo($filename, PATHINFO_EXTENSION);
// Check if file is registered (maybe by path match)
$webPath = '/assets/img/logos/' . $filename;
$stmt = $this->db->query("SELECT COUNT(*) FROM {$this->table} WHERE path = :path", ['path' => $webPath]);
if ($stmt->fetchColumn() == 0) {
// Not in DB, register it.
// Ideally we'd rename it to a hashID, but since it's existing, let's generate an ID and map it.
do {
$id = $this->generateId();
$exists = $this->getById($id);
} while ($exists);
$this->db->query("INSERT INTO {$this->table} (id, name, path, type, size) VALUES (:id, :name, :path, :type, :size)", [
'id' => $id,
'name' => $filename,
'path' => $webPath,
'type' => $extension,
'size' => filesize($file)
]);
}
}
}
public function delete($id) {
$logo = $this->getById($id);
if ($logo) {
$filePath = ROOT . '/public' . $logo['path'];
if (file_exists($filePath)) {
unlink($filePath);
}
$this->db->query("DELETE FROM {$this->table} WHERE id = :id", ['id' => $id]);
return true;
}
return false;
}
}