Add Minio integration for wash certificate storage
Introduced Minio support to store and manage wash certificates, replacing local file storage. This includes implementing traits, interfaces, and a Minio client integration, along with a CLI utility and relevant tests. Updated relevant modules and configurations.
This commit is contained in:
+23
-22
@@ -8,10 +8,11 @@ class router
|
||||
private string $method;
|
||||
private array $routes;
|
||||
private array $routeClasses; // Contains the classes that have the route_t trait
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->url = $_SERVER['REQUEST_URI'];
|
||||
$this->method = $_SERVER['REQUEST_METHOD'];
|
||||
$this->url = $_SERVER['REQUEST_URI'] ?? ($argv[1] ?? '/'); // Get the URL (Or the first argument if it's a CLI request)
|
||||
$this->method = $_SERVER['REQUEST_METHOD'] ?? ($argv[2] ?? 'GET'); // Get the method (Or the second argument if it's a CLI request)
|
||||
$this->routes = [];
|
||||
$this->routeClasses = [];
|
||||
}
|
||||
@@ -21,22 +22,11 @@ class router
|
||||
$this->routes[] = ['route' => $route, 'method' => $method, 'function' => $function];
|
||||
}
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
foreach ($this->routeClasses as $class) {
|
||||
$route = new $class();
|
||||
// Add the routes to the router
|
||||
$route->run();
|
||||
}
|
||||
|
||||
$this->routeRequest();
|
||||
}
|
||||
|
||||
public function auto_load_routes(string $path): void
|
||||
{
|
||||
global $response;
|
||||
$files = scandir($path);
|
||||
foreach ($files as $file) {
|
||||
foreach ( $files as $file ) {
|
||||
if ($file == '.' || $file == '..') {
|
||||
continue;
|
||||
}
|
||||
@@ -45,7 +35,7 @@ class router
|
||||
|
||||
// Get all the classes in the files with the route_t trait
|
||||
$classes = get_declared_classes();
|
||||
foreach ($classes as $class) {
|
||||
foreach ( $classes as $class ) {
|
||||
if (in_array('traits\route_t', class_uses($class))) {
|
||||
$this->routeClasses[] = $class;
|
||||
}
|
||||
@@ -59,21 +49,22 @@ class router
|
||||
}
|
||||
}
|
||||
|
||||
public function ERROR_HANDLER($callback): void
|
||||
public function run(): void
|
||||
{
|
||||
try {
|
||||
$callback();
|
||||
} catch (\Exception $e) {
|
||||
global $response;
|
||||
$response->internal_server_error($e->getMessage());
|
||||
foreach ( $this->routeClasses as $class ) {
|
||||
$route = new $class();
|
||||
// Add the routes to the router
|
||||
$route->run();
|
||||
}
|
||||
|
||||
$this->routeRequest();
|
||||
}
|
||||
|
||||
private function routeRequest(): void
|
||||
{
|
||||
global $response;
|
||||
$matching_route_found = false;
|
||||
foreach ($this->routes as $route) {
|
||||
foreach ( $this->routes as $route ) {
|
||||
if ($this->doesRouteMatchCurrent($route['route']) && $route['method'] == $this->method) {
|
||||
$route['function']();
|
||||
$matching_route_found = true;
|
||||
@@ -105,4 +96,14 @@ class router
|
||||
// None of the matches were found
|
||||
return false;
|
||||
}
|
||||
|
||||
public function ERROR_HANDLER($callback): void
|
||||
{
|
||||
try {
|
||||
$callback();
|
||||
} catch (\Exception $e) {
|
||||
global $response;
|
||||
$response->internal_server_error($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace classes;
|
||||
|
||||
use interfaces\minio_wash_certificates_i;
|
||||
use traits\minio_t;
|
||||
|
||||
class wash_certificate_store implements minio_wash_certificates_i
|
||||
{
|
||||
use minio_t;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
self::setBucket('truckwashdev'); // Change this to washcertificates when in production
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function washCertificateExists(string $certificate_id): bool
|
||||
{
|
||||
// Check if the file exists
|
||||
$objects = self::getS3Client()->listObjects([
|
||||
'Bucket' => self::getBucket(),
|
||||
'Prefix' => $certificate_id
|
||||
]);
|
||||
return count($objects['Contents'] ?? []) > 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
// This script only runs when the program is called from the command line. It is used to run the CLI script.
|
||||
if (php_sapi_name() !== 'cli') {
|
||||
exit;
|
||||
}
|
||||
$args = $argv;
|
||||
echo "This is the CLI script";
|
||||
echo "\n";
|
||||
echo "Arguments: ";
|
||||
print_r($args);
|
||||
|
||||
// If the first argument is 'run', switch to the second argument
|
||||
if ($args[1] === 'run') {
|
||||
switch ($args[2]) {
|
||||
case 'minio-test':
|
||||
echo "Running the minio test script";
|
||||
require_once 'tests/minio/minioTest.php';
|
||||
break;
|
||||
default:
|
||||
echo "Invalid script name";
|
||||
break;
|
||||
}
|
||||
}
|
||||
+6
-1
@@ -1,4 +1,4 @@
|
||||
<?php global $CONFIG_DB, $DEBUG, $ENCRYPTION_KEY, $CORS, $ECONOMIC_API, $WORDPRESS_STATIC_TOKEN, $USE_PROD_ECONOMIC_IN_DEBUG;
|
||||
<?php global $CONFIG_DB, $DEBUG, $ENCRYPTION_KEY, $CORS, $ECONOMIC_API, $WORDPRESS_STATIC_TOKEN, $USE_PROD_ECONOMIC_IN_DEBUG, $EMAIL_WASH_CERTIFICATE_TOKEN, $MINIO;
|
||||
$CONFIG_DB = [
|
||||
'host' => '', // IP address of the database server e.g. 127.0.0.1
|
||||
'user' => '', // Username of the database server e.g. root
|
||||
@@ -23,3 +23,8 @@ if ($DEBUG && !$USE_PROD_ECONOMIC_IN_DEBUG) {
|
||||
}
|
||||
$WORDPRESS_STATIC_TOKEN = ''; // Static token used to authenticate the WordPress plugin
|
||||
$EMAIL_WASH_CERTIFICATE_TOKEN = ''; // Token used to authenticate the wash certificate generator
|
||||
$MINIO = [
|
||||
'endpoint' => '', // Minio endpoint e.g. http://0.0.0.0:9000
|
||||
'access_key' => '', // Minio access
|
||||
'secret_key' => '' // Minio secret key
|
||||
];
|
||||
@@ -19,11 +19,11 @@ header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");
|
||||
/** Autoload */
|
||||
require_once 'vendor/autoload.php';
|
||||
/** Load all Interfaces */
|
||||
foreach (glob(WD . '/interfaces/*.php') as $interface) {
|
||||
foreach ( glob(WD . '/interfaces/*.php') as $interface ) {
|
||||
require_once $interface;
|
||||
}
|
||||
/** Load all Traits */
|
||||
foreach (glob(WD . '/traits/*.php') as $trait) {
|
||||
foreach ( glob(WD . '/traits/*.php') as $trait ) {
|
||||
require_once $trait;
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ require_once 'classes/db.php';
|
||||
require_once 'classes/response.php';
|
||||
require_once 'classes/request.php';
|
||||
require_once 'classes/ratelimit.php';
|
||||
require_once 'classes/wash_certificate_store.php';
|
||||
|
||||
/**
|
||||
* Modules
|
||||
@@ -47,9 +48,9 @@ require_once 'modules/economic/customers/economic_customer_mo.php';
|
||||
require_once 'modules/economic/invoices/draft/economicInvoicesDrafts.php';
|
||||
require_once 'modules/economic/invoices/draft/economic_invoice_draft_mo.php';
|
||||
|
||||
use classes\response;
|
||||
use classes\request;
|
||||
use classes\db;
|
||||
use classes\request;
|
||||
use classes\response;
|
||||
use classes\router;
|
||||
|
||||
// Start the session
|
||||
@@ -65,17 +66,17 @@ try {
|
||||
$response->error($e->getMessage(), 500);
|
||||
}
|
||||
// Load all the traits
|
||||
foreach (glob(WD . '/traits/*.php') as $trait) {
|
||||
foreach ( glob(WD . '/traits/*.php') as $trait ) {
|
||||
require_once $trait;
|
||||
}
|
||||
|
||||
// Load all the routes
|
||||
foreach (glob(WD . '/routes/*.php') as $route) {
|
||||
foreach ( glob(WD . '/routes/*.php') as $route ) {
|
||||
require_once $route;
|
||||
}
|
||||
|
||||
/** Load all Objects */
|
||||
foreach (glob(WD . '/objects/*.php') as $object) {
|
||||
foreach ( glob(WD . '/objects/*.php') as $object ) {
|
||||
try {
|
||||
require_once $object;
|
||||
} catch (Exception $e) {
|
||||
@@ -83,6 +84,12 @@ foreach (glob(WD . '/objects/*.php') as $object) {
|
||||
}
|
||||
}
|
||||
|
||||
// If the program was called from the command line, run the cli script
|
||||
if (php_sapi_name() === 'cli') {
|
||||
require_once 'cli.php';
|
||||
exit;
|
||||
}
|
||||
|
||||
// Autoload all the routes
|
||||
$router->auto_load_routes(WD . '/routes');
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace interfaces;
|
||||
|
||||
interface minio_wash_certificates_i
|
||||
{
|
||||
/**
|
||||
* Check if a wash certificate exists
|
||||
* @param string $certificate_id
|
||||
* @return bool
|
||||
*/
|
||||
public function washCertificateExists(string $certificate_id): bool;
|
||||
}
|
||||
@@ -3,7 +3,15 @@
|
||||
* This is the generator for the wash certificates (Used by the WordPress plugin)
|
||||
* The reason behind this being outside the WordPress plugin is that the PHPExcel library is not compatible with the WordPress plugin, and it is easier to maintain the generator here.
|
||||
*/
|
||||
|
||||
use classes\wash_certificate_store;
|
||||
|
||||
require_once '../../config.php';
|
||||
require_once '../../vendor/autoload.php';
|
||||
/** Load the relevant classes */
|
||||
require_once '../../interfaces/minio_wash_certificates_i.php';
|
||||
require_once '../../traits/minio_t.php';
|
||||
require_once '../../classes/wash_certificate_store.php';
|
||||
global $WORDPRESS_STATIC_TOKEN;
|
||||
// Validate the token was loaded from the config file
|
||||
if (!isset($WORDPRESS_STATIC_TOKEN) || $WORDPRESS_STATIC_TOKEN === '') {
|
||||
@@ -60,13 +68,11 @@ if (!isset($_GET['sealOrPlumber']) || !isset($_GET['performedBy']) || !isset($_G
|
||||
exit;
|
||||
}
|
||||
|
||||
// Check if the certificate already exists in the folder
|
||||
if (file_exists("output/certificates/wash_certificate_" . $_GET['bookingId'] . ".pdf")) {
|
||||
// Return the generated certificate path
|
||||
$generatedCertificatePath = "output/certificates/wash_certificate_" . $_GET['bookingId'] . ".pdf";
|
||||
|
||||
// Check if the certificate already exists in the bucket
|
||||
$wash_certificate_store = new wash_certificate_store();
|
||||
if ($wash_certificate_store->washCertificateExists("wash_certificate_" . $_GET['bookingId'] . ".pdf")) {
|
||||
// Return the certificate url
|
||||
echo $generatedCertificatePath;
|
||||
echo $wash_certificate_store->getPresignedUrl("wash_certificate_" . $_GET['bookingId'] . ".pdf");
|
||||
// Exit the script
|
||||
exit;
|
||||
}
|
||||
@@ -74,12 +80,21 @@ if (file_exists("output/certificates/wash_certificate_" . $_GET['bookingId'] . "
|
||||
// Usage example
|
||||
$template = "templates/template2024julv3.xlsx";
|
||||
$generator = new WashCertificateGenerator($template, $_GET['department']);
|
||||
$generator->generateCertificate("output/certificates/wash_certificate_" . $_GET['bookingId'] . ".pdf", $_GET['sealOrPlumber'], $_GET['regNumber'], $_GET['regNumberTrailer'], $_GET['performedBy']);
|
||||
$generator->generateCertificate(dirname(__FILE__) . "/output/certificates/wash_certificate_" . $_GET['bookingId'] . ".pdf", $_GET['sealOrPlumber'], $_GET['regNumber'], $_GET['regNumberTrailer'], $_GET['performedBy']);
|
||||
|
||||
// Determine the generated certificate name
|
||||
$generatedCertificateName = "wash_certificate_" . $_GET['bookingId'] . ".pdf";
|
||||
|
||||
// Return the generated certificate path
|
||||
$generatedCertificatePath = "output/certificates/wash_certificate_" . $_GET['bookingId'] . ".pdf";
|
||||
|
||||
// Return the generated certificate path
|
||||
echo $generatedCertificatePath;
|
||||
// Upload the certificate to the bucket
|
||||
$wash_certificate_store->uploadFile($generatedCertificateName, dirname(__FILE__) . '/' . $generatedCertificatePath);
|
||||
|
||||
// Delete the local copy of the certificate
|
||||
unlink(dirname(__FILE__) . '/' . $generatedCertificatePath);
|
||||
|
||||
// Return the generated certificate object URL
|
||||
$wash_certificate_store->getObjectUrl($generatedCertificateName);
|
||||
// Exit the script
|
||||
exit;
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
// prevent direct access
|
||||
if (!defined('WD')) {
|
||||
exit;
|
||||
}
|
||||
global $MINIO;
|
||||
|
||||
use classes\wash_certificate_store;
|
||||
|
||||
function warn($message): void
|
||||
{
|
||||
echo "\n\033[33m$message\033[0m\n";
|
||||
}
|
||||
|
||||
// Check if the MINIO array is set
|
||||
if (!isset($MINIO)) {
|
||||
throw new Exception('MINIO array is not set in config.php');
|
||||
}
|
||||
// Check if the MINIO array has the required keys
|
||||
if (!isset($MINIO['endpoint']) || !isset($MINIO['access_key']) || !isset($MINIO['secret_key'])) {
|
||||
throw new Exception('MINIO array is missing required keys');
|
||||
}
|
||||
// Create a new S3Client object
|
||||
$wash_certificate_store = new wash_certificate_store();
|
||||
|
||||
// List all wash certificates
|
||||
$wash_certificates = $wash_certificate_store->listFiles();
|
||||
// Check if the request was successful
|
||||
if (count($wash_certificates) > 0) {
|
||||
// Return the count of wash certificates
|
||||
echo "\nWash certificates found: " . count($wash_certificates);
|
||||
} else {
|
||||
// Show warning message
|
||||
warn('No wash certificates found');
|
||||
}
|
||||
|
||||
// Create a new wash certificate
|
||||
$wash_certificate = $wash_certificate_store->createObject('test.txt', 'Hello, World!');
|
||||
// Check if the request was successful
|
||||
if ($wash_certificate) {
|
||||
// Show success message
|
||||
echo "\nWash certificate created successfully";
|
||||
} else {
|
||||
// Show error message
|
||||
warn('Failed to create wash certificate');
|
||||
}
|
||||
|
||||
// Check if a wash certificate exists
|
||||
$wash_certificate_exists = $wash_certificate_store->washCertificateExists('test.txt');
|
||||
// Check if the request was successful
|
||||
if ($wash_certificate_exists) {
|
||||
// Show success message
|
||||
echo "\nWash certificate exists";
|
||||
} else {
|
||||
// Show warning message
|
||||
warn('Wash certificate does not exist');
|
||||
}
|
||||
|
||||
// Create a download link for the wash certificate
|
||||
$wash_certificate_download_link = $wash_certificate_store->getPresignedUrl('test.txt');
|
||||
// Check if the request was successful
|
||||
if ($wash_certificate_download_link) {
|
||||
// Show the download link
|
||||
echo "\nDownload link: $wash_certificate_download_link";
|
||||
} else {
|
||||
// Show error message
|
||||
warn('Failed to create download link');
|
||||
}
|
||||
|
||||
// Upload a wash certificate from a file
|
||||
$wash_certificate_upload = $wash_certificate_store->uploadFile('test.txt', 'tests/minio/testUpload.txt');
|
||||
// Check if the request was successful
|
||||
if ($wash_certificate_upload) {
|
||||
// Show success message
|
||||
echo "\nWash certificate uploaded successfully from file";
|
||||
} else {
|
||||
// Show error message
|
||||
warn('Failed to upload wash certificate from file');
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
This is a test file.
|
||||
@@ -0,0 +1,173 @@
|
||||
<?php
|
||||
|
||||
namespace traits;
|
||||
|
||||
use Aws\S3\S3Client;
|
||||
use classes\wash_certificate_store;
|
||||
|
||||
trait minio_t
|
||||
{
|
||||
/**
|
||||
* The bucket to store the files in
|
||||
* @return string
|
||||
*/
|
||||
private string $bucket;
|
||||
/**
|
||||
* The S3 client to interact with the Minio server
|
||||
* @return S3Client
|
||||
*/
|
||||
private s3Client $s3Client;
|
||||
|
||||
/**
|
||||
* List all the files in the bucket
|
||||
* @return array
|
||||
*/
|
||||
public function listFiles(): array
|
||||
{
|
||||
$objects = self::getS3Client()->listObjects([
|
||||
'Bucket' => self::getBucket()
|
||||
]);
|
||||
// If there are no files, return an empty array
|
||||
if (!isset($objects['Contents'])) {
|
||||
return [];
|
||||
}
|
||||
return $objects['Contents'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the S3 client to interact with the Minio server
|
||||
* @return S3Client
|
||||
*/
|
||||
public function getS3Client(): S3Client
|
||||
{
|
||||
// If the S3 client is not set, create a new one
|
||||
if (!isset($this->s3Client)) {
|
||||
$this->connect();
|
||||
}
|
||||
return $this->s3Client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to the Minio server
|
||||
*/
|
||||
private function connect(): self
|
||||
{
|
||||
$this->s3Client = new S3Client([
|
||||
'version' => 'latest',
|
||||
'region' => 'us-east-1',
|
||||
'endpoint' => $this->getEndpoint(),
|
||||
'use_path_style_endpoint' => true,
|
||||
'credentials' => [
|
||||
'key' => $this->getAccessKey(),
|
||||
'secret' => $this->getSecretKey(),
|
||||
],
|
||||
]);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the endpoint of the Minio server
|
||||
* @return string
|
||||
*/
|
||||
public function getEndpoint(): string
|
||||
{
|
||||
global $MINIO;
|
||||
return $MINIO['endpoint'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the access key of the Minio server
|
||||
* @return string
|
||||
*/
|
||||
public function getAccessKey(): string
|
||||
{
|
||||
global $MINIO;
|
||||
return $MINIO['access_key'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the secret key of the Minio server
|
||||
* @return string
|
||||
*/
|
||||
public function getSecretKey(): string
|
||||
{
|
||||
global $MINIO;
|
||||
return $MINIO['secret_key'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the bucket to store the files in
|
||||
* @return string
|
||||
*/
|
||||
public function getBucket(): string
|
||||
{
|
||||
return $this->bucket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the bucket to store the files in
|
||||
* @param string $bucket
|
||||
* @return wash_certificate_store|minio_t
|
||||
*/
|
||||
public function setBucket(string $bucket): self
|
||||
{
|
||||
$this->bucket = $bucket;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new object in the bucket
|
||||
* @param string $key The key of the object (file)
|
||||
* @param string $body The content of the object (file)
|
||||
* @return bool
|
||||
*/
|
||||
public function createObject(string $key, string $body): bool
|
||||
{
|
||||
$result = self::getS3Client()->putObject([
|
||||
'Bucket' => self::getBucket(),
|
||||
'Key' => $key,
|
||||
'Body' => $body
|
||||
]);
|
||||
return $result['@metadata']['statusCode'] == 200;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URL of the object in the bucket
|
||||
* @param string $key The key of the object (file)
|
||||
* @return string
|
||||
*/
|
||||
public function getObjectUrl(string $key): string
|
||||
{
|
||||
return self::getS3Client()->getObjectUrl(self::getBucket(), $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a presigned URL for the object in the bucket (valid for 20 minutes)
|
||||
* @param string $key The key of the object (file)
|
||||
* @return string
|
||||
*/
|
||||
public function getPresignedUrl(string $key): string
|
||||
{
|
||||
$command = self::getS3Client()->getCommand('GetObject', [
|
||||
'Bucket' => self::getBucket(),
|
||||
'Key' => $key
|
||||
]);
|
||||
return (string)self::getS3Client()->createPresignedRequest($command, '+20 minutes')->getUri();
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload a file to the bucket
|
||||
* @param string $key The key of the object (file)
|
||||
* @param string $file The path to the file to upload
|
||||
* @return bool
|
||||
*/
|
||||
public function uploadFile(string $key, string $file): bool
|
||||
{
|
||||
$result = self::getS3Client()->putObject([
|
||||
'Bucket' => self::getBucket(),
|
||||
'Key' => $key,
|
||||
'SourceFile' => $file
|
||||
]);
|
||||
return $result['@metadata']['statusCode'] == 200;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user