Segelparade / www / symfonyproject / src / Controller / UploadController.php
UploadController.php
Raw
<?php



namespace App\Controller;
use App\Entity\Image;
use App\Entity\User;
use App\Entity\Tag;
use App\Entity\Processing;
use DateTime;
use Doctrine\ORM\EntityManagerInterface;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\HttpFoundation\Request;
use PHPMailer\PHPMailer\PHPMailer;
class UploadController extends AbstractController
{
        public function index(EntityManagerInterface $entityManager, Request $request): Response
        {
            //this function will send a confirmation mail to the adress specified in param
            //if none is specified it will default to mail set in env, if not set either no mail is send
            function sendMail($mailto = NULL,  $message="A new file was uploaded\n")
            {
                // todo: do not overwrite
                $message =  $message="A new file was uploaded\n\n". 
                "user: ". $_POST['username'] . "\n"  .
                "email: ". $_POST['emailInput'] . "\n" .
                "age:". $_POST['age'] . "\n".
                "direction: " . $_POST['direction'] . "\n". 
                "filename:".$_FILES['imageInput']['name']."\n".
                "backend: http://www.segelparade.de/backend " . "\n";
                


                $mailto = (isset($_ENV["NOTIFICATION_MAIL"])&&!$mailto) ? $_ENV["NOTIFICATION_MAIL"] : NULL;

                //return early if no recipient is specified
                if (! $mailto) {
                    return;
                }

                $mail = new PHPMailer(true);

                try {
                    // configure SMTP
                    $mail->isSMTP();
                    $mail->Host = 'smtp.ionos.de';
                    $mail->SMTPAuth = true;
                    $mail->Username = 'testmail@luckyluke.click';
                    $mail->Password = 'itestmymail';
                    $mail->SMTPSecure = 'ssl';
                    $mail->Port = 465;
                    $mail->setFrom('testmail@luckyluke.click', 'Luke Kahms');
                    $mail->addAddress($mailto);

                    // configure the message
                    $mail->Subject = 'Segelparade';
                    $mail->Body    = $message;

                    // send the mail
                    $mail->send();
                } catch (Exception $e) {
                    // error handling by frontend
                }
            }
            sendMail();

        $userInfo = null;
        $imageInfo = null;
       
        $maxFileSize = 64 * 1024 * 1024; // 64 MB in Bytes


            if($_SERVER["REQUEST_METHOD"] == "POST"){

                // setting variables with user form input
                $email = ($_POST['emailInput']);
                $image = ($_FILES['imageInput']);
                $name = ($_POST['username']);
                $age = ($_POST['age']);
                $allowedtypes = array(
                    "image/jpeg",
                    "image/png",
                    "image/tiff",
                    "image/heic"
                    );


                if(isset($_POST['content'])) {
                    $tagsCont = $_POST['content'];
                } else {
                    $tagsCont = []; 
                }
                
                if(isset($_POST['direction'])) {
                    $tagsDir = $_POST['direction'];
                } else {
                    $tagsDir = []; 
                }

                
                // checking user input
                if (!empty($email) && !empty($image) && !empty($tagsCont) && !empty($tagsDir) && $image['size'] > 0 && $image['size'] < $maxFileSize) {

                    // checking file type
                    if (in_array($image["type"],$allowedtypes)){
                        
                    
                        // check if email is already set, if not: create new user + persist

                        // // FS FEEDBACK FRONTEND: TODO duplicate code: The if will be executed AND again if false in the else
                        // if(!$entityManager->getRepository(User::class)->findByEmailExists($email)){
                        //     $userInfo = new User();
                        //     $userInfo->setEmail($email);
                        //     // todo: after the project is finished for next year: remove the age and name
                        //     $userInfo->setAge($age);
                        //     $userInfo->setName($name);

                        //     $entityManager->persist($userInfo);
                        // }
                        // // if it is already set: search for mail in DB and connect it to new upload
                        // else{
                        //     $userInfo = $entityManager->getRepository(User::class)->FindUserByEmail($email);
                        // }


                        // checking if user already exixts, else create new user
                        $userInfo = $entityManager->getRepository(User::class)->FindUserByEmail($email);

                        if ($userInfo === null) {
                            $userInfo = new User();
                            $userInfo->setEmail($email);
                            // todo: after the project is finished for next year: remove the age and name
                            $userInfo->setAge($age);
                            $userInfo->setName($name);

                            $entityManager->persist($userInfo);
                        }

                        

                        // create new Image object for new upload + persist
                        $imageInfo = new Image();


                        // FS FEEDBACK FRONTEND: Keep in mind, but code as it is. here we can get a race condition whre ids get mixed up. Would be better 
                        // to first insert in DB and then get the id, it will be automatically in $lastInsertedId = $imageInfo->getId();
                        // Caution, then the filename is not set yet, so we need to set it afterwards

                        // getting last image id from DB and adding 1 for current image id 
                        $imageId = (($entityManager->getRepository(Image::class)->findLastId()) + 1);
                        // creating new filename (e.g. Bild_1.jpg)
                        $newFilename = 'Bild_' . $imageId . "." . pathinfo($image['name'], PATHINFO_EXTENSION);

                        // processing
                        $process = $entityManager->getRepository(Processing::class)->findByType("new");

                        $imageInfo->addProcessing($process);
                        $imageInfo->setImageFile($newFilename);
                        $imageInfo->setUploaded(new DateTime("now"));
                        $imageInfo->setFkUser($userInfo);
                        $imageInfo->setAge($age);
                        $imageInfo->setName($name);

                        $entityManager->persist($imageInfo);

                        if(isset($image)) {
                            $fileName = $newFilename;
                            $tempFile = $image['tmp_name'];
                            $directory = $_ENV["UPLOAD_PATH"]; // directory where image is saved
                            
                            // moving image to said directory
                            move_uploaded_file($tempFile, $directory . $fileName);
                        } 



                        // check if content tags are selected
                        if(isset($tagsCont)) {
                        
                                // for each tag in array
                                foreach($tagsCont as $selectedValue) {
                                    
                                    // // FS FEEDBACK FRONTEND: TODO extra file. here are duplicate requests to the DB. Better: store the result in a variable
                                    // // check if tag is already set, if not: create new tag + persist
                                    // if(!$entityManager->getRepository(Tag::class)->findByTagExists($selectedValue)){
                                    //     // Done: FS FEEDBACK FRONTEND: TODO, see above. Why do we need it? Dangerous, becuase there will be a lot of tags, if someone missued the form. Better: fixtures
                                    
                                    //     $tag = new Tag();
                                    //     $tag->setName($selectedValue);
                                    //     $tag->setType('content');
                                    //     $imageInfo->addTag($tag);

                                    //     $entityManager->persist($tag);
                                    // }
                                    // // if it is already set: search for tag in DB and connect it
                                    // else{
                                    //     $tag = $entityManager->getRepository(Tag::class)->FindTagByName($selectedValue);
                                    //     $imageInfo->addTag($tag);
                                    // }



                                    // checking with fixtures which tag is selected and setting variable 
                                    $tag = $entityManager->getRepository(Tag::class)->FindTagByName($selectedValue);
                                    // adding tag to image object
                                    $imageInfo->addTag($tag);



                                // (only for displaying)
                                $tags[] = $tag;
                            }
                        }
                        else {
                            $tags = [];
                        }


                        // check if direction tags are selected
                        if(isset($tagsDir)) {

                            $selectedValue = $tagsDir;


                                // // check if tag is already set, if not: create new tag + persist
                                // if(!$entityManager->getRepository(Tag::class)->findByTagExists($selectedValue)){
                                //     // FS FEEDBACK FRONTEND: TODO see above, can be missused
                                //     $tag = new Tag();
                                //     $tag->setName($selectedValue);
                                //     $tag->setType('direction');
                                //     $imageInfo->addTag($tag);

                                //     $entityManager->persist($tag);
                                // }
                                // // if it is already set: search for tag in DB and connect it
                                // else{
                                //     $tag = $entityManager->getRepository(Tag::class)->FindTagByName($selectedValue);
                                //     $imageInfo->addTag($tag);
                                // }

                                
                                
                                // checking with fixtures which tag is selected and setting variable 
                                $tag = $entityManager->getRepository(Tag::class)->FindTagByName($selectedValue);
                                // adding tag to image object
                                $imageInfo->addTag($tag);



                            
                            // (only for displaying)
                            $tags[] = $tag;
                        
                        }
                        else {
                            $tags = [];
                        }

                        // flushing to database
                        $entityManager->flush();

                        
                        // after sucsess render landing page
                        return $this->render('upload/upload.html.twig', [
                            'user' => $userInfo,
                            'image' => $imageInfo,
                            'tags' => $tags,
                            'errorMessage' => ""
                        ]);
                    }
                
                    // error message on homepage when file type is not allowed
                    else{
                        $message = "Ihr Dateiformat wird nicht unterstützt. Erlaubt sind: .jpg, .png, .HEIC und .tiff";
                        return $this->render('frontend/index.html.twig', [
                        'errorMessage' => $message,
                    ]);
                    }

                }


                // error message on homepage if not all the mandatory inputs are given or file is bigger than allowed
                else {
                    $message = "Bitte füllen Sie alle erforderlichen Felder aus und beachten Sie, dass die Bilddatei nicht größer als 64MB sein darf.";
                    return $this->render('frontend/index.html.twig', [
                        'errorMessage' => $message,
                    ]);
                    
                }
            }

            // return to index.html.twig if server did not answer to POST request
            else{ 
                return $this->render('frontend/index.html.twig', [
                ]);
            }



        }
}