From f1fd857acc01b727b2fbc5872f5c47762faa28a2 Mon Sep 17 00:00:00 2001 From: Kevin Ditscheid <kevin.ditscheid@sgalinski.de> Date: Fri, 24 Nov 2023 11:53:17 +0100 Subject: [PATCH] [TASK] Fix PHPStan issues --- Classes/Controller/Ajax/UploadController.php | 17 +- Classes/Controller/BackendController.php | 16 +- Classes/Controller/JobTeaserController.php | 28 +-- Classes/Controller/JoblistController.php | 126 +++++--------- Classes/Domain/Model/Contact.php | 7 +- Classes/Domain/Model/Job.php | 26 +-- Classes/Domain/Model/JobApplication.php | 59 ++++--- .../Domain/Repository/CompanyRepository.php | 10 +- .../Repository/DepartmentRepository.php | 5 +- .../Repository/ExperienceLevelRepository.php | 5 +- Classes/Domain/Repository/JobRepository.php | 51 +++--- .../Listener/AccessPageListEventListener.php | 2 + Classes/Pagination/Pagination.php | 4 - Classes/Service/BackendService.php | 25 +-- Classes/Service/FileAndFolderService.php | 43 ++--- Classes/Service/SitemapService.php | 34 ++-- .../ViewHelpers/Backend/ControlViewHelper.php | 23 +-- Classes/ViewHelpers/Form/UploadViewHelper.php | 32 +++- Classes/ViewHelpers/Widget/UriViewHelper.php | 161 ------------------ ext_localconf.php | 13 -- 20 files changed, 241 insertions(+), 446 deletions(-) delete mode 100644 Classes/ViewHelpers/Widget/UriViewHelper.php diff --git a/Classes/Controller/Ajax/UploadController.php b/Classes/Controller/Ajax/UploadController.php index 86508a06..f17b00e0 100644 --- a/Classes/Controller/Ajax/UploadController.php +++ b/Classes/Controller/Ajax/UploadController.php @@ -26,6 +26,7 @@ namespace SGalinski\SgJobs\Controller\Ajax; +use Psr\Http\Message\ResponseInterface; use SGalinski\SgAjax\Controller\Ajax\AbstractAjaxController; use SGalinski\SgJobs\Service\FileAndFolderService; use TYPO3\CMS\Core\Core\Environment; @@ -85,37 +86,40 @@ class UploadController extends AbstractAjaxController { /** * Uploads a new cover letter. * - * @return void + * @return ResponseInterface * @throws ExistingTargetFolderException * @throws InsufficientFolderAccessPermissionsException * @throws InsufficientFolderWritePermissionsException */ - public function uploadCoverletterAction(): void { + public function uploadCoverletterAction(): ResponseInterface { $this->handleAnyDropZoneUpload(); + return $this->htmlResponse(); } /** * Uploads a new cd. * - * @return void + * @return ResponseInterface * @throws ExistingTargetFolderException * @throws InsufficientFolderAccessPermissionsException * @throws InsufficientFolderWritePermissionsException */ - public function uploadCvAction(): void { + public function uploadCvAction(): ResponseInterface { $this->handleAnyDropZoneUpload(); + return $this->htmlResponse(); } /** * Uploads a new certificate. * - * @return void + * @return ResponseInterface * @throws ExistingTargetFolderException * @throws InsufficientFolderAccessPermissionsException * @throws InsufficientFolderWritePermissionsException */ - public function uploadCertificateAction(): void { + public function uploadCertificateAction(): ResponseInterface { $this->handleAnyDropZoneUpload(); + return $this->htmlResponse(); } /** @@ -146,6 +150,7 @@ class UploadController extends AbstractAjaxController { } else { $folder = $storage->getFolder($this->jobFolderPath); } + // if temp folder is not existing, create one if ($folder && !$storage->hasFolderInFolder(self::JOB_APPLICATION_TEMP_FOLDER, $folder)) { $storage->createFolder(self::JOB_APPLICATION_TEMP_FOLDER, $folder); diff --git a/Classes/Controller/BackendController.php b/Classes/Controller/BackendController.php index 928a5ed6..84f8133d 100644 --- a/Classes/Controller/BackendController.php +++ b/Classes/Controller/BackendController.php @@ -34,9 +34,8 @@ use SGalinski\SgJobs\Service\BackendService; use TYPO3\CMS\Backend\Template\Components\DocHeaderComponent; use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; -use TYPO3\CMS\Core\Messaging\FlashMessage; +use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity; use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Core\Utility\VersionNumberUtility; use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; use TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException; use TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException; @@ -89,11 +88,11 @@ class BackendController extends ActionController { * * @param array $filters * @param int $currentPage - * @return ResponseInterface|null + * @return ResponseInterface * @throws InvalidQueryException|NoSuchArgumentException */ - public function indexAction(array $filters = [], int $currentPage = 1): ?ResponseInterface { - $pageUid = (int) GeneralUtility::_GP('id'); + public function indexAction(array $filters = [], int $currentPage = 1): ResponseInterface { + $pageUid = (int) $this->request->getQueryParams()['id']; $itemsPerPage = 10; /** @var BackendUserAuthentication $backendUser */ $backendUser = $GLOBALS['BE_USER']; @@ -135,15 +134,10 @@ class BackendController extends ActionController { $this->addFlashMessage( LocalizationUtility::translate('backend.notice.noRecords', 'SgJobs'), '', - FlashMessage::INFO + ContextualFeedbackSeverity::INFO ); } - if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) { - $this->view->assign('V11', FALSE); - return NULL; - } - $this->view->assign('V11', TRUE); return $this->createBackendResponse(); } diff --git a/Classes/Controller/JobTeaserController.php b/Classes/Controller/JobTeaserController.php index 63ef1058..ddff5672 100644 --- a/Classes/Controller/JobTeaserController.php +++ b/Classes/Controller/JobTeaserController.php @@ -57,26 +57,26 @@ class JobTeaserController extends ActionController { if (isset($this->settings['filterByDepartment']) && $this->settings['filterByDepartment'] !== '') { $filters['filterByDepartment'] = $this->settings['filterByDepartment']; } + if (isset($this->settings['filterByExperienceLevel']) && $this->settings['filterByExperienceLevel'] !== '') { $filters['filterByExperienceLevel'] = $this->settings['filterByExperienceLevel']; } + if (isset($this->settings['filterByLocation']) && $this->settings['filterByLocation'] !== '') { $filters['filterByLocation'] = $this->settings['filterByLocation']; } - // TODO: Remove this on the next breaking change - // Used for backwards compatibility but is the same as 'filterByLocation' above - if (isset($this->settings['location']) && $this->settings['location'] !== '') { - $filters['filterByLocation'] = $this->settings['location']; - } - foreach ($filters as &$filter) { $filter = $filter ? GeneralUtility::trimExplode(',', $filter) : NULL; foreach ($filter as &$value) { $value = (int) $value; } + + unset($value); } + unset($filter); + $totalAmountOfOffers = $this->jobRepository->countAll($filters); $querySettings = $this->jobRepository->createQuery()->getQuerySettings(); @@ -88,22 +88,6 @@ class JobTeaserController extends ActionController { $this->view->assign('filters', $filters); $this->view->assign('featuredOffers', $featuredOffers); - if (version_compare(\TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) { - return NULL; - } - return $this->htmlResponse(); } - - /** - * Build Typo3 11 Response - * - * @param string|NULL $html - * @return ResponseInterface - */ - protected function htmlResponse(string $html = NULL): ResponseInterface { - return $this->responseFactory->createResponse() - ->withHeader('Content-Type', 'text/html; charset=utf-8') - ->withBody($this->streamFactory->createStream($html ?? $this->view->render())); - } } diff --git a/Classes/Controller/JoblistController.php b/Classes/Controller/JoblistController.php index e1cc0193..885c1530 100644 --- a/Classes/Controller/JoblistController.php +++ b/Classes/Controller/JoblistController.php @@ -27,7 +27,6 @@ namespace SGalinski\SgJobs\Controller; use Psr\Http\Message\ResponseInterface; -use SGalinski\ProjectBase\Domain\Repository\CountryRepository; use SGalinski\SgJobs\Controller\Ajax\UploadController; use SGalinski\SgJobs\Domain\Model\Company; use SGalinski\SgJobs\Domain\Model\Job; @@ -39,12 +38,14 @@ use SGalinski\SgJobs\Domain\Repository\JobApplicationRepository; use SGalinski\SgJobs\Domain\Repository\JobRepository; use SGalinski\SgJobs\Service\FileAndFolderService; use SGalinski\SgMail\Service\MailTemplateService; +use SGalinski\SgSeo\Service\HeadTagService; use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationExtensionNotConfiguredException; use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationPathDoesNotExistException; use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; use TYPO3\CMS\Core\Context\Context; use TYPO3\CMS\Core\Context\Exception\AspectNotFoundException; use TYPO3\CMS\Core\Core\Environment; +use TYPO3\CMS\Core\Country\CountryProvider; use TYPO3\CMS\Core\Error\Http\PageNotFoundException; use TYPO3\CMS\Core\Exception\SiteNotFoundException; use TYPO3\CMS\Core\Http\ImmediateResponseException; @@ -61,16 +62,17 @@ use TYPO3\CMS\Core\Site\SiteFinder; use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\PathUtility; -use TYPO3\CMS\Core\Utility\VersionNumberUtility; use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface; +use TYPO3\CMS\Extbase\Http\ForwardResponse; use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; use TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentNameException; use TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException; -use TYPO3\CMS\Extbase\Mvc\Exception\StopActionException; +use TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException; use TYPO3\CMS\Extbase\Property\Exception\TypeConverterException; use TYPO3\CMS\Extbase\Utility\LocalizationUtility; use TYPO3\CMS\Extbase\Validation\Validator\ConjunctionValidator; use TYPO3\CMS\Extbase\Validation\Validator\GenericObjectValidator; +use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer; use TYPO3\CMS\Frontend\Controller\ErrorController; use TYPO3\CMS\Frontend\Page\PageAccessFailureReasons; @@ -193,13 +195,13 @@ class JoblistController extends ActionController { */ public function initializeIndexAction(): void { $currentPageBrowserPage = 0; - $parameters = GeneralUtility::_GP('tx_sgjobs_pagebrowser'); + $parameters = $this->request->getQueryParams()['tx_sgjobs_pagebrowser']; if (is_array($parameters)) { $currentPageBrowserPage = (int) $parameters['currentPage'] ?: 0; } if ($currentPageBrowserPage > 0) { - $this->request->setArgument('currentPageBrowserPage', $currentPageBrowserPage); + $this->request = $this->request->withArgument('currentPageBrowserPage', $currentPageBrowserPage); } } @@ -209,7 +211,7 @@ class JoblistController extends ActionController { * @param array $filters * @param int|null $jobId * @param int $currentPageBrowserPage - * @return ResponseInterface|null + * @return ResponseInterface * @throws ImmediateResponseException * @throws AspectNotFoundException * @throws PageNotFoundException @@ -218,7 +220,7 @@ class JoblistController extends ActionController { array $filters = [], int $jobId = NULL, int $currentPageBrowserPage = 0 - ): ?ResponseInterface { + ): ResponseInterface { if ($filters) { $this->view->assign('selectedCountry', $filters['filterCountry'] ?? ''); $this->view->assign('selectedCompany', $filters['filterCompany'] ?? ''); @@ -243,9 +245,11 @@ class JoblistController extends ActionController { foreach ($filter as &$value) { $value = (int) $value; } + unset($value); } } + unset($filter); $storagePids = GeneralUtility::trimExplode( @@ -268,7 +272,7 @@ class JoblistController extends ActionController { if (ExtensionManagementUtility::isLoaded('sg_seo')) { $headTagService = GeneralUtility::makeInstance( - \SGalinski\SgSeo\Service\HeadTagService::class, + HeadTagService::class, TRUE, $job->getTitle(), $job->getDescription(), @@ -315,10 +319,6 @@ class JoblistController extends ActionController { $this->view->assign('limit', $jobLimit); $this->view->assign('numberOfPages', $numberOfPages); - if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) { - return NULL; - } - return $this->htmlResponse(); } @@ -328,9 +328,8 @@ class JoblistController extends ActionController { * @param JobApplication|null $applyData * @param string $error * @param int|null $jobId - * @return ResponseInterface|null + * @return ResponseInterface * @throws AspectNotFoundException - * @throws StopActionException * @throws SiteNotFoundException * @throws InvalidArgumentNameException */ @@ -338,10 +337,10 @@ class JoblistController extends ActionController { JobApplication $applyData = NULL, string $error = '', int $jobId = NULL - ): ?ResponseInterface { + ): ResponseInterface { if ($error !== '') { $this->view->assign('internalError', $error); - $this->request->setArgument('error', NULL); + $this->request = $this->request->withArgument('error', NULL); } if ($jobId === NULL && $this->settings['disallowUnsolicitedApplication']) { @@ -362,8 +361,9 @@ class JoblistController extends ActionController { if ($folderName === NULL) { $folderName = \md5(\uniqid('sgjobs-', TRUE)); - $this->request->setArgument('folderName', $folderName); + $this->request = $this->request->withArgument('folderName', $folderName); } + $this->view->assign('folderName', $folderName); $job = NULL; @@ -373,7 +373,7 @@ class JoblistController extends ActionController { if ($job) { if (ExtensionManagementUtility::isLoaded('sg_seo')) { $headTagService = GeneralUtility::makeInstance( - \SGalinski\SgSeo\Service\HeadTagService::class, + HeadTagService::class, FALSE, $job->getTitle(), $job->getDescription(), @@ -389,6 +389,7 @@ class JoblistController extends ActionController { $this->view->assign('relatedJobs', $relatedJobs); } } + $this->view->assign('job', $job); } else { $storagePids = GeneralUtility::trimExplode( @@ -408,9 +409,10 @@ class JoblistController extends ActionController { ->getLanguageById($sysLanguageUid); $countries = []; if (ExtensionManagementUtility::isLoaded('project_base')) { - $countryRepository = $this->objectManager->get(CountryRepository::class); - $countries = $countryRepository->findAllOrderedByLanguage($site->getTwoLetterIsoCode()); + $countryProvider = GeneralUtility::makeInstance(CountryProvider::class); + $countries = $countryProvider->getAll(); } + $this->view->assign('countries', $countries); $this->view->assign('sysLanguageUid', $sysLanguageUid); @@ -420,7 +422,8 @@ class JoblistController extends ActionController { $this->view->assign('allowedFileExtensions', $allowedFileExtensions); if ($applyData === NULL) { - $applyData = $this->objectManager->get(JobApplication::class); + /** @var JobApplication $applyData */ + $applyData = GeneralUtility::makeInstance(JobApplication::class); if ($job) { $applyData->setJobId($job->getJobId()); } @@ -438,11 +441,7 @@ class JoblistController extends ActionController { $arguments = $this->request->getArguments(); if (isset($arguments['applyData']) && $arguments['applyData']) { $arguments['applyData'] = (string) $arguments['applyData']; - $this->request->setArguments($arguments); - } - - if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) { - return NULL; + $this->request = $this->request->withArguments($arguments); } return $this->htmlResponse(); @@ -454,10 +453,9 @@ class JoblistController extends ActionController { * @param JobApplication $applicationData * @param string $folderName * @return void - * @throws StopActionException */ protected function createCsvSummary(JobApplication $applicationData, string $folderName): void { - $resourceFactory = $this->objectManager->get(ResourceFactory::class); + $resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class); $newName = \date('Ymd-His') . '_' . $applicationData->getJobId() . '-' . $applicationData->getFirstName() . '-' . $applicationData->getLastName(); $storage = $resourceFactory->getStorageObject(1); @@ -525,7 +523,6 @@ class JoblistController extends ActionController { * Pre-apply action setup, configures model-property mapping and handles file upload * * @throws NoSuchArgumentException - * @throws StopActionException */ protected function initializeApplyAction(): void { $propertyMappingConfiguration = $this->arguments->getArgument('applyData')->getPropertyMappingConfiguration(); @@ -537,9 +534,8 @@ class JoblistController extends ActionController { foreach ($validator->getValidators() as $subValidator) { /** @var GenericObjectValidator $subValidatorSub */ foreach ($subValidator->getValidators() as $subValidatorSub) { - $subValidatorSub->getPropertyValidators('job')->removeAll( - $subValidatorSub->getPropertyValidators('job') - ); + $subValidatorsSub = $subValidatorSub->getPropertyValidators(); + unset($subValidatorsSub['job']); } } } @@ -548,13 +544,12 @@ class JoblistController extends ActionController { * Saves the application send by the applyFormAction * * @param JobApplication $applyData - * @return ResponseInterface|null - * @throws NoSuchArgumentException - * @throws StopActionException + * @return ResponseInterface * @throws ExtensionConfigurationExtensionNotConfiguredException * @throws ExtensionConfigurationPathDoesNotExistException + * @throws IllegalObjectTypeException */ - public function applyAction(JobApplication $applyData): ?ResponseInterface { + public function applyAction(JobApplication $applyData): ResponseInterface { $folderName = $this->request->getArgument('folderName'); $enableApplicantMail = (bool) GeneralUtility::makeInstance(ExtensionConfiguration::class) ->get('sg_jobs', 'enableApplicantMail'); @@ -592,8 +587,8 @@ class JoblistController extends ActionController { $this->moveTmpFolder($folderName, $applyData); $this->createCsvSummary($applyData, $folderName); - /** @noinspection PhpParamsInspection */ - $mailService = $this->objectManager->get( + /** @var MailTemplateService $mailService */ + $mailService = GeneralUtility::makeInstance( MailTemplateService::class, 'application_mail', 'sg_jobs', @@ -605,8 +600,8 @@ class JoblistController extends ActionController { $mailService->setPid($site->getRootPageId()); if ($enableApplicantMail) { - /** @noinspection PhpParamsInspection */ - $applicantMailService = $this->objectManager->get( + /** @var MailTemplateService $applicantMailService */ + $applicantMailService = GeneralUtility::makeInstance( MailTemplateService::class, 'applicant_mail', 'sg_jobs', @@ -671,36 +666,26 @@ class JoblistController extends ActionController { $redirectPageUid = (int) $this->settings['redirectPage']; if ($redirectPageUid) { - $contentObject = $this->configurationManager->getContentObject(); + $contentObject = GeneralUtility::makeInstance(ContentObjectRenderer::class); if ($contentObject) { - $url = $contentObject->getTypoLink_URL($redirectPageUid); + $url = $contentObject->typoLink_URL(['params' => $redirectPageUid]); $this->redirectToUri($url); } } $this->redirect('applyForm'); } catch (\Exception $exception) { - if ($exception instanceof StopActionException) { - return NULL; - } $this->deleteTmpFolder($folderName); $job = $applyData->getJob(); - $jobId = $job !== NULL ? $job->getUid() : NULL; + $jobId = $job?->getUid(); // remove application, since there was an exception (e.g. upload filetype mismatch @see: moveTmpFolder()) $this->jobApplicationRepository->remove($applyData); - $this->request->setArgument('folderName', $folderName); - $this->forward( - 'applyForm', - NULL, - NULL, + $this->request = $this->request->withArgument('folderName', $folderName); + return (new ForwardResponse('applyForm'))->withArguments( ['applyData' => $applyData, 'error' => $exception->getMessage(), 'jobId' => $jobId] ); } - if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) { - return NULL; - } - return $this->htmlResponse(); } @@ -826,6 +811,7 @@ class JoblistController extends ActionController { if (!$usableFile) { throw new \RuntimeException('File not found (' . $singleFilePostKey . ')!'); } + $usableFile = $storage->copyFile($usableFile, $newFolder, $newFilename); } elseif (!$newFolder->hasFile($newFilename)) { // when we reload, etc. this image might already be moved. @@ -836,6 +822,7 @@ class JoblistController extends ActionController { /** @noinspection PhpUnreachableStatementInspection */ $usableFile = $this->getFileInFolder($newFilename, $newFolder); } + $fileReference = $this->fileAndFolderService->createFileReferenceFromFalFileObject($usableFile); if ($singleFilePostKey === 'coverLetter') { @@ -857,22 +844,12 @@ class JoblistController extends ActionController { /** * Gets a file in a folder. * - * (Backwards compatible with TYPO3 10, where the Folder did not have a getFile() method yet). - * * @param string $fileName * @param Folder $folder * @return File|null */ protected function getFileInFolder(string $fileName, Folder $folder): ?File { - if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '>=')) { - return $folder->getFile($fileName); - } - - if ($folder->getStorage()->hasFileInFolder($fileName, $folder)) { - return $folder->getStorage()->getFileInFolder($fileName, $folder); - } - - return NULL; + return $folder->getFile($fileName); } /** @@ -891,7 +868,7 @@ class JoblistController extends ActionController { */ protected function deleteTmpFolder(string $folderName): void { /** @var ResourceFactory $resourceFactory */ - $resourceFactory = $this->objectManager->get(ResourceFactory::class); + $resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class); $storage = $resourceFactory->getStorageObject(1); try { $tempFolder = $storage->getFolder('/JobApplication/' . $folderName); @@ -905,9 +882,8 @@ class JoblistController extends ActionController { * If for any reason something goes wrong, delete the tmp upload folder * * @return ResponseInterface - * @throws NoSuchArgumentException */ - public function errorAction() { + public function errorAction(): ResponseInterface { if ($this->request->hasArgument('folderName')) { $folderName = $this->request->getArgument('folderName'); $this->deleteTmpFolder($folderName); @@ -915,16 +891,4 @@ class JoblistController extends ActionController { return parent::errorAction(); } - - /** - * Build TYPO3 11 Response - * - * @param string|NULL $html - * @return ResponseInterface - */ - protected function htmlResponse(string $html = NULL): ResponseInterface { - return $this->responseFactory->createResponse() - ->withHeader('Content-Type', 'text/html; charset=utf-8') - ->withBody($this->streamFactory->createStream($html ?? $this->view->render())); - } } diff --git a/Classes/Domain/Model/Contact.php b/Classes/Domain/Model/Contact.php index 065c5de3..60578858 100644 --- a/Classes/Domain/Model/Contact.php +++ b/Classes/Domain/Model/Contact.php @@ -26,6 +26,7 @@ namespace SGalinski\SgJobs\Domain\Model; +use TYPO3\CMS\Extbase\Annotation\ORM\Lazy; use TYPO3\CMS\Extbase\Domain\Model\FileReference; use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; use TYPO3\CMS\Extbase\Persistence\Generic\LazyLoadingProxy; @@ -85,9 +86,9 @@ class Contact extends AbstractEntity { protected $country = ''; /** - * @TYPO3\CMS\Extbase\Annotation\ORM\Lazy - * @var FileReference - */ + * @var FileReference + */ + #[Lazy] protected $image; /** diff --git a/Classes/Domain/Model/Job.php b/Classes/Domain/Model/Job.php index 44e283b5..820f4191 100644 --- a/Classes/Domain/Model/Job.php +++ b/Classes/Domain/Model/Job.php @@ -26,6 +26,8 @@ namespace SGalinski\SgJobs\Domain\Model; +use TYPO3\CMS\Extbase\Annotation\ORM\Lazy; +use TYPO3\CMS\Extbase\Domain\Model\FileReference; use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; use TYPO3\CMS\Extbase\Persistence\Generic\LazyLoadingProxy; use TYPO3\CMS\Extbase\Persistence\ObjectStorage; @@ -45,9 +47,9 @@ class Job extends AbstractEntity { protected $jobId = ''; /** - * @var ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\FileReference> - * @TYPO3\CMS\Extbase\Annotation\ORM\Lazy - */ + * @var ObjectStorage<FileReference> + */ + #[Lazy] protected $attachment; /** @@ -102,21 +104,21 @@ class Job extends AbstractEntity { protected $sorting; /** - * @var ObjectStorage<Company> - * @TYPO3\CMS\Extbase\Annotation\ORM\Lazy - */ + * @var ObjectStorage<Company> + */ + #[Lazy] protected $company; /** - * @TYPO3\CMS\Extbase\Annotation\ORM\Lazy - * @var ObjectStorage<Job> - */ + * @var ObjectStorage<Job> + */ + #[Lazy] protected $relatedJobs; /** - * @TYPO3\CMS\Extbase\Annotation\ORM\Lazy - * @var ObjectStorage<ExperienceLevel> - */ + * @var ObjectStorage<ExperienceLevel> + */ + #[Lazy] protected $experienceLevel; /** diff --git a/Classes/Domain/Model/JobApplication.php b/Classes/Domain/Model/JobApplication.php index fd8b999a..eaedf1ef 100644 --- a/Classes/Domain/Model/JobApplication.php +++ b/Classes/Domain/Model/JobApplication.php @@ -26,6 +26,9 @@ namespace SGalinski\SgJobs\Domain\Model; +use TYPO3\CMS\Extbase\Annotation\ORM\Lazy; +use TYPO3\CMS\Extbase\Annotation\Validate; +use TYPO3\CMS\Extbase\Domain\Model\FileReference; use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; use TYPO3\CMS\Extbase\Persistence\Generic\LazyLoadingProxy; use TYPO3\CMS\Extbase\Persistence\ObjectStorage; @@ -48,9 +51,9 @@ class JobApplication extends AbstractEntity { /** * @var ObjectStorage<Company> - * @TYPO3\CMS\Extbase\Annotation\ORM\Lazy */ - protected $company = ''; + #[Lazy] + protected $company; /** * @var Job $job @@ -59,68 +62,68 @@ class JobApplication extends AbstractEntity { /** * @var string $gender - * @TYPO3\CMS\Extbase\Annotation\Validate("NotEmpty") */ + #[Validate(['validator' => 'NotEmpty'])] protected $gender = ''; /** * @var string $firstName - * @TYPO3\CMS\Extbase\Annotation\Validate("NotEmpty") */ + #[Validate(['validator' => 'NotEmpty'])] protected $firstName = ''; /** * @var string $lastName - * @TYPO3\CMS\Extbase\Annotation\Validate("NotEmpty") */ + #[Validate(['validator' => 'NotEmpty'])] protected $lastName = ''; /** * @var string $street - * @TYPO3\CMS\Extbase\Annotation\Validate("NotEmpty") */ + #[Validate(['validator' => 'NotEmpty'])] protected $street = ''; /** * @var string $city - * @TYPO3\CMS\Extbase\Annotation\Validate("NotEmpty") */ + #[Validate(['validator' => 'NotEmpty'])] protected $city = ''; /** * @var string $zip - * @TYPO3\CMS\Extbase\Annotation\Validate("NotEmpty") */ + #[Validate(['validator' => 'NotEmpty'])] protected $zip = ''; /** * @var string $country - * @TYPO3\CMS\Extbase\Annotation\Validate("NotEmpty") */ + #[Validate(['validator' => 'NotEmpty'])] protected $country = ''; /** * @var string $nationality - * @TYPO3\CMS\Extbase\Annotation\Validate("NotEmpty") */ + #[Validate(['validator' => 'NotEmpty'])] protected $nationality = ''; /** * @var string $education - * @TYPO3\CMS\Extbase\Annotation\Validate("NotEmpty") */ + #[Validate(['validator' => 'NotEmpty'])] protected $education = ''; /** * @var string $birthDate - * @TYPO3\CMS\Extbase\Annotation\Validate("NotEmpty") */ + #[Validate(['validator' => 'NotEmpty'])] protected $birthDate = ''; /** * @var string $phone - * @TYPO3\CMS\Extbase\Annotation\Validate("NotEmpty") */ + #[Validate(['validator' => 'NotEmpty'])] protected $phone = ''; /** @@ -130,23 +133,23 @@ class JobApplication extends AbstractEntity { /** * @var string $email - * @TYPO3\CMS\Extbase\Annotation\Validate("NotEmpty") - * @TYPO3\CMS\Extbase\Annotation\Validate("EmailAddress") */ + #[Validate(['validator' => 'NotEmpty'])] + #[Validate(['validator' => 'EmailAddress'])] protected $email = ''; /** - * @var \TYPO3\CMS\Extbase\Domain\Model\FileReference $coverLetter + * @var FileReference $coverLetter */ protected $coverLetter; /** - * @var \TYPO3\CMS\Extbase\Domain\Model\FileReference $cv + * @var FileReference $cv */ protected $cv; /** - * @var \TYPO3\CMS\Extbase\Domain\Model\FileReference $certificate + * @var FileReference $certificate */ protected $certificate; @@ -157,8 +160,8 @@ class JobApplication extends AbstractEntity { /** * @var bool - * @TYPO3\CMS\Extbase\Annotation\Validate("Boolean", options={"is": TRUE}) */ + #[Validate(['validator' => 'Boolean', 'options' => ['is' => TRUE]])] protected $privacyPolicy = FALSE; /** @@ -365,44 +368,44 @@ class JobApplication extends AbstractEntity { } /** - * @return \TYPO3\CMS\Extbase\Domain\Model\FileReference + * @return FileReference */ public function getCoverLetter() { return $this->coverLetter; } /** - * @param \TYPO3\CMS\Extbase\Domain\Model\FileReference $coverLetter + * @param FileReference $coverLetter */ - public function setCoverLetter(\TYPO3\CMS\Extbase\Domain\Model\FileReference $coverLetter = NULL) { + public function setCoverLetter(FileReference $coverLetter = NULL) { $this->coverLetter = $coverLetter; } /** - * @return \TYPO3\CMS\Extbase\Domain\Model\FileReference + * @return FileReference */ public function getCv() { return $this->cv; } /** - * @param \TYPO3\CMS\Extbase\Domain\Model\FileReference $cv + * @param FileReference $cv */ - public function setCV(\TYPO3\CMS\Extbase\Domain\Model\FileReference $cv = NULL) { + public function setCV(FileReference $cv = NULL) { $this->cv = $cv; } /** - * @return \TYPO3\CMS\Extbase\Domain\Model\FileReference + * @return FileReference */ public function getCertificate() { return $this->certificate; } /** - * @param \TYPO3\CMS\Extbase\Domain\Model\FileReference $certificate + * @param FileReference $certificate */ - public function setCertificate(\TYPO3\CMS\Extbase\Domain\Model\FileReference $certificate = NULL) { + public function setCertificate(FileReference $certificate = NULL) { $this->certificate = $certificate; } diff --git a/Classes/Domain/Repository/CompanyRepository.php b/Classes/Domain/Repository/CompanyRepository.php index 91d50107..b7be6123 100644 --- a/Classes/Domain/Repository/CompanyRepository.php +++ b/Classes/Domain/Repository/CompanyRepository.php @@ -129,13 +129,14 @@ class CompanyRepository extends Repository { foreach ($pageUids as $pageUid) { $hash .= $pageUid . '_' . implode('-', $filters); } + if (!isset($this->cache[$hash])) { $companyConstraints = []; $query = $this->createQuery(); $querySettings = $query->getQuerySettings(); $querySettings->setStoragePageIds($pageUids); - $querySettings->setLanguageUid( - GeneralUtility::makeInstance(Context::class)->getPropertyFromAspect('language', 'id', 0) + $querySettings->setLanguageAspect( + GeneralUtility::makeInstance(Context::class)->getAspect('language') ); $query->setQuerySettings($querySettings); @@ -151,10 +152,11 @@ class CompanyRepository extends Repository { foreach ($filters as $filter) { $constraints[] = $query->equals('uid', $filter); } - $companyConstraints[] = $query->logicalOr($constraints); + + $companyConstraints[] = $query->logicalOr(...$constraints); } - $query->matching($query->logicalAnd($companyConstraints)); + $query->matching($query->logicalAnd(...$companyConstraints)); $this->cache[$hash] = $query->execute(); } diff --git a/Classes/Domain/Repository/DepartmentRepository.php b/Classes/Domain/Repository/DepartmentRepository.php index d1d2e2ae..9ecce30b 100644 --- a/Classes/Domain/Repository/DepartmentRepository.php +++ b/Classes/Domain/Repository/DepartmentRepository.php @@ -37,9 +37,6 @@ use TYPO3\CMS\Extbase\Persistence\Repository; * @author Kevin Ditscheid <kevin.ditscheid@sgalinski.de> */ class DepartmentRepository extends Repository { - /** - * @var array - */ protected $defaultOrderings = [ 'sorting' => QueryInterface::ORDER_ASCENDING, 'title' => QueryInterface::ORDER_ASCENDING @@ -62,7 +59,7 @@ class DepartmentRepository extends Repository { $constraints[] = $query->equals('uid', $filter); } - $query->matching($query->logicalOr($constraints)); + $query->matching($query->logicalOr(...$constraints)); return $query->execute(); } } diff --git a/Classes/Domain/Repository/ExperienceLevelRepository.php b/Classes/Domain/Repository/ExperienceLevelRepository.php index 3fe083a2..4ba16c0d 100644 --- a/Classes/Domain/Repository/ExperienceLevelRepository.php +++ b/Classes/Domain/Repository/ExperienceLevelRepository.php @@ -37,9 +37,6 @@ use TYPO3\CMS\Extbase\Persistence\Repository; * @author Johannes Kreiner <jkreiner@sgalinski.de> */ class ExperienceLevelRepository extends Repository { - /** - * @var array - */ protected $defaultOrderings = [ 'sorting' => QueryInterface::ORDER_ASCENDING, 'title' => QueryInterface::ORDER_ASCENDING @@ -62,7 +59,7 @@ class ExperienceLevelRepository extends Repository { $constraints[] = $query->equals('uid', $filter); } - $query->matching($query->logicalOr($constraints)); + $query->matching($query->logicalOr(...$constraints)); return $query->execute(); } } diff --git a/Classes/Domain/Repository/JobRepository.php b/Classes/Domain/Repository/JobRepository.php index 8012f4fd..77ab3742 100644 --- a/Classes/Domain/Repository/JobRepository.php +++ b/Classes/Domain/Repository/JobRepository.php @@ -27,12 +27,7 @@ namespace SGalinski\SgJobs\Domain\Repository; use SGalinski\SgJobs\Domain\Model\Job; -use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Extbase\Configuration\ConfigurationManager; -use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface; -use TYPO3\CMS\Extbase\Configuration\Exception\InvalidConfigurationTypeException; -use TYPO3\CMS\Extbase\Object\ObjectManagerInterface; -use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings; +use TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException; use TYPO3\CMS\Extbase\Persistence\QueryInterface; use TYPO3\CMS\Extbase\Persistence\QueryResultInterface; use TYPO3\CMS\Extbase\Persistence\QueryResultInterface as ExtbaseQueryResultInterface; @@ -54,7 +49,7 @@ class JobRepository extends Repository { * @param int $limit * @param int $offset * @return ExtbaseQueryResultInterface|object[] - * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException + * @throws InvalidQueryException */ public function findBackendJobs(int $recordPageId, array $filters = [], int $limit = 0, int $offset = 0) { $query = $this->createQuery(); @@ -87,7 +82,7 @@ class JobRepository extends Repository { } if (\count($constraints) > 1) { - return $query->matching($query->logicalAnd($constraints))->execute(); + return $query->matching($query->logicalAnd(...$constraints))->execute(); } if (\count($constraints) > 0) { @@ -121,6 +116,7 @@ class JobRepository extends Repository { // if no record storage page has been selected in the plugin, ignore it $querySettings->setRespectStoragePage(FALSE); } + $this->setDefaultQuerySettings($querySettings); $constraints = []; @@ -132,13 +128,14 @@ class JobRepository extends Repository { $companyConstraints[] = $query->equals('uid', $jobId); } } + if (\count($companyConstraints)) { - $constraints[] = $query->logicalOr($companyConstraints); + $constraints[] = $query->logicalOr(...$companyConstraints); } } if (\count($constraints)) { - $query->matching($query->logicalAnd($constraints)); + $query->matching($query->logicalAnd(...$constraints)); } if ($limit > 0) { @@ -159,6 +156,7 @@ class JobRepository extends Repository { * @param int $limit * @param int $offset * @param int $ordering + * @param array $explicitFilters * @return ExtbaseQueryResultInterface */ public function findJobsByFilter( @@ -171,14 +169,6 @@ class JobRepository extends Repository { $query = $this->createQuery(); $storagePageIds = $query->getQuerySettings()->getStoragePageIds(); - // we always want to show all jobs if the strict mode is used (translated or - // created in the specific language w/o default) - $querySettings = $query->getQuerySettings(); - if ($querySettings->getLanguageOverlayMode() === 'hideNonTranslated') { - $querySettings->setLanguageOverlayMode(FALSE); - } - $query->setQuerySettings($querySettings); - if (empty($storagePageIds)) { // if no record storage page has been selected in the plugin, ignore it $query->getQuerySettings()->setRespectStoragePage(FALSE); @@ -214,10 +204,10 @@ class JobRepository extends Repository { } if (isset($filters['filterRemote']) && $filters['filterRemote'] !== '') { - $constraints[] = $query->logicalAnd([ + $constraints[] = $query->logicalAnd( $query->equals('telecommutePossible', TRUE), $query->equals('office_work_possible', FALSE) - ]); + ); } if (isset($filters['filterLocation']) && $filters['filterLocation'] !== '0') { @@ -229,8 +219,9 @@ class JobRepository extends Repository { foreach ($filters['filterByLocation'] as $companyFilter) { $companyConstraints[] = $query->equals('company.uid', $companyFilter); } + if (\count($companyConstraints) > 0) { - $constraints[] = $query->logicalOr($companyConstraints); + $constraints[] = $query->logicalOr(...$companyConstraints); } } @@ -241,8 +232,9 @@ class JobRepository extends Repository { foreach ($filters['filterByDepartment'] as $departmentFilter) { $departmentConstraints[] = $query->equals('department', $departmentFilter); } + if (\count($departmentConstraints) > 0) { - $constraints[] = $query->logicalOr($departmentConstraints); + $constraints[] = $query->logicalOr(...$departmentConstraints); } } @@ -253,13 +245,14 @@ class JobRepository extends Repository { foreach ($filters['filterByExperienceLevel'] as $experienceFilter) { $experienceConstraints[] = $query->equals('experienceLevel', $experienceFilter); } + if (\count($experienceConstraints) > 0) { - $constraints[] = $query->logicalOr($experienceConstraints); + $constraints[] = $query->logicalOr(...$experienceConstraints); } } if (\count($constraints)) { - $query->matching($query->logicalAnd($constraints)); + $query->matching($query->logicalAnd(...$constraints)); } if ($limit > 0) { @@ -331,6 +324,7 @@ class JobRepository extends Repository { // if no record storage page has been selected in the plugin, ignore it $query->getQuerySettings()->setRespectStoragePage(FALSE); } + $company = $job->getCompany(); $department = $job->getDepartment(); @@ -356,7 +350,7 @@ class JobRepository extends Repository { } if (\count($constraints)) { - $query->matching($query->logicalAnd($constraints)); + $query->matching($query->logicalAnd(...$constraints)); } return $query; @@ -379,7 +373,7 @@ class JobRepository extends Repository { if (count($filters) > 0) { $constraints = $this->getFilterConstraints($query, $filters); - $query->matching($query->logicalAnd($constraints)); + $query->matching($query->logicalAnd(...$constraints)); } return $query->execute()->count(); @@ -403,7 +397,7 @@ class JobRepository extends Repository { if (count($filters) > 0) { $constraints = $this->getFilterConstraints($query, $filters); - $query->matching($query->logicalAnd($constraints)); + $query->matching($query->logicalAnd(...$constraints)); } $query->setOrderings(['featured_offer' => QueryInterface::ORDER_DESCENDING]); @@ -426,6 +420,7 @@ class JobRepository extends Repository { foreach ($filters['filterByLocation'] as $companyFilter) { $companyConstraints[] = $query->equals('company.uid', $companyFilter); } + if (\count($companyConstraints) > 0) { $constraints[] = $query->logicalOr($companyConstraints); } @@ -436,6 +431,7 @@ class JobRepository extends Repository { foreach ($filters['filterByDepartment'] as $departmentFilter) { $departmentConstraints[] = $query->equals('department', $departmentFilter); } + if (\count($departmentConstraints) > 0) { $constraints[] = $query->logicalOr($departmentConstraints); } @@ -446,6 +442,7 @@ class JobRepository extends Repository { foreach ($filters['filterByExperienceLevel'] as $experienceFilter) { $experienceConstraints[] = $query->equals('experienceLevel', $experienceFilter); } + if (\count($experienceConstraints) > 0) { $constraints[] = $query->logicalOr($experienceConstraints); } diff --git a/Classes/Event/Listener/AccessPageListEventListener.php b/Classes/Event/Listener/AccessPageListEventListener.php index 0cddb17e..e14d24fd 100644 --- a/Classes/Event/Listener/AccessPageListEventListener.php +++ b/Classes/Event/Listener/AccessPageListEventListener.php @@ -28,6 +28,7 @@ namespace SGalinski\SgJobs\Event\Listener; use SGalinski\SgJobs\Service\SitemapService; use SGalinski\SgSeo\Events\AccessPageListEvent; +use TYPO3\CMS\Core\Context\Exception\AspectNotFoundException; use TYPO3\CMS\Core\Utility\ArrayUtility; /** @@ -52,6 +53,7 @@ class AccessPageListEventListener { /** * @param AccessPageListEvent $event + * @throws AspectNotFoundException */ public function __invoke(AccessPageListEvent $event) { $pageList = $event->getPageList(); diff --git a/Classes/Pagination/Pagination.php b/Classes/Pagination/Pagination.php index a53d3bda..07e191d7 100644 --- a/Classes/Pagination/Pagination.php +++ b/Classes/Pagination/Pagination.php @@ -100,8 +100,6 @@ class Pagination { * Reconfigure the query builder to fetch the total count of items * * @return int - * @throws \Doctrine\DBAL\DBALException - * @throws \Doctrine\DBAL\Driver\Exception */ private function fetchTotalItemCount(): int { $query = clone $this->queryResult->getQuery(); @@ -113,8 +111,6 @@ class Pagination { * Reconfigure the queryResult to fetch the items for the configured currentPage * * @return array - * @throws \Doctrine\DBAL\DBALException - * @throws \Doctrine\DBAL\Driver\Exception */ private function fetchItems(): array { $query = clone $this->queryResult->getQuery(); diff --git a/Classes/Service/BackendService.php b/Classes/Service/BackendService.php index 26d4f3cd..929b537e 100644 --- a/Classes/Service/BackendService.php +++ b/Classes/Service/BackendService.php @@ -26,6 +26,7 @@ namespace SGalinski\SgJobs\Service; +use Doctrine\DBAL\Exception; use TYPO3\CMS\Backend\Template\Components\ButtonBar; use TYPO3\CMS\Backend\Template\Components\DocHeaderComponent; use TYPO3\CMS\Backend\Utility\BackendUtility; @@ -45,7 +46,7 @@ class BackendService { * Get all pages the be user has access to * * @return array - * @throws \InvalidArgumentException + * @throws Exception */ public static function getPages(): array { $out = []; @@ -55,7 +56,7 @@ class BackendService { ->from('pages') ->where( $queryBuilder->expr()->eq('is_siteroot', $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT)) - )->execute()->fetchAll(); + )->executeQuery()->fetchAllAssociative(); foreach ($rows as $row) { $pageInfo = BackendUtility::readPageAccess($row['uid'], $GLOBALS['BE_USER']->getPagePermsClause(1)); @@ -66,10 +67,12 @@ class BackendService { foreach ($rootline as $page) { $path .= '/p' . dechex($page['uid']); } + $pageInfo['path'] = $path; $out[] = $pageInfo; } } + return $out; } @@ -101,24 +104,22 @@ class BackendService { // shortcut button $shortcutButton = $buttonBar->makeShortcutButton() - ->setModuleName($request->getPluginName()) - ->setGetVariables( + ->setRouteIdentifier($request->getPluginName()) + ->setArguments( [ - 'id', - 'M' + 'id' => [], + 'M' => [] ] - ) - ->setSetVariables([]); + ); $buttonBar->addButton($shortcutButton, ButtonBar::BUTTON_POSITION_RIGHT); - $docHeaderComponent->getButtonBar(); } /** * Returns the uids of the pages with job records * * @return array - * @throws \InvalidArgumentException + * @throws Exception */ public static function getPagesWithJobRecords(): array { $out = []; @@ -129,7 +130,7 @@ class BackendService { $rows = $queryBuilder->select('pid') ->from('tx_sgjobs_domain_model_job') ->groupBy('pid') - ->execute()->fetchAll(); + ->executeQuery()->fetchAllAssociative(); foreach ($rows as $row) { $pageInfo = BackendUtility::readPageAccess($row['pid'], $GLOBALS['BE_USER']->getPagePermsClause(1)); if ($pageInfo) { @@ -139,10 +140,12 @@ class BackendService { foreach ($rootline as $page) { $path .= '/p' . dechex($page['uid']); } + $pageInfo['path'] = $path; $out[] = $pageInfo; } } + return $out; } } diff --git a/Classes/Service/FileAndFolderService.php b/Classes/Service/FileAndFolderService.php index b60db5d5..834fde4b 100644 --- a/Classes/Service/FileAndFolderService.php +++ b/Classes/Service/FileAndFolderService.php @@ -28,6 +28,9 @@ namespace SGalinski\SgJobs\Service; use TYPO3\CMS\Core\Charset\CharsetConverter; use TYPO3\CMS\Core\Core\Environment; +use TYPO3\CMS\Core\Resource\Exception\ExistingTargetFolderException; +use TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException; +use TYPO3\CMS\Core\Resource\Exception\InsufficientFolderWritePermissionsException; use TYPO3\CMS\Core\Resource\File as FalFile; use TYPO3\CMS\Core\Resource\FileReference as FalFileReference; use TYPO3\CMS\Core\Resource\Folder; @@ -39,28 +42,12 @@ use TYPO3\CMS\Core\SingletonInterface; use TYPO3\CMS\Core\Utility\File\BasicFileUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Domain\Model\FileReference; -use TYPO3\CMS\Extbase\Object\ObjectManagerInterface; use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager; /** * Service for diverse file operations */ class FileAndFolderService implements SingletonInterface { - /** - * - * @var ObjectManagerInterface - */ - protected $objectManager; - - /** - * Inject the ObjectManager - * - * @param ObjectManagerInterface $objectManager - */ - public function injectObjectManager(ObjectManagerInterface $objectManager) { - $this->objectManager = $objectManager; - } - /** * * @var BasicFileUtility @@ -186,15 +173,13 @@ class FileAndFolderService implements SingletonInterface { * @param int $storageUid * @return Folder * @throws \InvalidArgumentException - * @throws \TYPO3\CMS\Core\Resource\Exception\InsufficientFolderWritePermissionsException - * @throws \TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException - * @throws \TYPO3\CMS\Core\Resource\Exception\ExistingTargetFolderException + * @throws InsufficientFolderWritePermissionsException + * @throws InsufficientFolderAccessPermissionsException + * @throws ExistingTargetFolderException * @throws \Exception */ protected function createFolder($folderIdentifier, $storageUid): Folder { - /** @var ResourceStorage $storage */ - $storage = $this->getStorage($storageUid); - return $storage->createFolder($folderIdentifier); + return $this->getStorage($storageUid)->createFolder($folderIdentifier); } /** @@ -235,7 +220,7 @@ class FileAndFolderService implements SingletonInterface { continue; } - if ($fileTypes !== '' && \substr($fileTypes, -1) !== ',') { + if ($fileTypes !== '' && !str_ends_with($fileTypes, ',')) { $fileTypes .= ','; } @@ -265,14 +250,13 @@ class FileAndFolderService implements SingletonInterface { * * @param string $folderIdentifier * @return Folder - * @throws \TYPO3\CMS\Core\Resource\Exception\InsufficientFolderWritePermissionsException + * @throws InsufficientFolderWritePermissionsException * @throws \InvalidArgumentException * @throws \Exception - * @throws \TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException - * @throws \TYPO3\CMS\Core\Resource\Exception\ExistingTargetFolderException + * @throws InsufficientFolderAccessPermissionsException + * @throws ExistingTargetFolderException */ public function getFolder($folderIdentifier): Folder { - /** @var ResourceStorage $storage */ $storage = $this->getStorage(); if ($storage->hasFolder($folderIdentifier)) { @@ -363,12 +347,11 @@ EOT; ): FileReference { if ($resourcePointer === NULL) { /** @var FileReference $fileReference */ - $fileReference = $this->objectManager->get(FileReference::class); + $fileReference = GeneralUtility::makeInstance(FileReference::class); } else { $fileReference = $this->persistenceManager->getObjectByIdentifier( $resourcePointer, - FileReference::class, - FALSE + FileReference::class ); } diff --git a/Classes/Service/SitemapService.php b/Classes/Service/SitemapService.php index afd49f7a..82e3c1e3 100644 --- a/Classes/Service/SitemapService.php +++ b/Classes/Service/SitemapService.php @@ -26,10 +26,13 @@ namespace SGalinski\SgJobs\Service; +use Doctrine\DBAL\Exception; use TYPO3\CMS\Core\Context\Context; +use TYPO3\CMS\Core\Context\Exception\AspectNotFoundException; use TYPO3\CMS\Core\Context\LanguageAspect; use TYPO3\CMS\Core\Database\Connection; use TYPO3\CMS\Core\Database\ConnectionPool; +use TYPO3\CMS\Core\Domain\Repository\PageRepository; use TYPO3\CMS\Core\Exception\SiteNotFoundException; use TYPO3\CMS\Core\Site\SiteFinder; use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; @@ -52,7 +55,8 @@ class SitemapService { * @param int $sysLanguageUid * @param int $rootPageId * @return array - * @throws \TYPO3\CMS\Core\Context\Exception\AspectNotFoundException + * @throws Exception + * @throws AspectNotFoundException */ public function generatePagesList(int $sysLanguageUid, int $rootPageId = 0): array { $pageList = []; @@ -69,13 +73,13 @@ class SitemapService { AND pages.no_search = 0' ) ->where( - $queryBuilder->expr()->andX( + $queryBuilder->expr()->and( $queryBuilder->expr()->eq('CType', $queryBuilder->createNamedParameter('list')), $queryBuilder->expr()->eq( 'list_type', $queryBuilder->createNamedParameter(self::PLUGIN_NAME) ), - $queryBuilder->expr()->orX( + $queryBuilder->expr()->or( $queryBuilder->expr()->eq('tt_content.sys_language_uid', -1), $queryBuilder->expr()->eq( 'tt_content.sys_language_uid', @@ -84,15 +88,16 @@ class SitemapService { ) ) ) - ->execute(); + ->executeQuery(); $context = GeneralUtility::makeInstance(Context::class); - while ($row = $databaseResource->fetch()) { + while ($row = $databaseResource->fetchAssociative()) { try { $site = GeneralUtility::makeInstance(SiteFinder::class)->getSiteByPageId($row['pid']); if ($rootPageId > 0 && $site->getRootPageId() !== $rootPageId) { continue; } + $jobs = $this->getJobsByPid($row['pages'], $sysLanguageUid); foreach ($jobs as $job) { $url = $site->getRouter($context)->generateUri( @@ -114,6 +119,7 @@ class SitemapService { // No site configuration for the page found } } + return $pageList; } @@ -123,6 +129,8 @@ class SitemapService { * @param string $pageList * @param int $sysLanguageUid * @return array|null + * @throws AspectNotFoundException + * @throws Exception */ private function getJobsByPid(string $pageList, int $sysLanguageUid): ?array { $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) @@ -130,31 +138,33 @@ class SitemapService { $databaseResource = $queryBuilder->select('*') ->from('tx_sgjobs_domain_model_job') ->where( - $queryBuilder->expr()->andX( + $queryBuilder->expr()->and( $queryBuilder->expr()->in('pid', $queryBuilder->createNamedParameter($pageList)), $queryBuilder->expr()->in('sys_language_uid', '-1,0') ) ) - ->execute(); + ->executeQuery(); $visibleRows = []; - $rows = $databaseResource->fetchAll(); - $pageRepository = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Domain\Repository\PageRepository::class); + $rows = $databaseResource->fetchAllAssociative(); + /** @var PageRepository $pageRepository */ + $pageRepository = GeneralUtility::makeInstance(PageRepository::class); $isLanguageVisibilityLoaded = ExtensionManagementUtility::isLoaded('languagevisibility'); $languageAspect = GeneralUtility::makeInstance(Context::class)->getAspect('language'); $overlayType = $languageAspect->getLegacyOverlayType(); + $frontendServices = GeneralUtility::makeInstance(FrontendServices::class); foreach ($rows as $row) { $table = 'tx_sgjobs_domain_model_job'; // get languagevisibility uid that is available (check for the correct uid to fall back to) if ($isLanguageVisibilityLoaded) { try { - $element = FrontendServices::getElement($row, $table); + $element = $frontendServices->getElement($row, $table); } catch (TableNotSupportedException $exception) { continue; } - $languageId = FrontendServices::getOverlayLanguageIdForElement($element, $sysLanguageUid); + $languageId = $frontendServices->getOverlayLanguageIdForElement($element, $sysLanguageUid); if ($languageId === FALSE) { continue; } @@ -164,7 +174,7 @@ class SitemapService { if ($languageId > 0) { /** @var LanguageAspect $languageAspect */ - $row = $pageRepository->getRecordOverlay($table, $row, $languageId, $overlayType); + $row = $pageRepository->getLanguageOverlay($table, $row, $languageId, $overlayType); if (!is_array($row) || !count($row)) { continue; } diff --git a/Classes/ViewHelpers/Backend/ControlViewHelper.php b/Classes/ViewHelpers/Backend/ControlViewHelper.php index ee242d31..73f3dd78 100644 --- a/Classes/ViewHelpers/Backend/ControlViewHelper.php +++ b/Classes/ViewHelpers/Backend/ControlViewHelper.php @@ -28,9 +28,11 @@ namespace SGalinski\SgJobs\ViewHelpers\Backend; use SGalinski\SgJobs\Domain\Model\Job; use TYPO3\CMS\Backend\Utility\BackendUtility; +use TYPO3\CMS\Core\Localization\LanguageService; use TYPO3\CMS\Core\Page\PageRenderer; +use TYPO3\CMS\Core\Type\Bitmask\Permission; use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Recordlist\RecordList\DatabaseRecordList; +use TYPO3\CMS\Backend\RecordList\DatabaseRecordList; use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper; /** @@ -64,17 +66,14 @@ class ControlViewHelper extends AbstractViewHelper { $databaseRecordList = GeneralUtility::makeInstance(DatabaseRecordList::class); $pageInfo = BackendUtility::readPageAccess($row['pid'], $GLOBALS['BE_USER']->getPagePermsClause(1)); - if (version_compare(\TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) { - $databaseRecordList->calcPerms = $GLOBALS['BE_USER']->calcPerms($pageInfo); - } else { - $databaseRecordList->calcPerms = new \TYPO3\CMS\Core\Type\Bitmask\Permission( - $GLOBALS['BE_USER']->calcPerms($pageInfo) - ); - } + $databaseRecordList->calcPerms = new Permission( + $GLOBALS['BE_USER']->calcPerms($pageInfo) + ); + /** @var PageRenderer $pageRenderer */ $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class); - $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/AjaxDataHandler'); + $pageRenderer->loadJavaScriptModule('@typo3/backend/AjaxDataHandler.js'); $pageRenderer->addInlineLanguageLabelFile('EXT:backend/Resources/Private/Language/locallang_alt_doc.xlf'); - $languageService = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Localization\LanguageService::class); + $languageService = GeneralUtility::makeInstance(LanguageService::class); $languageService->includeLLFile('EXT:backend/Resources/Private/Language/locallang_alt_doc.xlf'); // DatabaseRecordList has a $prevPrevUid, which might track back a page. We wont do that, 1st+last record are always @@ -85,9 +84,11 @@ class ControlViewHelper extends AbstractViewHelper { if (!$iterator['isFirst'] && $iterator['index'] !== 1) { $uidPrev = '-' . $this->arguments['allItems'][$iterator['index'] - 2]['uid']; } + if ($iterator['index'] === 1) { $uidPrev = $row['pid']; } + if (!$iterator['isLast']) { $uidNext = '-' . $this->arguments['allItems'][$iterator['index'] + 1]['uid']; } @@ -107,6 +108,7 @@ class ControlViewHelper extends AbstractViewHelper { ] ]; } + if (!$uidNext) { $newCurrentTableArr = [ 'prev' => [ @@ -114,6 +116,7 @@ class ControlViewHelper extends AbstractViewHelper { ] ]; } + $databaseRecordList->id = $row['pid']; $databaseRecordList->currentTable = $newCurrentTableArr; diff --git a/Classes/ViewHelpers/Form/UploadViewHelper.php b/Classes/ViewHelpers/Form/UploadViewHelper.php index 7a911134..59e8e998 100644 --- a/Classes/ViewHelpers/Form/UploadViewHelper.php +++ b/Classes/ViewHelpers/Form/UploadViewHelper.php @@ -30,11 +30,12 @@ namespace SGalinski\SgJobs\ViewHelpers\Form; use TYPO3\CMS\Extbase\Property\PropertyMapper; use TYPO3\CMS\Extbase\Security\Cryptography\HashService; +use TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper; /** * Class UploadViewHelper */ -class UploadViewHelper extends \TYPO3\CMS\Fluid\ViewHelpers\Form\UploadViewHelper { +class UploadViewHelper extends AbstractFormFieldViewHelper { /** * @var HashService * @@ -47,6 +48,11 @@ class UploadViewHelper extends \TYPO3\CMS\Fluid\ViewHelpers\Form\UploadViewHelpe */ protected $propertyMapper; + /** + * @var string + */ + protected $tagName = 'input'; + /** * Inject the HashService * @@ -68,8 +74,13 @@ class UploadViewHelper extends \TYPO3\CMS\Fluid\ViewHelpers\Form\UploadViewHelpe /** * Register the ViewHelper arguments */ - public function initializeArguments() { + public function initializeArguments(): void { parent::initializeArguments(); + $this->registerTagAttribute('disabled', 'string', 'Specifies that the input element should be disabled when the page loads'); + $this->registerTagAttribute('multiple', 'string', 'Specifies that the file input element should allow multiple selection of files'); + $this->registerTagAttribute('accept', 'string', 'Specifies the allowed file extensions to upload via comma-separated list, example ".png,.gif"'); + $this->registerArgument('errorClass', 'string', 'CSS class to set if there are errors for this ViewHelper', false, 'f3-form-error'); + $this->registerUniversalTagAttributes(); $this->registerArgument('resourceName', 'string', 'The name of the resource', FALSE, 'resource'); } @@ -93,7 +104,21 @@ class UploadViewHelper extends \TYPO3\CMS\Fluid\ViewHelpers\Form\UploadViewHelpe $output .= $this->renderChildren(); } - $output .= parent::render(); + $name = $this->getName(); + $allowedFields = ['name', 'type', 'tmp_name', 'error', 'size']; + foreach ($allowedFields as $fieldName) { + $this->registerFieldNameForFormTokenGeneration($name . '[' . $fieldName . ']'); + } + $this->tag->addAttribute('type', 'file'); + + if (isset($this->arguments['multiple'])) { + $this->tag->addAttribute('name', $name . '[]'); + } else { + $this->tag->addAttribute('name', $name); + } + + $this->setErrorClassAttribute(); + $output .= $this->tag->render(); return $output; } @@ -111,4 +136,5 @@ class UploadViewHelper extends \TYPO3\CMS\Fluid\ViewHelpers\Form\UploadViewHelpe $this->respectSubmittedDataValue = TRUE; return $this->getValueAttribute(); } + } diff --git a/Classes/ViewHelpers/Widget/UriViewHelper.php b/Classes/ViewHelpers/Widget/UriViewHelper.php deleted file mode 100644 index da68dc66..00000000 --- a/Classes/ViewHelpers/Widget/UriViewHelper.php +++ /dev/null @@ -1,161 +0,0 @@ -<?php - -/*************************************************************** - * 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! - ***************************************************************/ - -namespace SGalinski\SgJobs\ViewHelpers\Widget; - -use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext; -use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface; -use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper; -use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic; - -/** - * Class UriViewHelper - */ -class UriViewHelper extends AbstractViewHelper { - use CompileWithRenderStatic; - - /** - * @var boolean - */ - protected $escapeOutput = FALSE; - - /** - * @var boolean - */ - protected $escapeChildren = FALSE; - - /** - * Initialize arguments - */ - public function initializeArguments(): void { - $this->registerArgument('addQueryStringMethod', 'string', 'Method to be used for query string'); - $this->registerArgument('action', 'string', 'Target action'); - $this->registerArgument('arguments', 'array', 'Arguments', FALSE, []); - $this->registerArgument('section', 'string', 'The anchor to be added to the URI', FALSE, ''); - $this->registerArgument('format', 'string', 'The requested format, e.g. ".html', FALSE, ''); - $this->registerArgument( - 'ajax', - 'bool', - 'TRUE if the URI should be to an AJAX widget, FALSE otherwise.', - FALSE, - FALSE - ); - } - - /** - * @param array $arguments - * @param \Closure $renderChildrenClosure - * @param RenderingContextInterface $renderingContext - * @return string - */ - public static function renderStatic( - array $arguments, - \Closure $renderChildrenClosure, - RenderingContextInterface $renderingContext - ): string { - $ajax = $arguments['ajax']; - if ($ajax === TRUE) { - return static::getAjaxUri($renderingContext, $arguments); - } - return static::getWidgetUri($renderingContext, $arguments); - } - - /** - * Render the Uri. - * - * @return string The rendered link - * @api - */ - public function render(): string { - $ajax = $this->arguments['ajax']; - - if ($ajax === TRUE) { - return static::getAjaxUri($this->renderingContext, $this->arguments); - } - return static::getWidgetUri($this->renderingContext, $this->arguments); - } - - /** - * Get the URI for an AJAX Request. - * - * @param RenderingContextInterface $renderingContext - * @param array $arguments - * @return string the AJAX URI - */ - protected static function getAjaxUri(RenderingContextInterface $renderingContext, array $arguments): string { - /** @var ControllerContext $controllerContext */ - $controllerContext = $renderingContext->getControllerContext(); - $action = $arguments['action']; - $arguments = $arguments['arguments']; - if ($action === NULL) { - $action = $controllerContext->getRequest()->getControllerActionName(); - } - - $arguments['id'] = $GLOBALS['TSFE']->id; - // @todo page type should be configurable - $arguments['type'] = 7076; - $arguments['fluid-widget-id'] = $controllerContext->getRequest()->getWidgetContext()->getAjaxWidgetIdentifier(); - $arguments['action'] = $action; - return '?' . http_build_query($arguments, NULL, '&'); - } - - /** - * Get the URI for a non-AJAX Request. - * - * @param RenderingContextInterface $renderingContext - * @param array $arguments - * @return string the Widget URI - */ - protected static function getWidgetUri(RenderingContextInterface $renderingContext, array $arguments): string { - /** @var ControllerContext $controllerContext */ - $controllerContext = $renderingContext->getControllerContext(); - $uriBuilder = $controllerContext->getUriBuilder(); - $argumentPrefix = $controllerContext->getRequest()->getArgumentPrefix(); - $parentNamespace = $controllerContext->getRequest()->getWidgetContext()->getParentPluginNamespace(); - $parentArguments = GeneralUtility::_GP($parentNamespace); - $allArguments = [$argumentPrefix => $arguments['arguments']] ?? []; - if ($parentArguments && isset($parentArguments['filters'])) { - $allArguments[$parentNamespace . '[filters]'] = $parentArguments['filters']; - } - - if ($arguments['action'] ?? FALSE) { - $allArguments[$argumentPrefix]['action'] = $arguments['action']; - } - - if (($arguments['format'] ?? '') !== '') { - $allArguments[$argumentPrefix]['format'] = $arguments['format']; - } - - return $uriBuilder->reset() - ->setArguments($allArguments) - ->setSection($arguments['section']) - ->setAddQueryString(TRUE) - ->setArgumentsToBeExcludedFromQueryString([$argumentPrefix, 'cHash']) - ->setFormat($arguments['format']) - ->build(); - } -} diff --git a/ext_localconf.php b/ext_localconf.php index c3fe89a8..430d0553 100644 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -76,18 +76,5 @@ call_user_func( ); $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['languagevisibility']['recordElementSupportedTables']['tx_sgjobs_domain_model_job'] = []; - - // register icons for TYPO3 10 compatibility - if (version_compare(\TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) { - $iconRegistry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance( - \TYPO3\CMS\Core\Imaging\IconRegistry::class - ); - - $iconRegistry->registerIcon( - 'extension-sg_jobs-module', - \TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider::class, - ['source' => 'EXT:sg_jobs/Resources/Public/Icons/module-sgjobs.svg'] - ); - } } ); -- GitLab