Newer
Older
<?php
namespace SGalinski\SgJobs\Controller;
/***************************************************************
* Copyright notice
*
* (c) sgalinski Internet Services (https://www.sgalinski.de)
*
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
use SGalinski\SgJobs\Domain\Model\JobApplication;
use SGalinski\SgMail\Service\MailTemplateService;
use TYPO3\CMS\Core\Resource\DuplicationBehavior;
use TYPO3\CMS\Core\Resource\ResourceFactory;
use TYPO3\CMS\Core\Utility\File\ExtendedFileUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
use TYPO3\CMS\Extbase\Object\ObjectManager;
/**
* The joblist plugin controller
*/
class JoblistController extends ActionController {
/**
* @var \SGalinski\SgJobs\Domain\Repository\CompanyRepository
/**
* @var \SGalinski\SgJobs\Domain\Repository\JobRepository
* @inject
*/
private $jobRepository;
/**
* Show all job offers and options to manage them
*
* @return void
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
* @throws \InvalidArgumentException
*/
public function indexAction() {
$recordPageId = $this->configurationManager->getConfiguration(
ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK
)['persistence']['storagePid'];

Torsten Oppermann
committed
$this->assignFilterValues($recordPageId);
// get all jobs for the next root page
$jobs = $this->jobRepository->findJobs($recordPageId);
$this->view->assign('jobs', $jobs);
}
* Renders the application form with an optional job
*
* @param JobApplication $applyData
public function applyFormAction(JobApplication $applyData = NULL) {
if ($this->request->getOriginalRequest()) {
$uploadedFiles = $this->request->getOriginalRequest()->getArguments()['uploadedFiles'];
$this->view->assign('uploadedFiles', $uploadedFiles);
}
$jobId = $this->request->getArguments()['jobData']['uid'];
if (!empty($jobId)) {
$jobData = $this->jobRepository->findByUid($jobId);
$this->view->assign('job', $jobData);
}
$allowedMimeTypes = $this->settings['allowedMimeTypes'];
$this->view->assign('allowedMimeTypes', $allowedMimeTypes);
$this->view->assign('jobApplication', $applyData);
* Saves the application send by the applyFormAction
*
* @param JobApplication $applyData
public function applyAction(JobApplication $applyData) {
$this->submitApplicationFiles($GLOBALS['TSFE']->fe_user->id, $applyData);
/** @noinspection PhpMethodParametersCountMismatchInspection */
$mailService = $this->objectManager->get(
MailTemplateService::class, 'application_mail', 'sg_jobs',
$this->getApplicationMailMarkers((array) $applyData)
);
$mailService->setIgnoreMailQueue(TRUE);
$mailService->setToAddresses($this->settings['applicationEmail']);
} catch (\Exception $exception) {
// possible errors, because of wrong mails (maybe log that somewhere? Does this makes sense?)
/**
* Pre-apply action setup, configures model-property mapping and handles file upload
Sergiu-Lucian Petrica
committed
*
* @return void
* @throws \TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException
* @throws \Exception
Sergiu-Lucian Petrica
committed
protected function initializeApplyAction() {
try {
$this->handleFileUpload('coverLetter');
$this->handleFileUpload('cv');
$this->handleFileUpload('certificates');
} catch (\Exception $e) {
// possible errors, because of wrong mails
// @TODO output them in some way?
}
Sergiu-Lucian Petrica
committed
$propertyMappingConfiguration = $this->arguments->getArgument('applyData')->getPropertyMappingConfiguration();
$propertyMappingConfiguration->forProperty('coverLetter')->allowAllProperties();
$propertyMappingConfiguration->forProperty('cv')->allowAllProperties();
$propertyMappingConfiguration->forProperty('certificates')->allowAllProperties();
Sergiu-Lucian Petrica
committed
$uploadedFiles = $this->getExistingApplicationFiles($GLOBALS['TSFE']->fe_user->id);
$this->request->setArgument('uploadedFiles', $uploadedFiles);
Sergiu-Lucian Petrica
committed
}

Torsten Oppermann
committed
/**

Torsten Oppermann
committed
* @param int $rootPageId
*/
private function assignFilterValues($rootPageId) {

Torsten Oppermann
committed
$countries = $this->companyRepository->getAllCountries($rootPageId);
$this->view->assign('countries', $countries);
$cities = $this->companyRepository->getAllCities($rootPageId);
$this->view->assign('cities', $cities);
$companies = $this->companyRepository->getAllCompanyNames($rootPageId);
$this->view->assign('companies', $companies);
$areas = $this->jobRepository->getAllAreas($rootPageId);
$this->view->assign('areas', $areas);
$functions = $this->jobRepository->getAllFunctions($rootPageId);
$this->view->assign('functions', $functions);
}
* Returns the application mail markers
*
* @param array $applyData
* @return array
*/
private function getApplicationMailMarkers(array $applyData = []): array {
return [
'jobtitle' => $applyData['jobTitle'],
'salutation' => $applyData['salutation'],
'firstname' => $applyData['firstName'],
'lastname' => $applyData['lastName'],
'street' => $applyData['street'],
'city' => $applyData['city'],
'country' => $applyData['country'],
'phone' => $applyData['phone'],
'mobile' => $applyData['mobile'],
'email' => $applyData['email'],
'message' => $applyData['message']
];
Sergiu-Lucian Petrica
committed
* Returns all the files in a folder
*
* @return \TYPO3\CMS\Core\Resource\File[]
* @throws \TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException
* @throws \Exception
* @throws \InvalidArgumentException
private function getExistingFiles($folder): array {
$objectManager = GeneralUtility::makeInstance(ObjectManager::class);
$resourceFactory = $objectManager->get(ResourceFactory::class);
$storage = $resourceFactory->getStorageObject(1);
Sergiu-Lucian Petrica
committed
$folderObject = $storage->getFolder('/Extension/' . $folder);
return $storage->getFilesInFolder($folderObject);
Sergiu-Lucian Petrica
committed
/**
* Returns all the application files based on a folder
*
Sergiu-Lucian Petrica
committed
* @return array
Sergiu-Lucian Petrica
committed
*/
private function getExistingApplicationFiles($folder): array {
Sergiu-Lucian Petrica
committed
$files['coverLetter'] = $this->getExistingFiles('temp/' . $folder . '/coverLetter');
$files['cv'] = $this->getExistingFiles('temp/' . $folder . '/cv');
$files['certificates'] = $this->getExistingFiles('temp/' . $folder . '/certificates');
return $files;
}
/**
* Moves the application files from temporary to permanent storage
*
* @param string $folder
* @param JobApplication $applicationData
Sergiu-Lucian Petrica
committed
* @return void
* @throws \TYPO3\CMS\Core\Resource\Exception\ExistingTargetFolderException
* @throws \TYPO3\CMS\Core\Resource\Exception\InvalidTargetFolderException
* @throws \TYPO3\CMS\Core\Exception
* @throws \TYPO3\CMS\Core\Resource\Exception\InsufficientFolderWritePermissionsException
* @throws \TYPO3\CMS\Core\Resource\Exception\IllegalFileExtensionException
* @throws \RuntimeException
* @throws \TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException
* @throws \Exception
* @throws \InvalidArgumentException
Sergiu-Lucian Petrica
committed
*/
private function submitApplicationFiles($folder, JobApplication $applicationData) {
$objectManager = GeneralUtility::makeInstance(ObjectManager::class);
$resourceFactory = $objectManager->get(ResourceFactory::class);
Sergiu-Lucian Petrica
committed
$storage = $resourceFactory->getStorageObject(1);
$newName = date('Ymd-His') . '_' . $applicationData->getFirstName();
Sergiu-Lucian Petrica
committed
$sourceFolder = $storage->getFolder('/Extension/temp/' . $folder);
Sergiu-Lucian Petrica
committed
$subFolders = $storage->getFoldersInFolder($sourceFolder);
$fileNames = [];
foreach ($subFolders as $subFolder) {
$files = $subFolder->getFiles();
foreach ($files as $file) {
$currentFile = $file->rename($newName . '_' . $subFolder->getName() . '.pdf');
$fileNames[$subFolder->getName()][] = $currentFile->getName();
$file->moveTo($sourceFolder);
}
$subFolder->delete();
}
$sourceFolder->rename($newName);
Sergiu-Lucian Petrica
committed
$sourceFolder = $storage->getFolder('/Extension/temp/' . $newName);
if (!$storage->hasFolder('/Extension/JobApplication/')) {
$storage->createFolder('/Extension/JobApplication/');
Sergiu-Lucian Petrica
committed
$targetFolder = $storage->getFolder('/Extension/JobApplication/');
Sergiu-Lucian Petrica
committed
$applicationFile = $storage->createFile($newName . '.csv', $sourceFolder);
$applicationFilePath = str_replace('/', '', $storage->getConfiguration()['basePath']) .
$applicationFile->getIdentifier();
Sergiu-Lucian Petrica
committed
$this->writeApplicationFile($applicationData, $applicationFilePath, $fileNames);
Sergiu-Lucian Petrica
committed
$storage->moveFolder($sourceFolder, $targetFolder);
}
Sergiu-Lucian Petrica
committed
/**
* Writes the application files
*
* @param JobApplication $data
* @param string $filePath
Sergiu-Lucian Petrica
committed
*/
private function writeApplicationFile(JobApplication $data, $filePath, $fileNames) {
Sergiu-Lucian Petrica
committed
$certificatesArr = [];
/** @var array[][] $fileNames */
if (isset($fileNames['certificates'])) {
foreach ($fileNames['certificates'] as $certificateName) {
$certificatesArr[] = $certificateName;
}
$certificateNames = implode($certificatesArr, ', ');
Sergiu-Lucian Petrica
committed
}
$dataToInsertArr = [
$data->getJobId(),
$data->getJobTitle(),
Sergiu-Lucian Petrica
committed
$data->getLastName(),
$data->getGender(),
$data->getCountry(),
$data->getBirthDate(),
$data->getEducation(),
$data->getStreet(),
$data->getZip(),
$data->getCity(),
$data->getNationality(),
$data->getPhone(),
$data->getEmail(),
$fileNames['coverLetter'][0],
$fileNames['cv'][0],
$certificateNames
];
try {
$file = fopen($filePath, 'wb+');
} catch (\RuntimeException $exception) {
throw new \RuntimeException($exception->getMessage());
}
}
/**
* Registers an uploaded file for TYPO3 native upload handling.
*
* @param array &$data
* @param string $namespace
* @param string $fieldName
* @param string $targetDirectory
* @return void
*/
private function registerUploadField(array &$data, $namespace, $fieldName, $targetDirectory = '1:/_temp_/') {
if (!\is_array($_FILES[$namespace])) {
return;
}
if (!isset($data['upload'])) {
$data['upload'] = [];
}
$counter = \count($data['upload']) + 1;
$keys = array_keys($_FILES[$namespace]);
foreach ($keys as $key) {
$_FILES['upload_' . $counter][$key] = $_FILES[$namespace][$key]['applyData'][$fieldName];
}
$data['upload'][$counter] = [
'data' => $counter,
'target' => $targetDirectory,
];
Sergiu-Lucian Petrica
committed
}
/**
* @param string $fieldName
* @throws \UnexpectedValueException
* @throws \TYPO3\CMS\Core\Resource\Exception\InsufficientFolderWritePermissionsException
* @throws \TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException
* @throws \TYPO3\CMS\Core\Resource\Exception\ExistingTargetFolderException
* @throws \Exception
* @throws \InvalidArgumentException
* @throws \TYPO3\CMS\Core\Resource\Exception
private function handleFileUpload($fieldName = ''): array {
$data = [];
$namespace = key($_FILES);
Sergiu-Lucian Petrica
committed
$applicationId = $GLOBALS['TSFE']->fe_user->id;
$objectManager = GeneralUtility::makeInstance(ObjectManager::class);
$resourceFactory = $objectManager->get(ResourceFactory::class);
$storage = $resourceFactory->getStorageObject(1);
Sergiu-Lucian Petrica
committed
if (!$storage->hasFolder('/Extension/temp/' . $applicationId . '/' . $fieldName)) {
$storage->createFolder('/Extension/temp/' . $applicationId . '/' . $fieldName);
Sergiu-Lucian Petrica
committed
$targetFalDirectory = '1:/Extension/temp/' . $applicationId . '/' . $fieldName;
// Register every upload field from the form:
$this->registerUploadField($data, $namespace, $fieldName, $targetFalDirectory);
// Initializing:
/** @var \TYPO3\CMS\Core\Utility\File\ExtendedFileUtility $fileProcessor */
$fileProcessor = GeneralUtility::makeInstance(ExtendedFileUtility::class);
$fileProcessor->setActionPermissions(['addFile' => TRUE]);
$fileProcessor->setFileExtensionPermissions($this->settings['allowedFileExtensions'], '');
// Actual upload
$fileProcessor->start($data);
// This was previously passed as empty string, why and from where? It breaks the upload if it's not set.
$fileProcessor->setExistingFilesConflictMode(DuplicationBehavior::REPLACE);
$result = $fileProcessor->processData();
foreach ((array) $result['upload'] as $files) {
/** @var array $files */
foreach ($files as $file) {
$uploadedFiles[] = $file;
}