Skip to content

Instantly share code, notes, and snippets.

@Bruno17
Created June 19, 2024 20:32
Show Gist options
  • Save Bruno17/1b733a4d38e270effe52bb9f414f4cc9 to your computer and use it in GitHub Desktop.
Save Bruno17/1b733a4d38e270effe52bb9f414f4cc9 to your computer and use it in GitHub Desktop.
Very simple Example for uppy uploader on MODX frontpage
<!DOCTYPE html>
<html lang="[[++cultureKey]]" >
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- @todo: fill with your company info or remove -->
<meta name="description" content="">
<meta name="author" content="">
<title>[[++site_name]] - [[*pagetitle]]</title>
<base href="[[!++site_url]]" />
<!-- Bootstrap 4.0.0-alpha.6 CSS via CDN -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
<link href="https://releases.transloadit.com/uppy/v3.23.0/uppy.min.css" rel="stylesheet">
</head>
<body>
<div id="files-drag-drop"></div>
<br><br>
<div id="images">
[[!migxLoopCollection?
&packageName=`rgm`
&classname=`rgmNewsImages`
&sortConfig=`[{"sortby":"pos"},{"sortby":"filepath"}]`
&where=`{"news_id":"[[!#Get.news_id]]"}`
&tpl=`tplNewsPreviewThumbnail`
&debug=`0`
]]
</div>
<script src="https://code.jquery.com/jquery-1.10.2.min.js"></script>
<script src="https://releases.transloadit.com/uppy/v3.20.0/uppy.min.js"></script>
<script src="https://releases.transloadit.com/uppy/locales/v3.3.1/de_DE.min.js"></script>
<script>
const endpoint = 'termine-and-news/neuigkeiten/bilder-hochladen/upload.html';
const uppy = new Uppy.Uppy({
debug: true,
locale: Uppy.locales.de_DE,
meta: {news_id:'[[!#Get.news_id]]'}
});
uppy.use(Uppy.Dashboard, { target: '#files-drag-drop' ,inline:true});
uppy.use(Uppy.ImageEditor, { target: Uppy.Dashboard });
uppy.use(Uppy.Compressor, {maxWidth:2000,maxHeight:2000});
uppy.use(Uppy.XHRUpload, {
endpoint: endpoint,
});
uppy.on('upload-success', (file, response) => {
$('#images').load('[[!~[[!*id]]]]?news_id=[[!#Get.news_id]] #images>*');
});
$("#images").on("click",".file-remove", function(e){
const image_id = $(this).data('id');
e.stopPropagation();
if (confirm('Bilddatei löschen?') == true) {
$.post( endpoint, { processaction: "delete", image_id: image_id } , function() {
$('#images').load('[[!~[[!*id]]]]?news_id=[[!#Get.news_id]] #images>*');
})
} else {
}
return false;
});
</script>
</body>
</html>
<div class="image">
<a class="ps-preview-tn" href="assets/galleries/9999[[+news_id]]/[[+filepath]]">
<img src="[[pthumb? &input=`assets/galleries/9999[[+news_id]]/[[+filepath]]` &options=`w=200&h=200&zc=1`]]" />
</a>
<button data-id="[[+id]]" class="file-remove uppy-u-reset uppy-Dashboard-Item-action uppy-Dashboard-Item-action--remove"
type="button" aria-label="Datei entfernen" title="Datei entfernen" style="position: absolute;width: 20px;right: -10px;top: -10px;">
<svg aria-hidden="true" focusable="false" class="uppy-c-icon" width="18" height="18" viewBox="0 0 18 18">
<path d="M9 0C4.034 0 0 4.034 0 9s4.034 9 9 9 9-4.034 9-9-4.034-9-9-9z"></path>
<path fill="#FFF" d="M13 12.222l-.778.778L9 9.778 5.778 13 5 12.222 8.222 9 5 5.778 5.778 5 9 8.222 12.222 5l.778.778L9.778 9z"></path>
</svg>
</button>
</div>
<?php
class UppyUploader {
/**
* Converts a given size with units to bytes.
* @param string $str
*/
public function toBytes($str){
$val = (float) trim($str);
$last = strtolower($str[strlen($str)-1]);
switch($last) {
case 'g': $val *= 1024;
case 'm': $val *= 1024;
case 'k': $val *= 1024;
}
return $val;
}
public function addPackage(){
global $modx;
$classname = 'rgmNewsImages';
$modx->runSnippet('migxLoopCollection',['packageName'=>'rgm','classname'=>$classname,'limit'=>'1']);
}
public function addItem($news_id,$file) {
global $modx;
$classname = 'rgmNewsImages';
$this->addPackage();
$item = ['news_id'=>$news_id,'filepath'=>$file];
if ($modx->getObject($classname,$item)){
return '';
}
$object = $modx->newObject($classname);
$object->fromArray($item);
$object->save();
}
public function deleteItem($image_id){
global $modx;
$classname = 'rgmNewsImages';
$this->addPackage();
if (!empty($image_id) && $object = $modx->getObject($classname,$image_id)){
$file_name = $object->get('filepath');
$news_id = $object->get('news_id');
$target_dir = $modx->getOption('assets_path') . 'galleries/9999' . $news_id;
$object->remove();
$target_file = $target_dir . DIRECTORY_SEPARATOR . $file_name;
unlink($target_file);
}
}
}
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
if ($modx->hasPermission('file_upload')){
} else {
header('Access-Control-Allow-Origin: *');
header('Content-type: application/json');
$data = ['message' => 'You have no permission to upload files.'];
http_response_code(400);
echo json_encode($data);
exit;
}
$uploader = new UppyUploader;
// Get the maximum upload file size
$max_size = $uploader->toBytes(ini_get('upload_max_filesize'));
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) {
header('Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT');
}
//Make sure you remove those you do not want to support
header('Access-Control-Allow-Origin: *');
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) {
header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
}
//Just exit with 200 OK with the above headers for OPTIONS method
exit(0);
}
$news_id = isset($_POST['news_id']) ? $_POST['news_id'] : 0;
$target_dir = $modx->getOption('assets_path') . 'galleries/9999' . $news_id;
if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_POST["processaction"])){
switch ($_POST["processaction"]) {
case 'delete':
if (!empty($_POST['image_id'])){
$uploader->deleteItem($_POST['image_id']);
}
return '';
break;
}
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_FILES["file"])) {
if (empty($news_id)){
header('Access-Control-Allow-Origin: *');
header('Content-type: application/json');
$data = ['message' => 'missing property: news_id'];
http_response_code(400);
echo json_encode($data);
exit;
}
$file_name = basename($_FILES['file']['name']);
$file_size = $_FILES['file']['size'];
$target_file = $target_dir . DIRECTORY_SEPARATOR . $file_name;
if ($target_dir) {
$permissions = octdec('0' . (int)($modx->getOption('new_folder_permissions', null, '755', true)));
if (!@mkdir($target_dir, $permissions, true)) {
$modx->log(MODX_LOG_LEVEL_ERROR, sprintf('[uppy_upload]: could not create directory %s).', $target_dir));
}
else{
chmod($target_dir, $permissions);
}
}
// Validate file size
if ($file_size > $max_size) {
header('Access-Control-Allow-Origin: *');
header('Content-type: application/json');
$data = ['message' => 'File size exceeds the maximum allowed size of ' . $max_size . '.'];
http_response_code(400);
echo json_encode($data);
exit;
}
// Sanitize file name to prevent directory traversal attacks
$file_name = preg_replace('/[^a-zA-Z0-9._-]/', '', $file_name);
$target_file = $target_dir . DIRECTORY_SEPARATOR . $file_name;
try {
if (move_uploaded_file($_FILES['file']['tmp_name'], $target_file)) {
header('Access-Control-Allow-Origin: *');
header('Content-type: application/json');
$data = ['url' => $target_file, 'message' => 'The file ' . $file_name . ' has been uploaded.'];
$uploader->addItem($news_id,$file_name);
http_response_code(201);
echo json_encode($data);
} else {
throw new Exception('Unable to move the uploaded file to its final location:' . $target_file);
}
} catch (\Throwable $th) {
header('Access-Control-Allow-Origin: *');
header('Content-type: application/json');
$data = ['message' => 'Sorry, there was an error uploading your file.', 'error' => $th->getMessage()];
http_response_code(400);
echo json_encode($data);
}
} else {
header('Access-Control-Allow-Origin: *');
header('Content-type: application/json');
$data = ['message' => 'Please upload a file.'];
http_response_code(400);
echo json_encode($data);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment