From 0cb139efb52a48181273be44ad3dd69aaee9439e Mon Sep 17 00:00:00 2001 From: Benjamin Jasper Date: Wed, 8 Dec 2021 14:14:42 +0100 Subject: [PATCH 01/61] build: added phpstan --- .github/workflows/static-analysis.yaml | 25 +- Classes/Controller/ApplicationController.php | 16 +- Classes/Utility/Mail/MailFluid.php | 6 +- Classes/Utility/Mail/MailInterface.php | 6 +- Classes/Utility/Mail/MailMessage.php | 12 +- baseline.xml | 490 ------------------- psalm.xml | 148 ------ 7 files changed, 39 insertions(+), 664 deletions(-) delete mode 100644 baseline.xml delete mode 100644 psalm.xml diff --git a/.github/workflows/static-analysis.yaml b/.github/workflows/static-analysis.yaml index e9afff1..24611ab 100644 --- a/.github/workflows/static-analysis.yaml +++ b/.github/workflows/static-analysis.yaml @@ -3,12 +3,25 @@ name: Static analysis on: [ push, pull_request ] jobs: - psalm: - name: Running Psalm + phpstan: runs-on: ubuntu-latest steps: - - name: Checkout code - uses: actions/checkout@v2 + - uses: actions/checkout@v2 - - name: Psalm - uses: docker://vimeo/psalm-github-actions \ No newline at end of file + - id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - uses: actions/cache@v1 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-composer- + - uses: shivammathur/setup-php@v1 + with: + php-version: 7.3 + coverage: none + + - run: composer install --no-progress + + - run: composer phpstan \ No newline at end of file diff --git a/Classes/Controller/ApplicationController.php b/Classes/Controller/ApplicationController.php index 2579230..6f803d1 100644 --- a/Classes/Controller/ApplicationController.php +++ b/Classes/Controller/ApplicationController.php @@ -421,8 +421,8 @@ public function createAction(\ITX\Jobapplications\Domain\Model\Application $newA // Prepare and send the message $mail - ->setSubject(LocalizationUtility::translate("fe.email.toContactSubject", 'jobapplications', [0 => $currentPosting->getTitle()])) - ->setFrom([$this->settings["emailSender"] => $this->settings["emailSenderName"]]) + ->addSubject(LocalizationUtility::translate("fe.email.toContactSubject", 'jobapplications', [0 => $currentPosting->getTitle()])) + ->from([$this->settings["emailSender"] => $this->settings["emailSenderName"]]) ->setReply([$newApplication->getEmail() => $newApplication->getFirstName()." ".$newApplication->getLastName()]) ->setContent('

'. $nameLabel.$salutation.' '.$newApplication->getFirstName().' '.$newApplication->getLastName().'
'. @@ -455,16 +455,16 @@ public function createAction(\ITX\Jobapplications\Domain\Model\Application $newA //Figure out who the email will be sent to and how if ($this->settings['sendEmailToInternal'] != "" && $this->settings['sendEmailToContact'] == "1") { - $mail->setTo([$contact->getEmail() => $contact->getFirstName().' '.$contact->getLastName()]); + $mail->to([$contact->getEmail() => $contact->getFirstName().' '.$contact->getLastName()]); $mail->setBlindcopies([$this->settings['sendEmailToInternal']]); } else if ($this->settings['sendEmailToContact'] != "1" && $this->settings['sendEmailToInternal'] != "") { - $mail->setTo([$this->settings['sendEmailToInternal'] => 'Internal']); + $mail->to([$this->settings['sendEmailToInternal'] => 'Internal']); } else if ($this->settings['sendEmailToContact'] == "1" && $this->settings['sendEmailToInternal'] != "1") { - $mail->setTo([$contact->getEmail() => $contact->getFirstName()." ".$contact->getLastName()]); + $mail->to([$contact->getEmail() => $contact->getFirstName()." ".$contact->getLastName()]); } try @@ -521,9 +521,9 @@ public function createAction(\ITX\Jobapplications\Domain\Model\Application $newA $body = str_replace("%postingTitle%", $currentPosting->getTitle(), $body); $mail - ->setSubject($subject) - ->setFrom([$this->settings["emailSender"] => $this->settings["emailSenderName"]]) - ->setTo([$newApplication->getEmail() => $newApplication->getFirstName()." ".$newApplication->getLastName()]) + ->addSubject($subject) + ->from([$this->settings["emailSender"] => $this->settings["emailSenderName"]]) + ->to([$newApplication->getEmail() => $newApplication->getFirstName()." ".$newApplication->getLastName()]) ->setContent($body, ['application' => $newApplication, 'settings' => $this->settings]); try diff --git a/Classes/Utility/Mail/MailFluid.php b/Classes/Utility/Mail/MailFluid.php index 9bf2786..475f370 100644 --- a/Classes/Utility/Mail/MailFluid.php +++ b/Classes/Utility/Mail/MailFluid.php @@ -91,7 +91,7 @@ private function addressArrayToObject($key, $address): Address /** * @inheritDoc */ - public function setSubject(string $subject): MailInterface + public function addSubject(string $subject): MailInterface { return $this->subject($subject); } @@ -163,7 +163,7 @@ public function setBlindcopies(array $addresses): MailInterface /** * @inheritDoc */ - public function setTo(array $addresses, string $name = ''): MailInterface + public function to(array $addresses, string $name = ''): MailInterface { foreach ($addresses as $key => $address) { @@ -178,7 +178,7 @@ public function setTo(array $addresses, string $name = ''): MailInterface /** * @inheritDoc */ - public function setFrom(array $addresses, $name = ''): MailInterface + public function from(array $addresses, $name = ''): MailInterface { foreach ($addresses as $key => $address) { diff --git a/Classes/Utility/Mail/MailInterface.php b/Classes/Utility/Mail/MailInterface.php index 8b0a62b..24139cc 100644 --- a/Classes/Utility/Mail/MailInterface.php +++ b/Classes/Utility/Mail/MailInterface.php @@ -46,7 +46,7 @@ interface MailInterface * * @return MailInterface */ - public function setTo(array $addresses, string $name = ''): MailInterface; + public function to(array $addresses, string $name = ''): MailInterface; /** * @param array $addresses @@ -68,7 +68,7 @@ public function setBlindcopies(array $addresses): MailInterface; * * @return MailInterface */ - public function setSubject(string $subject): MailInterface; + public function addSubject(string $subject): MailInterface; /** * @param array $addresses @@ -76,7 +76,7 @@ public function setSubject(string $subject): MailInterface; * * @return MailInterface */ - public function setFrom(array $addresses, $name = ''): MailInterface; + public function from(array $addresses, $name = ''): MailInterface; /** * @param array $addresses diff --git a/Classes/Utility/Mail/MailMessage.php b/Classes/Utility/Mail/MailMessage.php index 02dbdb3..93821b9 100644 --- a/Classes/Utility/Mail/MailMessage.php +++ b/Classes/Utility/Mail/MailMessage.php @@ -57,9 +57,9 @@ public function setRecipient(array $addresses, string $name = ''): MailInterface * * @return \TYPO3\CMS\Core\Mail\MailMessage */ - public function setTo($addresses, $name = ''): MailInterface + public function to($addresses, $name = ''): MailInterface { - parent::setTo($addresses, $name); + $this->setTo($addresses, $name); return $this; } @@ -77,9 +77,9 @@ public function setTo($addresses, $name = ''): MailInterface * * @return \TYPO3\CMS\Core\Mail\MailMessage */ - public function setFrom($addresses, $name = ''): MailInterface + public function from($addresses, $name = ''): MailInterface { - parent::setFrom($addresses, $name); + $this->setFrom($addresses, $name); return $this; } @@ -149,9 +149,9 @@ public function setContentType($contentType): MailInterface * * @return $this */ - public function setSubject($subject): MailInterface + public function addSubject($subject): MailInterface { - parent::setSubject($subject); + $this->setSubject($subject); return $this; } diff --git a/baseline.xml b/baseline.xml deleted file mode 100644 index 88ae74e..0000000 --- a/baseline.xml +++ /dev/null @@ -1,490 +0,0 @@ - - - - - $body - $body - - - new HtmlResponse('') - new HtmlResponse('') - - - getBody - getClientFilename - getError - getSize - new HtmlResponse('') - new HtmlResponse('') - withStatus - - - $file->getClientFilename() - - - pathinfo($file->getClientFilename())['extension'] - - - - - getArgument - getPid - getUid - getUid - - - public function initializeCreateAction(): void - - - $newApplication->getPid() - $newApplication->getUid() - $salutation - LocalizationUtility::translate("date_format", "jobapplications") - LocalizationUtility::translate("fe.application.unsolicited.title", "jobapplications") - - - null - - - $posting - - - getUid - - - $newStorageUid - - - - - $newStatus - - - getUid - getUid - getUid - getUid - - - $pid - $this->request->getArgument('application') - $this->request->getArgument('status') - $this->request->getArgument('statusChange') - - - $language - - - $language - - - $contact->getUid() - - - null - null - null - null - - - - - public function listAction() - - - null - - - - - new ImmediateResponseException($response, 1599638331) - - - new ImmediateResponseException($response, 1599638331) - setArgument - - - public function initializeShowAction() - - - toArray - - - null - null - - - Posting - - - $this->locationRepository->findAll($categories) - - - - - 0 - - - $posting - null - null - null - null - null - null - null - null - - - \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\FileReference> - \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\FileReference> - \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\FileReference> - \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\FileReference> - \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\FileReference> - protected $coverLetter = null; - protected $cv = null; - protected $files = null; - protected $otherFiles = null; - protected $testimonials = null; - - - - - $this->_localizedUid - - - \TYPO3\CMS\Extbase\Domain\Model\BackendUser - - - null - - - null - null - - - TYPO3_MODE - - - - - $this->address - - - - - $baseSalary - 0 - - - null - null - null - null - null - null - - - \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\Category> - \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\Category> - \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\Category> - protected $categories = null; - - - - - null - - - \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\ITX\Jobapplications\Domain\Model\Status> - protected $followers = null; - - - - - QueryResultInterface|array - - - QueryResultInterface|array - - - execute - setOrderings - - - - - $query->execute() - - - QueryResultInterface|array - - - toArray - - - QueryResultInterface|array - - - - - QueryResultInterface|array - - - $query->execute() - - - QueryResultInterface|array - - - QueryResultInterface|array - - - - - getName - getProperties - - - $categories - $categories - $categories - $categories - $categories - $categories - - - statement - statement - statement - statement - statement - - - - - getStatementArray - importStaticData - - - getFirst - - - statement - statement - statement - - - - - map - - - - - getUid - - - $folder - - - - - \TYPO3\CMS\Scheduler\Task\AbstractTask - - - - - \TYPO3\CMS\Scheduler\Task\AbstractTask - - - - - \TYPO3\CMS\Scheduler\AbstractAdditionalFieldProvider - - - - - - $argument - $key - - - - - getUid - - - getFirst - - - count($categories) === 0 - count($categories) === 0 - - - $this->suppressFlashMessages - - - $token - - - - - $contents - - - - - \TYPO3\CMS\Core\Mail\MailMessage - \TYPO3\CMS\Core\Mail\MailMessage - - - $addresses - $content - - - public function setFrom($addresses, $name = ''): MailInterface - public function setSubject($subject): MailInterface - public function setTo($addresses, $name = ''): MailInterface - - - \TYPO3\CMS\Core\Mail\MailMessage - \TYPO3\CMS\Core\Mail\MailMessage - - - $name - $name - - - $result !== 0 - - - \Swift_Attachment - - - parent::setContentType('text/html') - parent::setContentType('text/plain') - - - - - $version - $version - - - - - getClientFilename - getClientFilename - moveTo - moveTo - - - $files - - - $files - $files - - - $i > 0 - - - files - - - - - $categories - - - $iterationData - $iterationData - - - - - getUid - - - count - - - $posting->getUid() - - - - - $buttonLink - - - $buttonLink - - - - - count - - - - - \TYPO3\TestingFramework\Core\Unit\UnitTestCase - - - - - \TYPO3\TestingFramework\Core\Unit\UnitTestCase - - - - - \TYPO3\TestingFramework\Core\Unit\UnitTestCase - - - - - \TYPO3\TestingFramework\Core\Unit\UnitTestCase - - - - - \TYPO3\TestingFramework\Core\Unit\UnitTestCase - - - - - \TYPO3\TestingFramework\Core\Unit\UnitTestCase - - - - - \TYPO3\TestingFramework\Core\Unit\UnitTestCase - - - - - \TYPO3\TestingFramework\Core\Unit\UnitTestCase - - - - - $EM_CONF - - - $_EXTKEY - - - - - \ITX\Jobapplications\Task\AnonymizeApplications - \ITX\Jobapplications\Task\CleanUpApplications - \ITX\Jobapplications\Task\CleanUpApplicationsAdditionalFieldProvider - \ITX\Jobapplications\Task\CleanUpApplicationsAdditionalFieldProvider - - - - - TYPO3_MODE - - - diff --git a/psalm.xml b/psalm.xml deleted file mode 100644 index d2fafe0..0000000 --- a/psalm.xml +++ /dev/null @@ -1,148 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From 03f772c90d397f5eb126992587fff2fbaadcaa5f Mon Sep 17 00:00:00 2001 From: Benjamin Jasper Date: Wed, 8 Dec 2021 14:16:43 +0100 Subject: [PATCH 02/61] build: added phpstan --- .github/workflows/static-analysis.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/static-analysis.yaml b/.github/workflows/static-analysis.yaml index 24611ab..8b9c43e 100644 --- a/.github/workflows/static-analysis.yaml +++ b/.github/workflows/static-analysis.yaml @@ -24,4 +24,4 @@ jobs: - run: composer install --no-progress - - run: composer phpstan \ No newline at end of file + - run: vendor/bin/phpstan analyse \ No newline at end of file From 1d240935b0d64a3c54ed0916a2f7745b7f98a377 Mon Sep 17 00:00:00 2001 From: Benjamin Jasper Date: Wed, 8 Dec 2021 14:17:37 +0100 Subject: [PATCH 03/61] build: added phpstan --- .github/workflows/static-analysis.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/static-analysis.yaml b/.github/workflows/static-analysis.yaml index 8b9c43e..1ec5a60 100644 --- a/.github/workflows/static-analysis.yaml +++ b/.github/workflows/static-analysis.yaml @@ -17,7 +17,7 @@ jobs: key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} restore-keys: | ${{ runner.os }}-composer- - - uses: shivammathur/setup-php@v1 + - uses: shivammathur/setup-php@v2 with: php-version: 7.3 coverage: none From e151de5635da00c72a129be2c1b7fe22258771d6 Mon Sep 17 00:00:00 2001 From: Benjamin Jasper Date: Wed, 8 Dec 2021 14:20:20 +0100 Subject: [PATCH 04/61] build: added phpstan --- composer.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/composer.json b/composer.json index e443b6c..a5aed8f 100644 --- a/composer.json +++ b/composer.json @@ -26,6 +26,9 @@ "typo3/cms-core": "^9.5 || ^10.4", "fluidtypo3/vhs": "^6" }, + "require-dev": { + "phpstan/phpstan": "^1.2" + }, "extra": { "typo3/cms": { "extension-key": "jobapplications" From 3d048dea2f9e55bd30d9053687e377c936ed150d Mon Sep 17 00:00:00 2001 From: Benjamin Jasper Date: Wed, 8 Dec 2021 14:22:27 +0100 Subject: [PATCH 05/61] build: added phpstan --- .github/workflows/static-analysis.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/static-analysis.yaml b/.github/workflows/static-analysis.yaml index 1ec5a60..1a1aa94 100644 --- a/.github/workflows/static-analysis.yaml +++ b/.github/workflows/static-analysis.yaml @@ -24,4 +24,4 @@ jobs: - run: composer install --no-progress - - run: vendor/bin/phpstan analyse \ No newline at end of file + - run: vendor/bin/phpstan analyse Classes \ No newline at end of file From aac0c29b290036b024b4a931eedcc9c712c27894 Mon Sep 17 00:00:00 2001 From: Benjamin Jasper Date: Wed, 8 Dec 2021 14:34:06 +0100 Subject: [PATCH 06/61] fix: fixed a few issues --- Classes/Controller/PostingController.php | 1 + Classes/Domain/Model/Location.php | 12 ------------ composer.json | 1 + 3 files changed, 2 insertions(+), 12 deletions(-) diff --git a/Classes/Controller/PostingController.php b/Classes/Controller/PostingController.php index 46fca34..c8f776b 100644 --- a/Classes/Controller/PostingController.php +++ b/Classes/Controller/PostingController.php @@ -3,6 +3,7 @@ namespace ITX\Jobapplications\Controller; use ITX\Jobapplications\Domain\Model\Constraint; + use ITX\Jobapplications\Domain\Model\Posting; use ITX\Jobapplications\PageTitle\JobsPageTitleProvider; use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface; use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; diff --git a/Classes/Domain/Model/Location.php b/Classes/Domain/Model/Location.php index 05e26a7..2bb210a 100644 --- a/Classes/Domain/Model/Location.php +++ b/Classes/Domain/Model/Location.php @@ -177,18 +177,6 @@ public function setAddressCountry(string $addressCountry): void $this->addressCountry = $addressCountry; } - /** - * Sets the address - * - * @param string $address - * - * @return void - */ - public function setAddress($address) - { - $this->address = $address; - } - /** * Returns the latitude * diff --git a/composer.json b/composer.json index a5aed8f..34b7cc1 100644 --- a/composer.json +++ b/composer.json @@ -24,6 +24,7 @@ }, "require": { "typo3/cms-core": "^9.5 || ^10.4", + "typo3/cms-scheduler": "*", "fluidtypo3/vhs": "^6" }, "require-dev": { From 3d3c06b20d49d96982a9eb7d6c9793b0fce11501 Mon Sep 17 00:00:00 2001 From: Benjamin Jasper Date: Wed, 8 Dec 2021 15:24:03 +0100 Subject: [PATCH 07/61] feat: removed mail message adapter and dropped v9 support --- .github/workflows/static-analysis.yaml | 2 +- Classes/Controller/ApplicationController.php | 133 +++++------------- ...nUpApplicationsAdditionalFieldProvider.php | 5 +- .../Utility/GoogleIndexingApiConnector.php | 4 +- Classes/Utility/UploadFileUtility.php | 7 +- Configuration/TypoScript/constants.typoscript | 2 +- composer.json | 3 +- phpstan.neon | 4 + 8 files changed, 49 insertions(+), 111 deletions(-) create mode 100644 phpstan.neon diff --git a/.github/workflows/static-analysis.yaml b/.github/workflows/static-analysis.yaml index 1a1aa94..a59ee53 100644 --- a/.github/workflows/static-analysis.yaml +++ b/.github/workflows/static-analysis.yaml @@ -24,4 +24,4 @@ jobs: - run: composer install --no-progress - - run: vendor/bin/phpstan analyse Classes \ No newline at end of file + - run: vendor/bin/phpstan analyse Classes -c phpstan.neon \ No newline at end of file diff --git a/Classes/Controller/ApplicationController.php b/Classes/Controller/ApplicationController.php index 6f803d1..ba5bdd2 100644 --- a/Classes/Controller/ApplicationController.php +++ b/Classes/Controller/ApplicationController.php @@ -32,8 +32,13 @@ use ITX\Jobapplications\Utility\Mail\MailInterface; use ITX\Jobapplications\Utility\Typo3VersionUtility; use ITX\Jobapplications\Utility\UploadFileUtility; + use Psr\Log\LogLevel; + use Symfony\Component\Mailer\Exception\TransportExceptionInterface; + use Symfony\Component\Mime\Address; use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; use TYPO3\CMS\Core\Database\ConnectionPool; + use TYPO3\CMS\Core\Mail\FluidEmail; + use TYPO3\CMS\Core\Mail\Mailer; use TYPO3\CMS\Core\Messaging\FlashMessage; use TYPO3\CMS\Core\Resource\FileInterface; use TYPO3\CMS\Core\Resource\StorageRepository; @@ -255,7 +260,6 @@ public function successAction($firstName, $lastName, $salutation, $problems, $po * @throws \TYPO3\CMS\Core\Resource\Exception\InsufficientFolderWritePermissionsException * @throws \TYPO3\CMS\Core\Resource\Exception\InvalidFileNameException * @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException - * @throws \TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException * @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException * @throws \TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotException * @throws \TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotReturnException @@ -374,64 +378,24 @@ public function createAction(\ITX\Jobapplications\Domain\Model\Application $newA $contact = ($currentPosting->getContact() ?: $contact); - // Get and translate labels - $salutation = LocalizationUtility::translate("fe.application.selector.".$newApplication->getSalutation(), "jobapplications"); - $salary = $newApplication->getSalaryExpectation() ? LocalizationUtility::translate("tx_jobapplications_domain_model_application.salary_expectation", "jobapplications").": ".$newApplication->getSalaryExpectation()."
" : ""; - $dateOfJoining = $newApplication->getEarliestDateOfJoining() ? - LocalizationUtility::translate("tx_jobapplications_domain_model_application.earliest_date_of_joining", "jobapplications") - .": ".$newApplication->getEarliestDateOfJoining()->format(LocalizationUtility::translate("date_format", "jobapplications"))."
" : ""; - $nameLabel = LocalizationUtility::translate("tx_jobapplications_domain_model_location.name", "jobapplications").": "; - $emailLabel = LocalizationUtility::translate("tx_jobapplications_domain_model_application.email", "jobapplications").": "; - $phoneLabel = LocalizationUtility::translate("tx_jobapplications_domain_model_application.phone", "jobapplications").": "; - $addressLabel = LocalizationUtility::translate("tx_jobapplications_domain_model_location.address", "jobapplications").": "; - $additionalAddress = $newApplication->getAddressAddition() ? $newApplication->getAddressAddition().'
' : ""; - $messageLabel = LocalizationUtility::translate("tx_jobapplications_domain_model_application.message", "jobapplications").": "; - $message = $newApplication->getMessage() ? '

'.$messageLabel.'
'.$newApplication->getMessage() : ""; - - $phoneLine = $newApplication->getPhone() !== '' ? $phoneLabel.$newApplication->getPhone().'
' : ''; - - $addressChunk = ""; - if ($newApplication->getAddressStreetAndNumber() - || $newApplication->getAddressPostCode() - || $newApplication->getAddressCity() - || $newApplication->getAddressCountry() - ) - { - $addressChunk = $addressLabel.'
'.$newApplication->getAddressStreetAndNumber().'
' - .$additionalAddress. - $newApplication->getAddressPostCode().' '.$newApplication->getAddressCity() - .'
'.$newApplication->getAddressCountry(); - } + /** @var Mailer $mailer */ + $mailer = GeneralUtility::makeInstance(Mailer::class); // Send mail to Contact E-Mail or/and internal E-Mail if ($this->settings["sendEmailToContact"] === "1" || $this->settings['sendEmailToInternal'] !== "") { - /** @var \ITX\Jobapplications\Utility\Mail\MailInterface $mail */ - if ($this->version >= 10) - { - $mail = GeneralUtility::makeInstance(\ITX\Jobapplications\Utility\Mail\MailFluid::class); - $mail->setTemplate('JobsNotificationMail'); - } - else - { - $mail = GeneralUtility::makeInstance(\ITX\Jobapplications\Utility\Mail\MailMessage::class); - } + $mail = GeneralUtility::makeInstance(FluidEmail::class); + $mail->setTemplate('JobsNotificationMail'); + - $mail->setContentType($this->settings['emailContentType']); + $mail->format($this->settings['emailContentType']); // Prepare and send the message $mail - ->addSubject(LocalizationUtility::translate("fe.email.toContactSubject", 'jobapplications', [0 => $currentPosting->getTitle()])) - ->from([$this->settings["emailSender"] => $this->settings["emailSenderName"]]) - ->setReply([$newApplication->getEmail() => $newApplication->getFirstName()." ".$newApplication->getLastName()]) - ->setContent('

'. - $nameLabel.$salutation.' '.$newApplication->getFirstName().' '.$newApplication->getLastName().'
'. - $emailLabel.$newApplication->getEmail().'
'. - $phoneLine. - $salary. - $dateOfJoining.'
'. - $addressChunk - .$message.'

', ['application' => $newApplication, 'settings' => $this->settings, 'currentPosting' => $currentPosting]); + ->subject(LocalizationUtility::translate("fe.email.toContactSubject", 'jobapplications', [0 => $currentPosting->getTitle()])) + ->from(new Address($this->settings["emailSender"], $this->settings["emailSenderName"])) + ->replyTo(new Address($newApplication->getEmail(), $newApplication->getFirstName()." ".$newApplication->getLastName())) + ->assignMultiple(['application' => $newApplication, 'settings' => $this->settings, 'currentPosting' => $currentPosting]); foreach ($legacyUploadfiles as $fileArray) { @@ -439,7 +403,7 @@ public function createAction(\ITX\Jobapplications\Domain\Model\Application $newA { if ($file instanceof FileInterface) { - $mail->addAttachment($file->getPublicUrl()); + $mail->attach($file->getPublicUrl()); } } } @@ -448,35 +412,32 @@ public function createAction(\ITX\Jobapplications\Domain\Model\Application $newA { if ($file instanceof FileInterface) { - $mail->addAttachment($file->getPublicUrl()); + $mail->attach($file->getPublicUrl()); } } //Figure out who the email will be sent to and how if ($this->settings['sendEmailToInternal'] != "" && $this->settings['sendEmailToContact'] == "1") { - $mail->to([$contact->getEmail() => $contact->getFirstName().' '.$contact->getLastName()]); - $mail->setBlindcopies([$this->settings['sendEmailToInternal']]); + $mail->to(new Address($contact->getEmail(), $contact->getFirstName().' '.$contact->getLastName())); + $mail->bcc(new Address($this->settings['sendEmailToInternal'])); } else if ($this->settings['sendEmailToContact'] != "1" && $this->settings['sendEmailToInternal'] != "") { - $mail->to([$this->settings['sendEmailToInternal'] => 'Internal']); + $mail->to(new Address($this->settings['sendEmailToInternal'], 'Internal')); } else if ($this->settings['sendEmailToContact'] == "1" && $this->settings['sendEmailToInternal'] != "1") { - $mail->to([$contact->getEmail() => $contact->getFirstName()." ".$contact->getLastName()]); + $mail->to(new Address($contact->getEmail(), $contact->getFirstName()." ".$contact->getLastName())); } try { - if (!$mail->send()) - { - throw new \RuntimeException('Failed to send mail!'); - } + $mailer->send($mail); } catch (\Exception $e) { - $this->logger->log(\TYPO3\CMS\Core\Log\LogLevel::CRITICAL, 'Error trying to send a mail: '.$e->getMessage(), [$this->settings, $mail]); + $this->logger->log(LogLevel::CRITICAL, 'Error trying to send a mail: '.$e->getMessage(), [$this->settings, $mail]); $problemWithNotificationMail = true; } } @@ -484,54 +445,24 @@ public function createAction(\ITX\Jobapplications\Domain\Model\Application $newA // Now send a mail to the applicant if ($this->settings["sendEmailToApplicant"] === "1") { - /** @var MailInterface $mail */ - if ($this->version >= 10) - { - $mail = GeneralUtility::makeInstance(\ITX\Jobapplications\Utility\Mail\MailFluid::class); - $mail->setTemplate('JobsApplicantMail'); - } - else - { - $mail = GeneralUtility::makeInstance(\ITX\Jobapplications\Utility\Mail\MailMessage::class); - } + $mail = GeneralUtility::makeInstance(FluidEmail::class); + $mail->setTemplate('JobsApplicantMail'); - $mail->setContentType($this->settings['emailContentType']); + $mail->format($this->settings['emailContentType']); //Template Messages $subject = $this->settings['sendEmailToApplicantSubject']; $subject = str_replace("%postingTitle%", $currentPosting->getTitle(), $subject); - $body = $this->settings["sendEmailToApplicantText"]; - switch ((int)$newApplication->getSalutation()) - { - case 3: - case 0: - $salutation = ""; - break; - case 1: - $salutation = LocalizationUtility::translate("fe.application.selector.mr", "jobapplications"); - break; - case 2: - $salutation = LocalizationUtility::translate("fe.application.selector.mrs", "jobapplications"); - break; - } - $body = str_replace("%applicantSalutation%", $salutation, $body); - $body = str_replace("%applicantFirstname%", $newApplication->getFirstName(), $body); - $body = str_replace("%applicantLastname%", $newApplication->getLastName(), $body); - $body = str_replace("%postingTitle%", $currentPosting->getTitle(), $body); - $mail - ->addSubject($subject) - ->from([$this->settings["emailSender"] => $this->settings["emailSenderName"]]) - ->to([$newApplication->getEmail() => $newApplication->getFirstName()." ".$newApplication->getLastName()]) - ->setContent($body, ['application' => $newApplication, 'settings' => $this->settings]); + ->subject($subject) + ->from(new Address($this->settings["emailSender"], $this->settings["emailSenderName"])) + ->to(new Address($newApplication->getEmail(), $newApplication->getFirstName()." ".$newApplication->getLastName())) + ->assignMultiple(['application' => $newApplication, 'settings' => $this->settings]); try { - if (!$mail->send()) - { - throw new \RuntimeException('Failed to send mail!'); - } + $mailer->send($mail); } catch (\Exception $e) { @@ -697,7 +628,7 @@ private function buildRelations(int $objectUid, int $fileUid, int $objectPid, st ->update( "tx_jobapplications_domain_model_application", ["files" => $totalFiles], [ - 'uid' => $newStorageUid + 'uid' => $objectUid ]); } } diff --git a/Classes/Task/CleanUpApplicationsAdditionalFieldProvider.php b/Classes/Task/CleanUpApplicationsAdditionalFieldProvider.php index 21e50b8..d34d349 100644 --- a/Classes/Task/CleanUpApplicationsAdditionalFieldProvider.php +++ b/Classes/Task/CleanUpApplicationsAdditionalFieldProvider.php @@ -2,6 +2,9 @@ namespace ITX\Jobapplications\Task; + use TYPO3\CMS\Core\Messaging\AbstractMessage; + use TYPO3\CMS\Core\Messaging\FlashMessage; + /*************************************************************** * Copyright notice * @@ -95,7 +98,7 @@ public function validateAdditionalFields(array &$submittedData, \TYPO3\CMS\Sched // @extensionScannerIgnoreLine $this->addMessage( $this->getLanguageService()->sL('LLL:EXT:jobapplications/Resources/Private/Language/locallang_backend.xlf:task.days.empty'), - FlashMessage::ERROR + AbstractMessage::ERROR ); $result = false; } diff --git a/Classes/Utility/GoogleIndexingApiConnector.php b/Classes/Utility/GoogleIndexingApiConnector.php index 6b92c5b..db30bae 100644 --- a/Classes/Utility/GoogleIndexingApiConnector.php +++ b/Classes/Utility/GoogleIndexingApiConnector.php @@ -187,7 +187,7 @@ private function sendFlashMessage(string $msg, string $header = "", bool $error { $debug = $this->backendConfiguration['indexing_api_debug']; - if ($debug === "0" || $this->suppressFlashMessages) + if ($debug === "0") { return; } @@ -399,7 +399,7 @@ private function makeAuthReq() $signatureSignedBase64 = base64_encode($signatureSigned); - $token .= $signatureInput.".".$signatureSignedBase64; + $token = $signatureInput.".".$signatureSignedBase64; $accessTokenRequestData = [ "grant_type" => "urn:ietf:params:oauth:grant-type:jwt-bearer", diff --git a/Classes/Utility/UploadFileUtility.php b/Classes/Utility/UploadFileUtility.php index 7fa3486..d984e8c 100644 --- a/Classes/Utility/UploadFileUtility.php +++ b/Classes/Utility/UploadFileUtility.php @@ -85,14 +85,13 @@ public function handleFile(UploadedFile $file): string * @param string $uniqueIdentifier * * @return string - * @throws IdentifierNotValidException */ public function getFilePath(string $uniqueIdentifier): string { $filePath = $this->fileTempPath.$uniqueIdentifier.DIRECTORY_SEPARATOR; if (strlen($uniqueIdentifier) !== 23) { - throw new IdentifierNotValidException('Invalid identifier'); + throw new \RuntimeException('Invalid identifier'); } if (!GeneralUtility::validPathStr($filePath)) @@ -125,7 +124,7 @@ public function getFilePath(string $uniqueIdentifier): string * @param string $uniqueIdentifier * * @return string - * @throws IdentifierNotValidException + * @throws \RuntimeException */ public function getFileName(string $uniqueIdentifier): string { @@ -133,7 +132,7 @@ public function getFileName(string $uniqueIdentifier): string if (strlen($uniqueIdentifier) !== 23) { - throw new IdentifierNotValidException('Invalid identifier'); + throw new \RuntimeException('Invalid identifier'); } if (!GeneralUtility::validPathStr($filePath)) diff --git a/Configuration/TypoScript/constants.typoscript b/Configuration/TypoScript/constants.typoscript index 2e4cad7..5948f1f 100644 --- a/Configuration/TypoScript/constants.typoscript +++ b/Configuration/TypoScript/constants.typoscript @@ -6,7 +6,7 @@ plugin.tx_jobapplications.settings { # cat=plugin.tx_jobapplications; type=boolean; label=LLL:EXT:jobapplications/Resources/Private/Language/locallang_backend.xlf:legacy_upload legacy_upload = 1 - # cat=plugin.tx_jobapplications; type=options[html,text,both]; label=Send Email as HTML or Text or Both + # cat=plugin.tx_jobapplications; type=options[html,plain,both]; label=Send Email as HTML or Text or Both emailContentType = both # cat=plugin.tx_jobapplications; type=int; label=Maximum number of items on one page diff --git a/composer.json b/composer.json index 34b7cc1..17940ff 100644 --- a/composer.json +++ b/composer.json @@ -23,8 +23,9 @@ "docs": "https://docs.typo3.org/p/itx/jobapplications/master/en-us/" }, "require": { - "typo3/cms-core": "^9.5 || ^10.4", + "typo3/cms-core": "^10.4", "typo3/cms-scheduler": "*", + "typo3/cms-dashboard": "*", "fluidtypo3/vhs": "^6" }, "require-dev": { diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..502f680 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,4 @@ +parameters: + level: 6 + paths: + - Classes \ No newline at end of file From 5e6077592e7aae80e2e7d3a7b429d76b90eb6d5a Mon Sep 17 00:00:00 2001 From: Benjamin Jasper Date: Wed, 8 Dec 2021 15:26:23 +0100 Subject: [PATCH 08/61] fix: reduced phpstan level for now --- phpstan.neon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpstan.neon b/phpstan.neon index 502f680..a37df58 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,4 +1,4 @@ parameters: - level: 6 + level: 2 paths: - Classes \ No newline at end of file From ebe9c886665240cb36feb385f1d5ff87f2119ce3 Mon Sep 17 00:00:00 2001 From: Benjamin Jasper Date: Wed, 8 Dec 2021 15:44:38 +0100 Subject: [PATCH 09/61] fix: more phpstan fixes --- Classes/Controller/AjaxController.php | 1 - Classes/Controller/ApplicationController.php | 41 ++-- Classes/Utility/Mail/MailFluid.php | 206 ------------------- Classes/Utility/Mail/MailInterface.php | 115 ----------- Classes/Utility/Mail/MailMessage.php | 165 --------------- 5 files changed, 23 insertions(+), 505 deletions(-) delete mode 100644 Classes/Utility/Mail/MailFluid.php delete mode 100644 Classes/Utility/Mail/MailInterface.php delete mode 100644 Classes/Utility/Mail/MailMessage.php diff --git a/Classes/Controller/AjaxController.php b/Classes/Controller/AjaxController.php index 5064868..91b3b14 100644 --- a/Classes/Controller/AjaxController.php +++ b/Classes/Controller/AjaxController.php @@ -50,7 +50,6 @@ public function __construct() /** * @param \Psr\Http\Message\ServerRequestInterface $request - * @param \Psr\Http\Message\ResponseInterface $response * * @return \Psr\Http\Message\ResponseInterface */ diff --git a/Classes/Controller/ApplicationController.php b/Classes/Controller/ApplicationController.php index ba5bdd2..d5d0f0b 100644 --- a/Classes/Controller/ApplicationController.php +++ b/Classes/Controller/ApplicationController.php @@ -33,16 +33,17 @@ use ITX\Jobapplications\Utility\Typo3VersionUtility; use ITX\Jobapplications\Utility\UploadFileUtility; use Psr\Log\LogLevel; - use Symfony\Component\Mailer\Exception\TransportExceptionInterface; use Symfony\Component\Mime\Address; use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; use TYPO3\CMS\Core\Database\ConnectionPool; + use TYPO3\CMS\Core\Localization\Exception\FileNotFoundException; use TYPO3\CMS\Core\Mail\FluidEmail; use TYPO3\CMS\Core\Mail\Mailer; use TYPO3\CMS\Core\Messaging\FlashMessage; + use TYPO3\CMS\Core\Resource\File; use TYPO3\CMS\Core\Resource\FileInterface; + use TYPO3\CMS\Core\Resource\ResourceStorage; use TYPO3\CMS\Core\Resource\StorageRepository; - use TYPO3\CMS\Core\Utility\DebugUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Mvc\View\ViewInterface; use TYPO3\CMS\Extbase\Property\TypeConverter\DateTimeConverter; @@ -105,7 +106,6 @@ class ApplicationController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionCont * initialize create action * adjusts date time format to y-m-d * - * @param void * * @throws \TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException */ @@ -319,7 +319,10 @@ public function createAction(\ITX\Jobapplications\Domain\Model\Application $newA $this->redirect("new", "Application", null, ["posting" => $posting]); } - $newApplication->setPosting($posting); + if ($posting instanceof Posting) + { + $newApplication->setPosting($posting); + } /* @var \ITX\Jobapplications\Domain\Model\Status $firstStatus */ $firstStatus = $this->statusRepository->findNewStatus(); @@ -387,7 +390,6 @@ public function createAction(\ITX\Jobapplications\Domain\Model\Application $newA $mail = GeneralUtility::makeInstance(FluidEmail::class); $mail->setTemplate('JobsNotificationMail'); - $mail->format($this->settings['emailContentType']); // Prepare and send the message @@ -497,13 +499,13 @@ public function createAction(\ITX\Jobapplications\Domain\Model\Application $newA ]; $uri = $this->uriBuilder->uriFor('success', - [ - 'firstName' => $newApplication->getFirstName(), - 'lastName' => $newApplication->getLastName(), - 'salutation' => $newApplication->getSalutation(), - 'problems' => $problems, - 'postingUid' => $currentPosting->getUid() ?: -1 - ], 'Application', null, 'SuccessPage'); + [ + 'firstName' => $newApplication->getFirstName(), + 'lastName' => $newApplication->getLastName(), + 'salutation' => $newApplication->getSalutation(), + 'problems' => $problems, + 'postingUid' => $currentPosting->getUid() ?: -1 + ], 'Application', null, 'SuccessPage'); $this->redirectToUri($uri); } @@ -520,9 +522,8 @@ public function createAction(\ITX\Jobapplications\Domain\Model\Application $newA * @throws \TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException * @throws \TYPO3\CMS\Core\Resource\Exception\InsufficientFolderWritePermissionsException * @throws \TYPO3\CMS\Core\Resource\Exception\InvalidFileNameException - * @throws \TYPO3\CMS\Form\Domain\Exception\IdentifierNotValidException */ - private function processFiles(Application $newApplication, array $fileIds, string $fieldName, $fileNamePrefix = ''): array + private function processFiles(Application $newApplication, array $fileIds, string $fieldName, string $fileNamePrefix = ''): array { $uploadUtility = new UploadFileUtility(); @@ -554,15 +555,15 @@ private function processFiles(Application $newApplication, array $fileIds, strin * @param \ITX\Jobapplications\Domain\Model\Application $domainObject * @param string $prefix * - * @return FileInterface + * @return File|FileInterface * @throws \TYPO3\CMS\Core\Resource\Exception\ExistingTargetFileNameException * @throws \TYPO3\CMS\Core\Resource\Exception\ExistingTargetFolderException * @throws \TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException * @throws \TYPO3\CMS\Core\Resource\Exception\InsufficientFolderWritePermissionsException * @throws \TYPO3\CMS\Core\Resource\Exception\InvalidFileNameException */ - private function handleFileUpload(string $filePath, string $fileName, - \ITX\Jobapplications\Domain\Model\Application $domainObject, string $prefix = ''): FileInterface + private function handleFileUpload(string $filePath, string $fileName, + \ITX\Jobapplications\Domain\Model\Application $domainObject, string $prefix = '') { $folder = $this->applicationFileService->getApplicantFolder($domainObject); @@ -571,6 +572,10 @@ private function handleFileUpload(string $filePath, string $fileName, $storageRepository = $this->objectManager->get(StorageRepository::class); $storage = $storageRepository->findByUid('1'); + if (!$storage instanceof ResourceStorage) { + throw new FileNotFoundException("Could not find fileadmin with uid 1"); + } + //build the new storage folder if ($storage->hasFolder($folder)) { @@ -598,7 +603,7 @@ private function handleFileUpload(string $filePath, string $fileName, * @param int $iteration The current iteration * @param int $totalFiles The total amount of iterations */ - private function buildRelations(int $objectUid, int $fileUid, int $objectPid, string $field, $iteration = 0, $totalFiles = 1): void + private function buildRelations(int $objectUid, int $fileUid, int $objectPid, string $field, int $iteration = 0, int $totalFiles = 1): void { /** @var ConnectionPool $database */ $database = GeneralUtility::makeInstance(ConnectionPool::class); diff --git a/Classes/Utility/Mail/MailFluid.php b/Classes/Utility/Mail/MailFluid.php deleted file mode 100644 index 475f370..0000000 --- a/Classes/Utility/Mail/MailFluid.php +++ /dev/null @@ -1,206 +0,0 @@ -view->assign('normalizedParams', NormalizedParams::createFromServerParams($_SERVER)); - $this->format(self::FORMAT_BOTH); - } - - /** - * @inheritDoc - */ - public function setRecipient(array $addresses, string $name = ''): MailInterface - { - foreach ($addresses as $key => $address) - { - $addressObject = $this->addressArrayToObject($key, $address); - $this->addTo($addressObject); - } - - return $this; - } - - /** - * @param $key - * @param $address - * - * @return Address - */ - private function addressArrayToObject($key, $address): Address - { - $addressObject = null; - if (is_int($key)) - { - $addressObject = new Address($address); - } - else - { - $addressObject = new Address($key, $address); - } - - return $addressObject; - } - - /** - * @inheritDoc - */ - public function addSubject(string $subject): MailInterface - { - return $this->subject($subject); - } - - /** - * @inheritDoc - */ - public function setReply(array $addresses, $name = ''): MailInterface - { - foreach ($addresses as $key => $address) - { - $addressObject = $this->addressArrayToObject($key, $address); - - $this->addReplyTo($addressObject); - } - - return $this; - } - - /** - * @inheritDoc - */ - public function setContent(string $contents, $objects = []): MailInterface - { - $assign = array_merge([ - 'text' => $contents - ], $objects); - - return $this->assignMultiple($assign); - } - - /** - * @inheritDoc - */ - public function addAttachment(string $url): MailInterface - { - return $this->attachFromPath($url); - } - - /** - * @inheritDoc - * @throws TransportExceptionInterface - */ - public function send(): bool - { - /** @var Mailer $mailer */ - $mailer = GeneralUtility::makeInstance(Mailer::class); - - $mailer->send($this); - - return true; - } - - /** - * @inheritDoc - */ - public function setBlindcopies(array $addresses): MailInterface - { - foreach ($addresses as $key => $address) - { - $addressObject = $this->addressArrayToObject($key, $address); - - $this->addBcc($addressObject); - } - - return $this; - } - - /** - * @inheritDoc - */ - public function to(array $addresses, string $name = ''): MailInterface - { - foreach ($addresses as $key => $address) - { - $addressObject = $this->addressArrayToObject($key, $address); - - $this->addTo($addressObject); - } - - return $this; - } - - /** - * @inheritDoc - */ - public function from(array $addresses, $name = ''): MailInterface - { - foreach ($addresses as $key => $address) - { - $addressObject = $this->addressArrayToObject($key, $address); - - $this->addFrom($addressObject); - } - - return $this; - } - - /** - * @inheritDoc - */ - public function setContentType(string $contentType): MailInterface - { - if ($contentType === self::CONTENT_TYPE_TEXT) - { - $contentType = 'plain'; - } - $this->format($contentType); - - return $this; - } - } \ No newline at end of file diff --git a/Classes/Utility/Mail/MailInterface.php b/Classes/Utility/Mail/MailInterface.php deleted file mode 100644 index 24139cc..0000000 --- a/Classes/Utility/Mail/MailInterface.php +++ /dev/null @@ -1,115 +0,0 @@ -to($addresses, $name); - } - - /** - * Set the to addresses of this message. - * - * If multiple recipients will receive the message an array should be used. - * Example: array('receiver@domain.org', 'other@domain.org' => 'A name') - * - * If $name is passed and the first parameter is a string, this name will be - * associated with the address. - * - * @param string|array $addresses - * @param string $name optional - * - * @return \TYPO3\CMS\Core\Mail\MailMessage - */ - public function to($addresses, $name = ''): MailInterface - { - $this->setTo($addresses, $name); - - return $this; - } - - /** - * Set the from address of this message. - * - * You may pass an array of addresses if this message is from multiple people. - * - * If $name is passed and the first parameter is a string, this name will be - * associated with the address. - * - * @param string|array $addresses - * @param string $name optional - * - * @return \TYPO3\CMS\Core\Mail\MailMessage - */ - public function from($addresses, $name = ''): MailInterface - { - $this->setFrom($addresses, $name); - - return $this; - } - - /** - * @inheritDoc - */ - public function setBlindcopies(array $addresses): MailInterface - { - $this->setBcc($addresses); - - return $this; - } - - /** - * @inheritDoc - */ - public function setReply(array $addresses): MailInterface - { - $this->setReplyTo($addresses); - - return $this; - } - - /** - * @inheritDoc - * - * Objects and Content Type are ignored - */ - public function setContent(string $content, $objects = []): MailInterface - { - $this->setBody($content); - - return $this; - } - - /** - * @inheritDoc - */ - public function addAttachment(string $url): MailInterface - { - return $this->attach(\Swift_Attachment::fromPath($url)); - } - - /** - * @inheritDoc - */ - public function setContentType($contentType): MailInterface - { - switch ($contentType) - { - case self::CONTENT_TYPE_TEXT: - parent::setContentType('text/plain'); - break; - default: - parent::setContentType('text/html'); - break; - } - - return $this; - } - - /** - * Set the subject of this message. - * - * @param string $subject - * - * @return $this - */ - public function addSubject($subject): MailInterface - { - $this->setSubject($subject); - - return $this; - } - - public function send(): bool - { - $result = parent::send(); - - return $result !== 0; - } - } \ No newline at end of file From 8f17814e43b18c0100924b5cbe6ba98200a85115 Mon Sep 17 00:00:00 2001 From: Benjamin Jasper Date: Wed, 8 Dec 2021 16:10:45 +0100 Subject: [PATCH 10/61] fix: more phpstan fixes --- Classes/Controller/ApplicationController.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Classes/Controller/ApplicationController.php b/Classes/Controller/ApplicationController.php index d5d0f0b..0ca0401 100644 --- a/Classes/Controller/ApplicationController.php +++ b/Classes/Controller/ApplicationController.php @@ -237,6 +237,9 @@ public function successAction($firstName, $lastName, $salutation, $problems, $po $salutation = LocalizationUtility::translate('fe.application.selector.'.$salutation, 'jobapplications'); } + /** @var Posting|null $posting */ + $posting = null; + if ($postingUid !== -1) { $posting = $this->postingRepository->findByUid($postingUid); From baa8f50f45ef831cda2823f088d278356af7aa90 Mon Sep 17 00:00:00 2001 From: Benjamin Jasper Date: Thu, 9 Dec 2021 12:41:46 +0100 Subject: [PATCH 11/61] fix: reduced php stan level --- phpstan.neon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpstan.neon b/phpstan.neon index a37df58..e7a89e6 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,4 +1,4 @@ parameters: - level: 2 + level: 1 paths: - Classes \ No newline at end of file From c8467f3ff92af16dff5e2179e77ddf8dca0dfa48 Mon Sep 17 00:00:00 2001 From: Benjamin Jasper Date: Thu, 9 Dec 2021 13:07:23 +0100 Subject: [PATCH 12/61] fix: fixed more phpstan issues --- Classes/Domain/Model/Contact.php | 5 +++-- Classes/Service/ApplicationFileService.php | 7 +++++++ .../CleanUpApplicationsAdditionalFieldProvider.php | 13 +++++++++---- Classes/Utility/UploadFileUtility.php | 2 +- Classes/ViewHelpers/GroupByCategoryViewHelper.php | 1 + .../Provider/BackendModuleButtonProvider.php | 4 +--- 6 files changed, 22 insertions(+), 10 deletions(-) diff --git a/Classes/Domain/Model/Contact.php b/Classes/Domain/Model/Contact.php index f2bc107..1d62158 100644 --- a/Classes/Domain/Model/Contact.php +++ b/Classes/Domain/Model/Contact.php @@ -2,6 +2,8 @@ namespace ITX\Jobapplications\Domain\Model; + use TYPO3\CMS\Core\Http\ApplicationType; + /*************************************************************** * Copyright notice * @@ -200,8 +202,7 @@ public function setPhoto(\TYPO3\CMS\Extbase\Domain\Model\FileReference $photo) */ public function getBeUser() { - if (TYPO3_MODE === 'BE') - { + if (ApplicationType::fromRequest($GLOBALS['TYPO3_REQUEST'])->isBackend()) { return $this->beUser; } diff --git a/Classes/Service/ApplicationFileService.php b/Classes/Service/ApplicationFileService.php index ee3f35a..55ba912 100644 --- a/Classes/Service/ApplicationFileService.php +++ b/Classes/Service/ApplicationFileService.php @@ -2,10 +2,12 @@ namespace ITX\Jobapplications\Service; + use TYPO3\CMS\Core\Localization\Exception\FileNotFoundException; use TYPO3\CMS\Core\Resource\Exception\FileOperationErrorException; use TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException; use TYPO3\CMS\Core\Resource\Exception\InsufficientUserPermissionsException; use TYPO3\CMS\Core\Resource\Exception\InvalidPathException; + use TYPO3\CMS\Core\Resource\ResourceStorage; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Object\ObjectManager; @@ -51,7 +53,12 @@ public function deleteApplicationFolder(string $folderPath): void /* @var \TYPO3\CMS\Core\Resource\StorageRepository $storageRepository */ $storageRepository = $objectManager->get(\TYPO3\CMS\Core\Resource\StorageRepository::class); $storage = $storageRepository->findByUid(1); + if (!$storage instanceof ResourceStorage) { + throw new FileNotFoundException("Could not find fileadmin with uid 1"); + } + /** @var \TYPO3\CMS\Core\Resource\Folder|null $folder */ + $folder = null; if ($storage->hasFolder($folderPath)) { $folder = $storage->getFolder($folderPath); diff --git a/Classes/Task/CleanUpApplicationsAdditionalFieldProvider.php b/Classes/Task/CleanUpApplicationsAdditionalFieldProvider.php index d34d349..ddd5c7b 100644 --- a/Classes/Task/CleanUpApplicationsAdditionalFieldProvider.php +++ b/Classes/Task/CleanUpApplicationsAdditionalFieldProvider.php @@ -2,6 +2,7 @@ namespace ITX\Jobapplications\Task; + use TYPO3\CMS\Core\Localization\LanguageService; use TYPO3\CMS\Core\Messaging\AbstractMessage; use TYPO3\CMS\Core\Messaging\FlashMessage; @@ -90,7 +91,7 @@ public function getAdditionalFields(array &$taskInfo, $task, \TYPO3\CMS\Schedule * * @return bool TRUE if validation was ok (or selected class is not relevant), FALSE otherwise */ - public function validateAdditionalFields(array &$submittedData, \TYPO3\CMS\Scheduler\Controller\SchedulerModuleController $schedulerModule) + public function validateAdditionalFields(array &$submittedData, \TYPO3\CMS\Scheduler\Controller\SchedulerModuleController $schedulerModule): bool { $submittedData['days'] = trim($submittedData['days']); if (empty($submittedData['days'])) @@ -111,11 +112,15 @@ public function validateAdditionalFields(array &$submittedData, \TYPO3\CMS\Sched } /** - * @return LanguageService|null + * @return LanguageService */ - protected function getLanguageService(): ?LanguageService + protected function getLanguageService(): LanguageService { - return $GLOBALS['LANG'] ?? null; + if (!$GLOBALS['LANG'] instanceof LanguageService) { + throw new FileNotFoundException("Could not fetch language service"); + } + + return $GLOBALS['LANG']; } /** diff --git a/Classes/Utility/UploadFileUtility.php b/Classes/Utility/UploadFileUtility.php index d984e8c..f35ca90 100644 --- a/Classes/Utility/UploadFileUtility.php +++ b/Classes/Utility/UploadFileUtility.php @@ -70,7 +70,7 @@ public function handleFile(UploadedFile $file): string $renameResult = rename($filePath.reset($files), $filePath.$file->getClientFilename()); if (!$renameResult) { - throw new \RuntimeException("Could not rename file: ".$filePath.files[0]); + throw new \RuntimeException("Could not rename file: ".$filePath.$files[0]); } } else diff --git a/Classes/ViewHelpers/GroupByCategoryViewHelper.php b/Classes/ViewHelpers/GroupByCategoryViewHelper.php index 47b0e2f..0b74bf2 100644 --- a/Classes/ViewHelpers/GroupByCategoryViewHelper.php +++ b/Classes/ViewHelpers/GroupByCategoryViewHelper.php @@ -50,6 +50,7 @@ public static function renderStatic(array $arguments, \Closure $renderChildrenCl throw new ViewHelper\Exception('GroupByCategoryViewHelper only supports arrays and objects implementing \Traversable interface', 1248728393); } + $iterationData = []; if (isset($arguments['iteration'])) { $iterationData = [ diff --git a/Classes/Widgets/Provider/BackendModuleButtonProvider.php b/Classes/Widgets/Provider/BackendModuleButtonProvider.php index de558fa..9178c68 100644 --- a/Classes/Widgets/Provider/BackendModuleButtonProvider.php +++ b/Classes/Widgets/Provider/BackendModuleButtonProvider.php @@ -37,11 +37,9 @@ class BackendModuleButtonProvider extends \TYPO3\CMS\Dashboard\Widgets\Provider\ /** * BackendModuleButtonProvider constructor. * - * @param string $title - * @param string $link * @param string $target */ - public function __construct(string $title, string $link, string $target = '') + public function __construct(string $target = '') { if (!$GLOBALS['BE_USER']->check('modules', 'web_JobapplicationsBackend')) { From afe45fe3060ee042bc27aead9df77de818aae280 Mon Sep 17 00:00:00 2001 From: Benjamin Jasper Date: Thu, 9 Dec 2021 13:09:28 +0100 Subject: [PATCH 13/61] fix: fixed more phpstan issues --- Classes/Task/CleanUpApplicationsAdditionalFieldProvider.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classes/Task/CleanUpApplicationsAdditionalFieldProvider.php b/Classes/Task/CleanUpApplicationsAdditionalFieldProvider.php index ddd5c7b..4ebac1d 100644 --- a/Classes/Task/CleanUpApplicationsAdditionalFieldProvider.php +++ b/Classes/Task/CleanUpApplicationsAdditionalFieldProvider.php @@ -117,7 +117,7 @@ public function validateAdditionalFields(array &$submittedData, \TYPO3\CMS\Sched protected function getLanguageService(): LanguageService { if (!$GLOBALS['LANG'] instanceof LanguageService) { - throw new FileNotFoundException("Could not fetch language service"); + throw new \RuntimeException("Could not fetch language service"); } return $GLOBALS['LANG']; From 7608bddfc6b85b7ce793dca8d500a7ca50b10de4 Mon Sep 17 00:00:00 2001 From: sdl Date: Mon, 10 Jan 2022 21:20:15 +0100 Subject: [PATCH 14/61] first run of rector1 --- Classes/Controller/AjaxController.php | 12 +-- Classes/Controller/ApplicationController.php | 74 ++++++++++++++----- Classes/Controller/BackendController.php | 55 +++++++++++--- Classes/Controller/ContactController.php | 14 +++- Classes/Controller/PostingController.php | 43 ++++++++--- Classes/Domain/Model/Application.php | 25 ++++--- Classes/Domain/Model/Contact.php | 6 +- Classes/Domain/Model/Location.php | 6 +- Classes/Domain/Model/Posting.php | 20 ++--- Classes/Domain/Model/Status.php | 5 +- Classes/Domain/Model/TtContent.php | 6 +- .../Repository/ApplicationRepository.php | 10 +-- .../Domain/Repository/ContactRepository.php | 2 +- .../Repository/JobapplicationsRepository.php | 6 +- .../Domain/Repository/LocationRepository.php | 2 +- .../Domain/Repository/PostingRepository.php | 8 +- .../Domain/Repository/StatusRepository.php | 6 +- Classes/Hooks/TCEmainHook.php | 10 +-- Classes/Service/ApplicationFileService.php | 12 ++- Classes/Task/AnonymizeApplications.php | 13 ++-- Classes/Task/CleanUpApplications.php | 13 ++-- ...nUpApplicationsAdditionalFieldProvider.php | 3 +- .../Utility/GoogleIndexingApiConnector.php | 19 ++--- .../ViewHelpers/GroupByCategoryViewHelper.php | 4 +- ...ApplicationsPerPostingBarChartProvider.php | 10 ++- .../Provider/BackendModuleButtonProvider.php | 6 +- .../Provider/PostingsActiveProvider.php | 7 +- Configuration/TCA/Overrides/sys_template.php | 2 +- Configuration/TCA/Overrides/tt_content.php | 10 +-- ..._jobapplications_domain_model_location.php | 2 +- ...x_jobapplications_domain_model_posting.php | 2 +- ...bapplications_domain_model_application.php | 70 +++++++++--------- ...x_jobapplications_domain_model_contact.php | 12 +-- ..._jobapplications_domain_model_location.php | 6 +- ...x_jobapplications_domain_model_posting.php | 30 ++------ ...tx_jobapplications_domain_model_status.php | 10 +-- .../Controller/ApplicationControllerTest.php | 14 ++-- .../Unit/Controller/ContactControllerTest.php | 38 ++++++---- .../Controller/LocationControllerTest.php | 38 ++++++---- .../Unit/Controller/PostingControllerTest.php | 22 ++++-- Tests/Unit/Domain/Model/ApplicationTest.php | 20 +++-- Tests/Unit/Domain/Model/ContactTest.php | 8 +- Tests/Unit/Domain/Model/LocationTest.php | 8 +- Tests/Unit/Domain/Model/PostingTest.php | 19 +++-- ext_emconf.php | 4 +- ext_localconf.php | 34 +++++---- ext_tables.php | 6 +- 47 files changed, 444 insertions(+), 308 deletions(-) diff --git a/Classes/Controller/AjaxController.php b/Classes/Controller/AjaxController.php index 91b3b14..b764d40 100644 --- a/Classes/Controller/AjaxController.php +++ b/Classes/Controller/AjaxController.php @@ -24,6 +24,8 @@ namespace ITX\Jobapplications\Controller; + use Psr\Http\Message\ServerRequestInterface; + use Psr\Http\Message\ResponseInterface; use ITX\Jobapplications\Utility\UploadFileUtility; use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; use TYPO3\CMS\Core\Core\Environment; @@ -54,8 +56,8 @@ public function __construct() * @return \Psr\Http\Message\ResponseInterface */ public function uploadAction( - \Psr\Http\Message\ServerRequestInterface $request - ): \Psr\Http\Message\ResponseInterface + ServerRequestInterface $request + ): ResponseInterface { $response = new HtmlResponse(''); @@ -65,7 +67,7 @@ public function uploadAction( $responseContent = ''; /** @var ExtensionConfiguration $extconf */ - $extconf = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(ExtensionConfiguration::class); + $extconf = GeneralUtility::makeInstance(ExtensionConfiguration::class); $extConfLimit = $extconf->get('jobapplications', 'customFileSizeLimit'); $allowedFileTypesString = $extconf->get('jobapplications', 'allowedFileTypes'); $allowedFileTypes = $allowedFileTypesString !== '' ? explode(',', $allowedFileTypesString) : []; @@ -142,8 +144,8 @@ public function uploadAction( } public function revertAction( - \Psr\Http\Message\ServerRequestInterface $request - ): \Psr\Http\Message\ResponseInterface + ServerRequestInterface $request + ): ResponseInterface { $response = new HtmlResponse(''); $body = $request->getBody(); diff --git a/Classes/Controller/ApplicationController.php b/Classes/Controller/ApplicationController.php index 0ca0401..e024134 100644 --- a/Classes/Controller/ApplicationController.php +++ b/Classes/Controller/ApplicationController.php @@ -24,7 +24,17 @@ * * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ - + use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; + use TYPO3\CMS\Core\Log\LogManager; + use Psr\Http\Message\ResponseInterface; + use ITX\Jobapplications\Domain\Model\Contact; + use TYPO3\CMS\Core\Resource\Driver\LocalDriver; + use ITX\Jobapplications\Domain\Repository\ApplicationRepository; + use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager; + use ITX\Jobapplications\Service\ApplicationFileService; + use TYPO3\CMS\Extbase\SignalSlot\Dispatcher; + use ITX\Jobapplications\Domain\Repository\PostingRepository; + use ITX\Jobapplications\Domain\Repository\StatusRepository; use ITX\Jobapplications\Domain\Model\Application; use ITX\Jobapplications\Domain\Model\Posting; use ITX\Jobapplications\Domain\Model\Status; @@ -52,14 +62,13 @@ /** * ApplicationController */ - class ApplicationController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController + class ApplicationController extends ActionController { /** * applicationRepository * * @var \ITX\Jobapplications\Domain\Repository\ApplicationRepository - * @TYPO3\CMS\Extbase\Annotation\Inject */ protected $applicationRepository = null; @@ -70,19 +79,16 @@ class ApplicationController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionCont protected $allowedFileTypesString; /** * @var \TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager - * @TYPO3\CMS\Extbase\Annotation\Inject */ protected $persistenceManager; /** * @var \ITX\Jobapplications\Service\ApplicationFileService - * @TYPO3\CMS\Extbase\Annotation\Inject */ protected $applicationFileService; /** * signalSlotDispatcher * * @var \TYPO3\CMS\Extbase\SignalSlot\Dispatcher - * @TYPO3\CMS\Extbase\Annotation\Inject */ protected $signalSlotDispatcher; /** @@ -93,12 +99,10 @@ class ApplicationController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionCont protected $version; /** * @var \ITX\Jobapplications\Domain\Repository\PostingRepository - * @TYPO3\CMS\Extbase\Annotation\Inject */ private $postingRepository; /** * @var \ITX\Jobapplications\Domain\Repository\StatusRepository - * @TYPO3\CMS\Extbase\Annotation\Inject */ private $statusRepository; @@ -115,11 +119,11 @@ public function initializeCreateAction(): void ->getPropertyMappingConfiguration()->forProperty('earliestDateOfJoining') ->setTypeConverterOption( DateTimeConverter::class, - \TYPO3\CMS\Extbase\Property\TypeConverter\DateTimeConverter::CONFIGURATION_DATE_FORMAT, + DateTimeConverter::CONFIGURATION_DATE_FORMAT, 'Y-m-d' ); - $this->logger = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Log\LogManager::class)->getLogger(__CLASS__); + $this->logger = GeneralUtility::makeInstance(LogManager::class)->getLogger(__CLASS__); } /** @@ -146,7 +150,7 @@ public function initializeView(ViewInterface $view) public function initializeAction(): void { /** @var ExtensionConfiguration $extconf */ - $extconf = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(ExtensionConfiguration::class); + $extconf = GeneralUtility::makeInstance(ExtensionConfiguration::class); $extConfLimit = $extconf->get('jobapplications', 'customFileSizeLimit'); $this->allowedFileTypesString = $extconf->get('jobapplications', 'allowedFileTypes'); @@ -168,7 +172,7 @@ public function initializeAction(): void * * @throws \TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException */ - public function newAction(Posting $posting = null): void + public function newAction(Posting $posting = null): ResponseInterface { /* Getting posting when Detailview and applicationform are on the same page. @@ -215,6 +219,7 @@ public function newAction(Posting $posting = null): void { $this->view->assign("fileError", 0); } + return $this->htmlResponse(); } /** @@ -224,7 +229,7 @@ public function newAction(Posting $posting = null): void * @param array $problems * @param int $postingUid */ - public function successAction($firstName, $lastName, $salutation, $problems, $postingUid = -1) + public function successAction($firstName, $lastName, $salutation, $problems, $postingUid = -1): ResponseInterface { $salutationValue = $salutation; @@ -251,6 +256,7 @@ public function successAction($firstName, $lastName, $salutation, $problems, $po $this->view->assign('salutation', $salutation); $this->view->assign('problems', $problems); $posting ? $this->view->assign('salutationValue', $salutationValue) : false; + return $this->htmlResponse(); } /** @@ -268,7 +274,7 @@ public function successAction($firstName, $lastName, $salutation, $problems, $po * @throws \TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotReturnException * @throws \TYPO3\CMS\Form\Domain\Exception\IdentifierNotValidException */ - public function createAction(\ITX\Jobapplications\Domain\Model\Application $newApplication, \ITX\Jobapplications\Domain\Model\Posting $posting = null): void + public function createAction(Application $newApplication, Posting $posting = null): void { $problemWithApplicantMail = false; $problemWithNotificationMail = false; @@ -351,7 +357,7 @@ public function createAction(\ITX\Jobapplications\Domain\Model\Application $newA if (!($posting instanceof Posting)) { /** @var Posting $posting */ - $posting = GeneralUtility::makeInstance(\ITX\Jobapplications\Domain\Model\Posting::class); + $posting = GeneralUtility::makeInstance(Posting::class); $posting->setTitle(LocalizationUtility::translate("fe.application.unsolicited.title", "jobapplications")); $newApplication->setPosting($posting); @@ -376,7 +382,7 @@ public function createAction(\ITX\Jobapplications\Domain\Model\Application $newA $currentPosting = $newApplication->getPosting(); // Default contact is not available - $contact = GeneralUtility::makeInstance(\ITX\Jobapplications\Domain\Model\Contact::class); + $contact = GeneralUtility::makeInstance(Contact::class); $contact->setEmail($this->settings["defaultContactMailAddress"]); $contact->setFirstName($this->settings["defaultContactFirstName"]); @@ -490,7 +496,7 @@ public function createAction(\ITX\Jobapplications\Domain\Model\Application $newA $this->uriBuilder->setTargetPageUid((int)$this->settings['successPage']); - if (\TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('TYPO3_SSL')) + if (GeneralUtility::getIndpEnv('TYPO3_SSL')) { $this->uriBuilder->setAbsoluteUriScheme('https'); } @@ -566,7 +572,7 @@ private function processFiles(Application $newApplication, array $fileIds, strin * @throws \TYPO3\CMS\Core\Resource\Exception\InvalidFileNameException */ private function handleFileUpload(string $filePath, string $fileName, - \ITX\Jobapplications\Domain\Model\Application $domainObject, string $prefix = '') + Application $domainObject, string $prefix = '') { $folder = $this->applicationFileService->getApplicantFolder($domainObject); @@ -590,7 +596,7 @@ private function handleFileUpload(string } //file name - $newFileName = (new \TYPO3\CMS\Core\Resource\Driver\LocalDriver)->sanitizeFileName($prefix.$fileName); + $newFileName = (new LocalDriver)->sanitizeFileName($prefix.$fileName); //build sys_file $movedNewFile = $storage->addFile($filePath, $targetFolder, $newFileName); @@ -640,4 +646,34 @@ private function buildRelations(int $objectUid, int $fileUid, int $objectPid, st ]); } } + + public function injectApplicationRepository(ApplicationRepository $applicationRepository): void + { + $this->applicationRepository = $applicationRepository; + } + + public function injectPersistenceManager(PersistenceManager $persistenceManager): void + { + $this->persistenceManager = $persistenceManager; + } + + public function injectApplicationFileService(ApplicationFileService $applicationFileService): void + { + $this->applicationFileService = $applicationFileService; + } + + public function injectSignalSlotDispatcher(Dispatcher $signalSlotDispatcher): void + { + $this->signalSlotDispatcher = $signalSlotDispatcher; + } + + public function injectPostingRepository(PostingRepository $postingRepository): void + { + $this->postingRepository = $postingRepository; + } + + public function injectStatusRepository(StatusRepository $statusRepository): void + { + $this->statusRepository = $statusRepository; + } } \ No newline at end of file diff --git a/Classes/Controller/BackendController.php b/Classes/Controller/BackendController.php index f227ebf..25a33aa 100644 --- a/Classes/Controller/BackendController.php +++ b/Classes/Controller/BackendController.php @@ -25,6 +25,15 @@ namespace ITX\Jobapplications\Controller; + use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; + use ITX\Jobapplications\Domain\Model\Application; + use Psr\Http\Message\ResponseInterface; + use ITX\Jobapplications\Domain\Repository\ApplicationRepository; + use ITX\Jobapplications\Domain\Repository\PostingRepository; + use ITX\Jobapplications\Domain\Repository\ContactRepository; + use ITX\Jobapplications\Domain\Repository\StatusRepository; + use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager; + use ITX\Jobapplications\Service\ApplicationFileService; use ITX\Jobapplications\Domain\Model\Contact; use ITX\Jobapplications\Domain\Model\Posting; use ITX\Jobapplications\Domain\Model\Status; @@ -38,13 +47,12 @@ * * @package ITX\Jobapplications\Controller */ - class BackendController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController + class BackendController extends ActionController { /** * applicationRepository * * @var \ITX\Jobapplications\Domain\Repository\ApplicationRepository - * @TYPO3\CMS\Extbase\Annotation\Inject */ protected $applicationRepository = null; @@ -52,7 +60,6 @@ class BackendController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionControll * postingRepository * * @var \ITX\Jobapplications\Domain\Repository\PostingRepository - * @TYPO3\CMS\Extbase\Annotation\Inject */ protected $postingRepository = null; @@ -60,7 +67,6 @@ class BackendController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionControll * contactRepository * * @var \ITX\Jobapplications\Domain\Repository\ContactRepository - * @TYPO3\CMS\Extbase\Annotation\Inject */ protected $contactRepository = null; @@ -68,7 +74,6 @@ class BackendController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionControll * statusRepository * * @var \ITX\Jobapplications\Domain\Repository\StatusRepository - * @TYPO3\CMS\Extbase\Annotation\Inject */ protected $statusRepository = null; @@ -76,13 +81,11 @@ class BackendController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionControll * persistenceManager * * @var \TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager - * @TYPO3\CMS\Extbase\Annotation\Inject */ protected $persistenceManager; /** * @var \ITX\Jobapplications\Service\ApplicationFileService - * @TYPO3\CMS\Extbase\Annotation\Inject */ protected $applicationFileService; @@ -202,7 +205,7 @@ private function getActiveBeContact() * @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException * @throws \TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException */ - public function showApplicationAction(\ITX\Jobapplications\Domain\Model\Application $application) + public function showApplicationAction(Application $application) { $statusDatabaseOp = false; @@ -257,7 +260,7 @@ public function showApplicationAction(\ITX\Jobapplications\Domain\Model\Applicat * Action for Backend Dashboard * */ - public function dashboardAction() + public function dashboardAction(): ResponseInterface { // Get data for counter of new applications with referenced contact $contact = $this->getActiveBeContact(); @@ -285,6 +288,7 @@ public function dashboardAction() $this->view->assign('admin', $GLOBALS['BE_USER']->isAdmin()); $this->view->assign('newApps', count($newApps)); $this->view->assign('contact', $contact); + return $this->htmlResponse(); } /** @@ -294,7 +298,7 @@ public function dashboardAction() * @throws \TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException * @throws \Exception */ - public function settingsAction() + public function settingsAction(): ResponseInterface { if (!$GLOBALS['BE_USER']->isAdmin()) { @@ -360,5 +364,36 @@ public function settingsAction() } $this->view->assign('admin', $GLOBALS['BE_USER']->isAdmin()); + return $this->htmlResponse(); + } + + public function injectApplicationRepository(ApplicationRepository $applicationRepository): void + { + $this->applicationRepository = $applicationRepository; + } + + public function injectPostingRepository(PostingRepository $postingRepository): void + { + $this->postingRepository = $postingRepository; + } + + public function injectContactRepository(ContactRepository $contactRepository): void + { + $this->contactRepository = $contactRepository; + } + + public function injectStatusRepository(StatusRepository $statusRepository): void + { + $this->statusRepository = $statusRepository; + } + + public function injectPersistenceManager(PersistenceManager $persistenceManager): void + { + $this->persistenceManager = $persistenceManager; + } + + public function injectApplicationFileService(ApplicationFileService $applicationFileService): void + { + $this->applicationFileService = $applicationFileService; } } \ No newline at end of file diff --git a/Classes/Controller/ContactController.php b/Classes/Controller/ContactController.php index d6f9825..8418790 100644 --- a/Classes/Controller/ContactController.php +++ b/Classes/Controller/ContactController.php @@ -2,6 +2,9 @@ namespace ITX\Jobapplications\Controller; + use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; + use Psr\Http\Message\ResponseInterface; + use ITX\Jobapplications\Domain\Repository\ContactRepository; use TYPO3\CMS\Extbase\Mvc\View\ViewInterface; /*************************************************************** @@ -30,14 +33,13 @@ /** * ContactController */ - class ContactController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController + class ContactController extends ActionController { /** * contactRepository * * @var \ITX\Jobapplications\Domain\Repository\ContactRepository - * @TYPO3\CMS\Extbase\Annotation\Inject */ protected $contactRepository = null; @@ -65,7 +67,7 @@ public function initializeView(ViewInterface $view) * * @return void */ - public function listAction() + public function listAction(): ResponseInterface { $contacts = []; $selectedContactsStr = $this->settings["selectedContacts"]; @@ -85,5 +87,11 @@ public function listAction() $contactObjects = array_replace(array_flip($contacts), $contactByUid); $this->view->assign('contacts', $contactObjects); + return $this->htmlResponse(); + } + + public function injectContactRepository(ContactRepository $contactRepository): void + { + $this->contactRepository = $contactRepository; } } diff --git a/Classes/Controller/PostingController.php b/Classes/Controller/PostingController.php index c8f776b..73094cd 100644 --- a/Classes/Controller/PostingController.php +++ b/Classes/Controller/PostingController.php @@ -2,6 +2,13 @@ namespace ITX\Jobapplications\Controller; + use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; + use Psr\Http\Message\ResponseInterface; + use TYPO3\CMS\Extbase\Persistence\QueryInterface; + use TYPO3\CMS\Core\Cache\CacheManager; + use ITX\Jobapplications\Domain\Repository\PostingRepository; + use ITX\Jobapplications\Domain\Repository\LocationRepository; + use TYPO3\CMS\Extbase\SignalSlot\Dispatcher; use ITX\Jobapplications\Domain\Model\Constraint; use ITX\Jobapplications\Domain\Model\Posting; use ITX\Jobapplications\PageTitle\JobsPageTitleProvider; @@ -39,14 +46,13 @@ /** * PostingController */ - class PostingController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController + class PostingController extends ActionController { /** * postingRepository * * @var \ITX\Jobapplications\Domain\Repository\PostingRepository - * @TYPO3\CMS\Extbase\Annotation\Inject */ protected $postingRepository = null; @@ -54,7 +60,6 @@ class PostingController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionControll * locationRepository * * @var \ITX\Jobapplications\Domain\Repository\LocationRepository - * @TYPO3\CMS\Extbase\Annotation\Inject */ protected $locationRepository = null; @@ -62,7 +67,6 @@ class PostingController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionControll * signalSlotDispatcher * * @var \TYPO3\CMS\Extbase\SignalSlot\Dispatcher - * @TYPO3\CMS\Extbase\Annotation\Inject */ protected $signalSlotDispatcher; @@ -106,7 +110,7 @@ public function initializeView(ViewInterface $view) * @throws \TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotReturnException * @throws \TYPO3\CMS\Extbase\Reflection\Exception\UnknownClassException */ - public function listAction(Constraint $constraint = null): void + public function listAction(Constraint $constraint = null): ResponseInterface { // Plugin selected categories $category_str = $this->settings["categories"]; @@ -117,13 +121,13 @@ public function listAction(Constraint $constraint = null): void switch ($this->settings['list']['ordering']['order']) { case 'descending': - $order = \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING; + $order = QueryInterface::ORDER_DESCENDING; break; case 'ascending': - $order = \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING; + $order = QueryInterface::ORDER_ASCENDING; break; default: - $order = \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING; + $order = QueryInterface::ORDER_DESCENDING; } // Get repository configuration from typoscript @@ -158,6 +162,7 @@ public function listAction(Constraint $constraint = null): void $this->view->assign('isFiltering', $isFiltering); $this->view->assign('filterOptions', $filterOptions); $this->view->assign('constraint', $constraint); + return $this->htmlResponse(); } /** @@ -168,7 +173,7 @@ public function listAction(Constraint $constraint = null): void private function getCachedFilterOptions($categories): array { /** @var FrontendInterface $cache */ - $cache = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Cache\CacheManager::class)->getCache('jobapplications_cache'); + $cache = GeneralUtility::makeInstance(CacheManager::class)->getCache('jobapplications_cache'); // If $entry is false, it hasn't been cached. Calculate the value and store it in the cache: if (($entry = $cache->get('filterOptions')) === false) @@ -211,7 +216,7 @@ public function getFilterOptions($categories): array * @throws \TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotException * @throws \TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotReturnException */ - public function showAction(\ITX\Jobapplications\Domain\Model\Posting $posting = null): void + public function showAction(Posting $posting = null): ResponseInterface { if ($posting === null) { @@ -224,7 +229,7 @@ public function showAction(\ITX\Jobapplications\Domain\Model\Posting $posting = $titleProvider = GeneralUtility::makeInstance(JobsPageTitleProvider::class); /** @var ExtensionConfiguration $extconf */ - $extconf = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(ExtensionConfiguration::class); + $extconf = GeneralUtility::makeInstance(ExtensionConfiguration::class); //Google Jobs @@ -344,5 +349,21 @@ public function showAction(\ITX\Jobapplications\Domain\Model\Posting $posting = } $this->view->assign('posting', $posting); + return $this->htmlResponse(); + } + + public function injectPostingRepository(PostingRepository $postingRepository): void + { + $this->postingRepository = $postingRepository; + } + + public function injectLocationRepository(LocationRepository $locationRepository): void + { + $this->locationRepository = $locationRepository; + } + + public function injectSignalSlotDispatcher(Dispatcher $signalSlotDispatcher): void + { + $this->signalSlotDispatcher = $signalSlotDispatcher; } } diff --git a/Classes/Domain/Model/Application.php b/Classes/Domain/Model/Application.php index d44894b..5727ccf 100644 --- a/Classes/Domain/Model/Application.php +++ b/Classes/Domain/Model/Application.php @@ -1,7 +1,9 @@ files = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage(); - $this->cv = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage(); - $this->coverLetter = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage(); - $this->testimonials = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage(); - $this->otherFiles = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage(); + $this->files = new ObjectStorage(); + $this->cv = new ObjectStorage(); + $this->coverLetter = new ObjectStorage(); + $this->testimonials = new ObjectStorage(); + $this->otherFiles = new ObjectStorage(); } /** @@ -381,7 +382,7 @@ public function getCv() * * @return void */ - public function setCv(\TYPO3\CMS\Extbase\Persistence\ObjectStorage $cv) + public function setCv(ObjectStorage $cv) { $this->cv = $cv; } @@ -403,7 +404,7 @@ public function getCoverLetter() * * @return void */ - public function setCoverLetter(\TYPO3\CMS\Extbase\Persistence\ObjectStorage $coverLetter) + public function setCoverLetter(ObjectStorage $coverLetter) { $this->coverLetter = $coverLetter; } @@ -425,7 +426,7 @@ public function getTestimonials() * * @return void */ - public function setTestimonials(\TYPO3\CMS\Extbase\Persistence\ObjectStorage $testimonials) + public function setTestimonials(ObjectStorage $testimonials) { $this->testimonials = $testimonials; } @@ -447,7 +448,7 @@ public function getOtherFiles() * * @return void */ - public function setOtherFiles(\TYPO3\CMS\Extbase\Persistence\ObjectStorage $otherFiles) + public function setOtherFiles(ObjectStorage $otherFiles) { $this->otherFiles = $otherFiles; } diff --git a/Classes/Domain/Model/Contact.php b/Classes/Domain/Model/Contact.php index 1d62158..c9c2e99 100644 --- a/Classes/Domain/Model/Contact.php +++ b/Classes/Domain/Model/Contact.php @@ -2,6 +2,8 @@ namespace ITX\Jobapplications\Domain\Model; + use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; + use TYPO3\CMS\Extbase\Domain\Model\FileReference; use TYPO3\CMS\Core\Http\ApplicationType; /*************************************************************** @@ -30,7 +32,7 @@ /** * A Contact is the person who handles the application process for this posting. */ - class Contact extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity + class Contact extends AbstractEntity { /** @@ -192,7 +194,7 @@ public function getPhoto() /** * @param \TYPO3\CMS\Extbase\Domain\Model\FileReference $photo */ - public function setPhoto(\TYPO3\CMS\Extbase\Domain\Model\FileReference $photo) + public function setPhoto(FileReference $photo) { $this->photo = $photo; } diff --git a/Classes/Domain/Model/Location.php b/Classes/Domain/Model/Location.php index 2bb210a..c27dec8 100644 --- a/Classes/Domain/Model/Location.php +++ b/Classes/Domain/Model/Location.php @@ -1,7 +1,8 @@ categories = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage(); + $this->categories = new ObjectStorage(); } /** @@ -534,7 +536,7 @@ public function getLocation() * * @return void */ - public function setLocation(\ITX\Jobapplications\Domain\Model\Location $location) + public function setLocation(Location $location) { $this->location = $location; } @@ -556,7 +558,7 @@ public function getContact() * * @return void */ - public function setContact(\ITX\Jobapplications\Domain\Model\Contact $contact) + public function setContact(Contact $contact) { $this->contact = $contact; } @@ -578,7 +580,7 @@ public function getDetailViewImage() * * @return void */ - public function setDetailViewImage(\TYPO3\CMS\Extbase\Domain\Model\FileReference $detailViewImage) + public function setDetailViewImage(FileReference $detailViewImage) { $this->detailViewImage = $detailViewImage; } @@ -600,7 +602,7 @@ public function getListViewImage() * * @return void */ - public function setListViewImage(\TYPO3\CMS\Extbase\Domain\Model\FileReference $listViewImage) + public function setListViewImage(FileReference $listViewImage) { $this->listViewImage = $listViewImage; } @@ -616,7 +618,7 @@ public function getCategories() /** * @param \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\Category> $categories */ - public function setCategories(\TYPO3\CMS\Extbase\Persistence\ObjectStorage $categories): void + public function setCategories(ObjectStorage $categories): void { $this->categories = $categories; } diff --git a/Classes/Domain/Model/Status.php b/Classes/Domain/Model/Status.php index 961e831..583cb13 100644 --- a/Classes/Domain/Model/Status.php +++ b/Classes/Domain/Model/Status.php @@ -2,6 +2,7 @@ namespace ITX\Jobapplications\Domain\Model; + use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; use TYPO3\CMS\Extbase\Persistence\ObjectStorage; /*************************************************************** @@ -30,7 +31,7 @@ /** * Status */ - class Status extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity + class Status extends AbstractEntity { /** * name @@ -87,7 +88,7 @@ public function getFollowers() /** * @param ObjectStorage $followers */ - public function setFollowers(\TYPO3\CMS\Extbase\Persistence\ObjectStorage $followers) + public function setFollowers(ObjectStorage $followers) { $this->followers = $followers; } diff --git a/Classes/Domain/Model/TtContent.php b/Classes/Domain/Model/TtContent.php index 1413f5f..ca113e9 100644 --- a/Classes/Domain/Model/TtContent.php +++ b/Classes/Domain/Model/TtContent.php @@ -1,7 +1,8 @@ createQuery(); $query->getQuerySettings()->setRespectStoragePage(false) @@ -97,7 +97,7 @@ public function findAll() ->setRespectStoragePage(false) ->setIgnoreEnableFields(true); $query->setOrderings([ - "crdate" => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING + "crdate" => QueryInterface::ORDER_DESCENDING ]); return $query->execute(); diff --git a/Classes/Domain/Repository/ContactRepository.php b/Classes/Domain/Repository/ContactRepository.php index d7bb6c7..0981c71 100644 --- a/Classes/Domain/Repository/ContactRepository.php +++ b/Classes/Domain/Repository/ContactRepository.php @@ -28,7 +28,7 @@ /** * The repository for Contacts */ - class ContactRepository extends \ITX\Jobapplications\Domain\Repository\JobapplicationsRepository + class ContactRepository extends JobapplicationsRepository { /** * @param array $uids diff --git a/Classes/Domain/Repository/JobapplicationsRepository.php b/Classes/Domain/Repository/JobapplicationsRepository.php index 96b80eb..4847bac 100644 --- a/Classes/Domain/Repository/JobapplicationsRepository.php +++ b/Classes/Domain/Repository/JobapplicationsRepository.php @@ -24,6 +24,8 @@ namespace ITX\Jobapplications\Domain\Repository; + use TYPO3\CMS\Extbase\Persistence\Repository; + use TYPO3\CMS\Core\Database\Query\QueryBuilder; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -32,7 +34,7 @@ * * Parent Repository for other repos */ - abstract class JobapplicationsRepository extends \TYPO3\CMS\Extbase\Persistence\Repository + abstract class JobapplicationsRepository extends Repository { /** * Helper function for building the sql for categories @@ -43,7 +45,7 @@ abstract class JobapplicationsRepository extends \TYPO3\CMS\Extbase\Persistence\ * @return \TYPO3\CMS\Core\Database\Query\QueryBuilder */ - public function buildCategoriesToSQL(array $categories, \TYPO3\CMS\Core\Database\Query\QueryBuilder $qb) + public function buildCategoriesToSQL(array $categories, QueryBuilder $qb) { $statement = ""; for ($i = 0, $iMax = count($categories); $i < $iMax; $i++) diff --git a/Classes/Domain/Repository/LocationRepository.php b/Classes/Domain/Repository/LocationRepository.php index d235c8c..120646b 100644 --- a/Classes/Domain/Repository/LocationRepository.php +++ b/Classes/Domain/Repository/LocationRepository.php @@ -30,7 +30,7 @@ /** * The repository for Locations */ - class LocationRepository extends \ITX\Jobapplications\Domain\Repository\JobapplicationsRepository + class LocationRepository extends JobapplicationsRepository { /** * Returns all objects of this repository. diff --git a/Classes/Domain/Repository/PostingRepository.php b/Classes/Domain/Repository/PostingRepository.php index 6eb60b3..668f931 100644 --- a/Classes/Domain/Repository/PostingRepository.php +++ b/Classes/Domain/Repository/PostingRepository.php @@ -35,7 +35,7 @@ /** * The repository for Postings */ - class PostingRepository extends \ITX\Jobapplications\Domain\Repository\JobapplicationsRepository + class PostingRepository extends JobapplicationsRepository { /** * Helper function for finding postings by category @@ -233,7 +233,7 @@ public function findAllCategories($categories) */ public function findByFilter(array $categories, array $repositoryConfig, Constraint $constraint = null, $orderBy = 'date_posted', - $order = \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING) + $order = QueryInterface::ORDER_DESCENDING) { $query = $this->createQuery(); @@ -328,7 +328,7 @@ public function findByFilter(array $categories, array $repositoryConfig, Constra * * @return array|QueryResultInterface */ - public function findByContact(int $contact, string $orderBy = "title", string $order = \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING) + public function findByContact(int $contact, string $orderBy = "title", string $order = QueryInterface::ORDER_ASCENDING) { $query = $this->createQuery(); $query->getQuerySettings()->setRespectStoragePage(false) @@ -345,7 +345,7 @@ public function findByContact(int $contact, string $orderBy = "title", string $o * * @return QueryResultInterface|array */ - public function findAllWithOrderIgnoreEnable(string $orderBy = "title", string $order = \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING) + public function findAllWithOrderIgnoreEnable(string $orderBy = "title", string $order = QueryInterface::ORDER_ASCENDING) { $query = $this->createQuery(); $query->getQuerySettings()->setRespectStoragePage(false)->setIgnoreEnableFields(true); diff --git a/Classes/Domain/Repository/StatusRepository.php b/Classes/Domain/Repository/StatusRepository.php index c052a44..eefc9f2 100644 --- a/Classes/Domain/Repository/StatusRepository.php +++ b/Classes/Domain/Repository/StatusRepository.php @@ -32,7 +32,7 @@ /** * The repository for Applications */ - class StatusRepository extends \ITX\Jobapplications\Domain\Repository\JobapplicationsRepository + class StatusRepository extends JobapplicationsRepository { /** * Finds all with option of specifiying order @@ -75,8 +75,8 @@ public function findNewStatus() */ public function generateStatus(string $statusFile, string $statusMmFile, int $pid, int $langUid) { - $file1 = \TYPO3\CMS\Core\Utility\GeneralUtility::getFileAbsFileName('EXT:jobapplications/Resources/Private/Sql/'.$statusFile); - $file2 = \TYPO3\CMS\Core\Utility\GeneralUtility::getFileAbsFileName('EXT:jobapplications/Resources/Private/Sql/'.$statusMmFile); + $file1 = GeneralUtility::getFileAbsFileName('EXT:jobapplications/Resources/Private/Sql/'.$statusFile); + $file2 = GeneralUtility::getFileAbsFileName('EXT:jobapplications/Resources/Private/Sql/'.$statusMmFile); $queryDropStatus = $this->createQuery(); $queryDropStatus->statement('DROP TABLE tx_jobapplications_domain_model_status'); diff --git a/Classes/Hooks/TCEmainHook.php b/Classes/Hooks/TCEmainHook.php index 20765e6..c3bcfc0 100644 --- a/Classes/Hooks/TCEmainHook.php +++ b/Classes/Hooks/TCEmainHook.php @@ -32,12 +32,12 @@ class TCEmainHook * * @throws \Exception */ - public function processDatamap_afterDatabaseOperations($status, $table, $id, array $fieldArray, \TYPO3\CMS\Core\DataHandling\DataHandler &$pObj) + public function processDatamap_afterDatabaseOperations($status, $table, $id, array $fieldArray, DataHandler &$pObj) { if ($table === 'tx_jobapplications_domain_model_posting') { - $enabled = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(ExtensionConfiguration::class) + $enabled = GeneralUtility::makeInstance(ExtensionConfiguration::class) ->get('jobapplications', 'indexing_api'); if ($enabled !== "1") @@ -73,11 +73,11 @@ public function processDatamap_afterDatabaseOperations($status, $table, $id, arr * * @throws \Exception */ - public function processDatamap_postProcessFieldArray($command, $table, $uid, $value, \TYPO3\CMS\Core\DataHandling\DataHandler &$pObj) + public function processDatamap_postProcessFieldArray($command, $table, $uid, $value, DataHandler &$pObj) { if ($table === "tx_jobapplications_domain_model_posting") { - $enabled = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(ExtensionConfiguration::class) + $enabled = GeneralUtility::makeInstance(ExtensionConfiguration::class) ->get('jobapplications', 'indexing_api'); if ($enabled !== "1") { @@ -114,7 +114,7 @@ public function processCmdmap_deleteAction($table, $uid, array $record, &$record { if ($table === "tx_jobapplications_domain_model_posting") { - $enabled = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(ExtensionConfiguration::class) + $enabled = GeneralUtility::makeInstance(ExtensionConfiguration::class) ->get('jobapplications', 'indexing_api'); if ($enabled !== "1") { diff --git a/Classes/Service/ApplicationFileService.php b/Classes/Service/ApplicationFileService.php index 55ba912..0673c74 100644 --- a/Classes/Service/ApplicationFileService.php +++ b/Classes/Service/ApplicationFileService.php @@ -2,6 +2,10 @@ namespace ITX\Jobapplications\Service; + use ITX\Jobapplications\Domain\Model\Application; + use TYPO3\CMS\Core\Resource\Driver\LocalDriver; + use TYPO3\CMS\Core\Resource\StorageRepository; + use TYPO3\CMS\Core\Resource\Folder; use TYPO3\CMS\Core\Localization\Exception\FileNotFoundException; use TYPO3\CMS\Core\Resource\Exception\FileOperationErrorException; use TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException; @@ -30,9 +34,9 @@ class ApplicationFileService * @throws \TYPO3\CMS\Core\Resource\Exception\InvalidFileNameException */ - public function getApplicantFolder(\ITX\Jobapplications\Domain\Model\Application $applicationObject): string + public function getApplicantFolder(Application $applicationObject): string { - return self::APP_FILE_FOLDER.(new \TYPO3\CMS\Core\Resource\Driver\LocalDriver) + return self::APP_FILE_FOLDER.(new LocalDriver) ->sanitizeFileName($applicationObject->getFirstName()."_".$applicationObject->getLastName() ."_".hash("md5", $applicationObject->getFirstName()."|" .$applicationObject->getLastName() @@ -51,7 +55,7 @@ public function deleteApplicationFolder(string $folderPath): void $objectManager = GeneralUtility::makeInstance(ObjectManager::class); /* @var \TYPO3\CMS\Core\Resource\StorageRepository $storageRepository */ - $storageRepository = $objectManager->get(\TYPO3\CMS\Core\Resource\StorageRepository::class); + $storageRepository = $objectManager->get(StorageRepository::class); $storage = $storageRepository->findByUid(1); if (!$storage instanceof ResourceStorage) { throw new FileNotFoundException("Could not find fileadmin with uid 1"); @@ -64,7 +68,7 @@ public function deleteApplicationFolder(string $folderPath): void $folder = $storage->getFolder($folderPath); } - if ($folder instanceof \TYPO3\CMS\Core\Resource\Folder) + if ($folder instanceof Folder) { try { diff --git a/Classes/Task/AnonymizeApplications.php b/Classes/Task/AnonymizeApplications.php index f29dd29..c753339 100644 --- a/Classes/Task/AnonymizeApplications.php +++ b/Classes/Task/AnonymizeApplications.php @@ -24,7 +24,10 @@ * * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ - + use TYPO3\CMS\Scheduler\Task\AbstractTask; + use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager; + use ITX\Jobapplications\Domain\Repository\ApplicationRepository; + use ITX\Jobapplications\Service\ApplicationFileService; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Object\ObjectManager; @@ -33,7 +36,7 @@ * * @package ITX\Jobapplications */ - class AnonymizeApplications extends \TYPO3\CMS\Scheduler\Task\AbstractTask + class AnonymizeApplications extends AbstractTask { public $days = null; public $status = 0; @@ -51,9 +54,9 @@ public function execute() $anonymizeChars = "***"; /* @var $objectManager ObjectManager */ $objectManager = GeneralUtility::makeInstance(ObjectManager::class); - $persistenceManager = $objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager::class); - $applicationRepository = $objectManager->get(\ITX\Jobapplications\Domain\Repository\ApplicationRepository::class); - $applicationFileService = $objectManager->get(\ITX\Jobapplications\Service\ApplicationFileService::class); + $persistenceManager = $objectManager->get(PersistenceManager::class); + $applicationRepository = $objectManager->get(ApplicationRepository::class); + $applicationFileService = $objectManager->get(ApplicationFileService::class); // Calculate Timestamp for how old the application must be to give to the repo $now = new \DateTime(); diff --git a/Classes/Task/CleanUpApplications.php b/Classes/Task/CleanUpApplications.php index 7016b91..093902b 100644 --- a/Classes/Task/CleanUpApplications.php +++ b/Classes/Task/CleanUpApplications.php @@ -24,7 +24,10 @@ * * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ - + use TYPO3\CMS\Scheduler\Task\AbstractTask; + use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager; + use ITX\Jobapplications\Domain\Repository\ApplicationRepository; + use ITX\Jobapplications\Service\ApplicationFileService; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Object\ObjectManager; @@ -33,7 +36,7 @@ * * @package ITX\Jobapplications */ - class CleanUpApplications extends \TYPO3\CMS\Scheduler\Task\AbstractTask + class CleanUpApplications extends AbstractTask { public $days = null; public $status = 0; @@ -47,9 +50,9 @@ class CleanUpApplications extends \TYPO3\CMS\Scheduler\Task\AbstractTask public function execute() { $objectManager = GeneralUtility::makeInstance(ObjectManager::class); - $persistenceManager = $objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager::class); - $applicationRepository = $objectManager->get(\ITX\Jobapplications\Domain\Repository\ApplicationRepository::class); - $applicationFileService = $objectManager->get(\ITX\Jobapplications\Service\ApplicationFileService::class); + $persistenceManager = $objectManager->get(PersistenceManager::class); + $applicationRepository = $objectManager->get(ApplicationRepository::class); + $applicationFileService = $objectManager->get(ApplicationFileService::class); $now = new \DateTime(); $timestamp = $now->modify("-".$this->days." days")->getTimestamp(); diff --git a/Classes/Task/CleanUpApplicationsAdditionalFieldProvider.php b/Classes/Task/CleanUpApplicationsAdditionalFieldProvider.php index 4ebac1d..6925483 100644 --- a/Classes/Task/CleanUpApplicationsAdditionalFieldProvider.php +++ b/Classes/Task/CleanUpApplicationsAdditionalFieldProvider.php @@ -2,6 +2,7 @@ namespace ITX\Jobapplications\Task; + use TYPO3\CMS\Scheduler\AbstractAdditionalFieldProvider; use TYPO3\CMS\Core\Localization\LanguageService; use TYPO3\CMS\Core\Messaging\AbstractMessage; use TYPO3\CMS\Core\Messaging\FlashMessage; @@ -34,7 +35,7 @@ * * @package ITX\Jobapplications\TaskAdditionalFieldProvider */ - class CleanUpApplicationsAdditionalFieldProvider extends \TYPO3\CMS\Scheduler\AbstractAdditionalFieldProvider + class CleanUpApplicationsAdditionalFieldProvider extends AbstractAdditionalFieldProvider { /** * This method is used to define new fields for adding or editing a task diff --git a/Classes/Utility/GoogleIndexingApiConnector.php b/Classes/Utility/GoogleIndexingApiConnector.php index db30bae..f415efa 100644 --- a/Classes/Utility/GoogleIndexingApiConnector.php +++ b/Classes/Utility/GoogleIndexingApiConnector.php @@ -24,6 +24,7 @@ namespace ITX\Jobapplications\Utility; + use TYPO3\CMS\Core\Core\Environment; use ITX\Jobapplications\Domain\Model\Posting; use ITX\Jobapplications\Domain\Repository\PostingRepository; use ITX\Jobapplications\Domain\Repository\TtContentRepository; @@ -67,11 +68,11 @@ class GoogleIndexingApiConnector */ public function __construct($supressFlashMessages = false) { - $this->backendConfiguration = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(ExtensionConfiguration::class) + $this->backendConfiguration = GeneralUtility::makeInstance(ExtensionConfiguration::class) ->get('jobapplications'); if ($this->backendConfiguration['key_path'] !== '') { - $fileName = \TYPO3\CMS\Core\Utility\GeneralUtility::getFileAbsFileName($this->backendConfiguration['key_path']); + $fileName = GeneralUtility::getFileAbsFileName($this->backendConfiguration['key_path']); if (file_exists($fileName)) { $this->googleConfig = json_decode(file_get_contents( @@ -98,15 +99,15 @@ public function __construct($supressFlashMessages = false) */ public function updateGoogleIndex($uid, $delete = false, $specificPosting = null): ?bool { - if (\TYPO3\CMS\Core\Utility\GeneralUtility::getApplicationContext()->isDevelopment() && $this->backendConfiguration['indexing_api_dev'] === "0") + if (Environment::getContext()->isDevelopment() && $this->backendConfiguration['indexing_api_dev'] === "0") { return false; } /** @var PostingRepository $postingRepository */ - $postingRepository = $this->objectManager->get(\ITX\Jobapplications\Domain\Repository\PostingRepository::class); + $postingRepository = $this->objectManager->get(PostingRepository::class); /** @var TtContentRepository $ttContentRepository */ - $ttContentRepository = $this->objectManager->get(\ITX\Jobapplications\Domain\Repository\TtContentRepository::class); + $ttContentRepository = $this->objectManager->get(TtContentRepository::class); /** @var Posting $posting */ if ($specificPosting instanceof Posting) @@ -192,18 +193,18 @@ private function sendFlashMessage(string $msg, string $header = "", bool $error return; } - $type = \TYPO3\CMS\Core\Messaging\FlashMessage::OK; + $type = FlashMessage::OK; if ($error) { - $type = \TYPO3\CMS\Core\Messaging\FlashMessage::WARNING; + $type = FlashMessage::WARNING; } /** @var FlashMessage $message */ - $message = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessage::class, $msg, $header, $type, true); + $message = GeneralUtility::makeInstance(FlashMessage::class, $msg, $header, $type, true); /** @var FlashMessageService $flashMessageService */ - $flashMessageService = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessageService::class); + $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class); /** @var FlashMessageQueue $messageQueue */ $messageQueue = $flashMessageService->getMessageQueueByIdentifier(); // @extensionScannerIgnoreLine diff --git a/Classes/ViewHelpers/GroupByCategoryViewHelper.php b/Classes/ViewHelpers/GroupByCategoryViewHelper.php index 0b74bf2..a8b06f1 100644 --- a/Classes/ViewHelpers/GroupByCategoryViewHelper.php +++ b/Classes/ViewHelpers/GroupByCategoryViewHelper.php @@ -6,7 +6,7 @@ * This file belongs to the package "TYPO3 Fluid". * See LICENSE.txt that was shipped with this package. */ - + use TYPO3Fluid\Fluid\Core\ViewHelper\Exception; use ITX\Jobapplications\Domain\Model\Posting; use TYPO3\CMS\Extbase\Domain\Model\Category; use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface; @@ -47,7 +47,7 @@ public static function renderStatic(array $arguments, \Closure $renderChildrenCl } if (is_object($arguments['postings']) && !$arguments['postings'] instanceof \Traversable) { - throw new ViewHelper\Exception('GroupByCategoryViewHelper only supports arrays and objects implementing \Traversable interface', 1248728393); + throw new Exception('GroupByCategoryViewHelper only supports arrays and objects implementing \Traversable interface', 1248728393); } $iterationData = []; diff --git a/Classes/Widgets/Provider/ApplicationsPerPostingBarChartProvider.php b/Classes/Widgets/Provider/ApplicationsPerPostingBarChartProvider.php index 6bb76f8..e332313 100644 --- a/Classes/Widgets/Provider/ApplicationsPerPostingBarChartProvider.php +++ b/Classes/Widgets/Provider/ApplicationsPerPostingBarChartProvider.php @@ -24,6 +24,10 @@ namespace ITX\Jobapplications\Widgets\Provider; + use TYPO3\CMS\Dashboard\Widgets\ChartDataProviderInterface; + use TYPO3\CMS\Core\Utility\GeneralUtility; + use TYPO3\CMS\Extbase\Object\ObjectManager; + use ITX\Jobapplications\Domain\Repository\PostingRepository; use ITX\Jobapplications\Domain\Model\Posting; use ITX\Jobapplications\Domain\Repository\ApplicationRepository; use TYPO3\CMS\Dashboard\Widgets\AbstractBarChartWidget; @@ -34,7 +38,7 @@ * * @package ITX\Jobapplications\Widgets */ - class ApplicationsPerPostingBarChartProvider implements \TYPO3\CMS\Dashboard\Widgets\ChartDataProviderInterface + class ApplicationsPerPostingBarChartProvider implements ChartDataProviderInterface { /** @var array */ protected $labels = []; @@ -42,10 +46,10 @@ class ApplicationsPerPostingBarChartProvider implements \TYPO3\CMS\Dashboard\Wid public function getChartData(): array { /** @var \TYPO3\CMS\Extbase\Object\ObjectManager $objectmanager */ - $objectmanager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class); + $objectmanager = GeneralUtility::makeInstance(ObjectManager::class); /** @var \ITX\Jobapplications\Domain\Repository\PostingRepository $postingRepo */ - $postingRepo = $objectmanager->get(\ITX\Jobapplications\Domain\Repository\PostingRepository::class); + $postingRepo = $objectmanager->get(PostingRepository::class); /** @var ApplicationRepository $applicationRepo */ $applicationRepo = $objectmanager->get(ApplicationRepository::class); diff --git a/Classes/Widgets/Provider/BackendModuleButtonProvider.php b/Classes/Widgets/Provider/BackendModuleButtonProvider.php index 9178c68..1cc5f68 100644 --- a/Classes/Widgets/Provider/BackendModuleButtonProvider.php +++ b/Classes/Widgets/Provider/BackendModuleButtonProvider.php @@ -24,6 +24,8 @@ namespace ITX\Jobapplications\Widgets\Provider; + use TYPO3\CMS\Dashboard\Widgets\Provider\ButtonProvider; + use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException; use TYPO3\CMS\Backend\Routing\UriBuilder; @@ -32,7 +34,7 @@ * * @package ITX\Jobapplications\Widgets\Provider */ - class BackendModuleButtonProvider extends \TYPO3\CMS\Dashboard\Widgets\Provider\ButtonProvider + class BackendModuleButtonProvider extends ButtonProvider { /** * BackendModuleButtonProvider constructor. @@ -47,7 +49,7 @@ public function __construct(string $target = '') } /** @var UriBuilder $uriBuilder */ - $uriBuilder = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(UriBuilder::class); + $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); try { diff --git a/Classes/Widgets/Provider/PostingsActiveProvider.php b/Classes/Widgets/Provider/PostingsActiveProvider.php index 0c59633..e974923 100644 --- a/Classes/Widgets/Provider/PostingsActiveProvider.php +++ b/Classes/Widgets/Provider/PostingsActiveProvider.php @@ -24,6 +24,9 @@ namespace ITX\Jobapplications\Widgets\Provider; + use TYPO3\CMS\Core\Utility\GeneralUtility; + use TYPO3\CMS\Extbase\Object\ObjectManager; + use ITX\Jobapplications\Domain\Repository\PostingRepository; use TYPO3\CMS\Dashboard\Widgets\NumberWithIconDataProviderInterface; /** @@ -36,10 +39,10 @@ class PostingsActiveProvider implements NumberWithIconDataProviderInterface public function getNumber(): int { /** @var \TYPO3\CMS\Extbase\Object\ObjectManager $objectmanager */ - $objectmanager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class); + $objectmanager = GeneralUtility::makeInstance(ObjectManager::class); /** @var \ITX\Jobapplications\Domain\Repository\PostingRepository $postingRepo */ - $postingRepo = $objectmanager->get(\ITX\Jobapplications\Domain\Repository\PostingRepository::class); + $postingRepo = $objectmanager->get(PostingRepository::class); return $postingRepo->findAllIgnoreStoragePage()->count(); } diff --git a/Configuration/TCA/Overrides/sys_template.php b/Configuration/TCA/Overrides/sys_template.php index 06d9b24..5a3ddc4 100644 --- a/Configuration/TCA/Overrides/sys_template.php +++ b/Configuration/TCA/Overrides/sys_template.php @@ -1,5 +1,5 @@ 'first_name,last_name,email,phone,address_street_and_number,address_addition,address_city,address_country,salary_expectation', 'iconfile' => 'EXT:jobapplications/Resources/Public/Icons/Extension.svg' ], - 'interface' => [ - 'showRecordFieldList' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, salutation, first_name, last_name, email, phone, address_street_and_number, address_addition, address_post_code, address_city, address_country, salary_expectation, message, earliest_date_of_joining, files, cv, cover_letter, testimonials, other_files, privacy_agreement, posting, archived, status', - ], 'types' => [ - '1' => ['showitem' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, salutation, first_name, last_name, email, phone, address_street_and_number, address_addition, address_post_code, address_city, address_country, salary_expectation, message ,earliest_date_of_joining, files, cv, cover_letter, testimonials, other_files, privacy_agreement, posting, archived, status, --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.access, starttime, endtime'], + '1' => ['showitem' => 'sys_language_uid,l10n_parent,l10n_diffsource,hidden,salutation,first_name,last_name,email,phone,address_street_and_number,address_addition,address_post_code,address_city,address_country,salary_expectation,message,earliest_date_of_joining,files,cv,cover_letter,testimonials,other_files,privacy_agreement,posting,archived,status,--div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.access,starttime,endtime'], ], 'columns' => [ 'crdate' => [ @@ -55,7 +52,6 @@ ], 'l10n_parent' => [ 'displayCond' => 'FIELD:sys_language_uid:>:0', - 'exclude' => true, 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent', 'config' => [ 'type' => 'select', @@ -267,32 +263,32 @@ 'types' => [ '0' => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_TEXT => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_IMAGE => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_AUDIO => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_VIDEO => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_APPLICATION => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ] ] @@ -316,32 +312,32 @@ 'types' => [ '0' => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_TEXT => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_IMAGE => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_AUDIO => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_VIDEO => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_APPLICATION => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ] ] @@ -365,32 +361,32 @@ 'types' => [ '0' => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_TEXT => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_IMAGE => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_AUDIO => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_VIDEO => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_APPLICATION => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ] ] @@ -414,32 +410,32 @@ 'types' => [ '0' => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_TEXT => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_IMAGE => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_AUDIO => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_VIDEO => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_APPLICATION => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ] ], @@ -463,32 +459,32 @@ 'types' => [ '0' => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_TEXT => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_IMAGE => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_AUDIO => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_VIDEO => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_APPLICATION => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ] ] @@ -505,7 +501,7 @@ 'type' => 'check', 'items' => [ '1' => [ - '0' => 'LLL:EXT:lang/locallang_core.xlf:labels.enabled' + '0' => 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.enabled' ] ], 'default' => 0, @@ -529,7 +525,7 @@ 'type' => 'check', 'items' => [ '1' => [ - '0' => 'LLL:EXT:lang/locallang_core.xlf:labels.enabled' + '0' => 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.enabled' ] ], 'default' => 0, diff --git a/Configuration/TCA/tx_jobapplications_domain_model_contact.php b/Configuration/TCA/tx_jobapplications_domain_model_contact.php index 5e2ab38..9ded31a 100644 --- a/Configuration/TCA/tx_jobapplications_domain_model_contact.php +++ b/Configuration/TCA/tx_jobapplications_domain_model_contact.php @@ -19,11 +19,8 @@ 'searchFields' => 'last_name,email,phone,division', 'iconfile' => 'EXT:jobapplications/Resources/Public/Icons/Extension.svg' ], - 'interface' => [ - 'showRecordFieldList' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, first_name, last_name, email, phone, division, photo, be_user', - ], 'types' => [ - '1' => ['showitem' => 'sys_language_uid, first_name, last_name, email, phone, division, photo, be_user, --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.access, hidden, l10n_parent, l10n_diffsource, starttime, endtime'], + '1' => ['showitem' => 'sys_language_uid,first_name,last_name,email,phone,division,photo,be_user,--div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.access,hidden,l10n_parent,l10n_diffsource,starttime,endtime'], ], 'columns' => [ 'sys_language_uid' => [ @@ -45,7 +42,6 @@ ], 'l10n_parent' => [ 'displayCond' => 'FIELD:sys_language_uid:>:0', - 'exclude' => true, 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent', 'config' => [ 'type' => 'select', @@ -173,7 +169,8 @@ 'showAllLocalizationLink' => true, 'showSynchronizationLink' => true ], - 'foreign_types' => [ + 'maxitems' => 1, + 'overrideChildTca' => ['types' => [ '0' => [ 'showitem' => ' --palette--;;imageoverlayPalette, @@ -204,8 +201,7 @@ --palette--;;imageoverlayPalette, --palette--;;filePalette' ] - ], - 'maxitems' => 1 + ]] ], $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'] ), diff --git a/Configuration/TCA/tx_jobapplications_domain_model_location.php b/Configuration/TCA/tx_jobapplications_domain_model_location.php index 3a88498..115a065 100644 --- a/Configuration/TCA/tx_jobapplications_domain_model_location.php +++ b/Configuration/TCA/tx_jobapplications_domain_model_location.php @@ -19,11 +19,8 @@ 'searchFields' => 'name,address,latitude,londitude', 'iconfile' => 'EXT:jobapplications/Resources/Public/Icons/Extension.svg' ], - 'interface' => [ - 'showRecordFieldList' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, name, address_street_and_number, address_addition, address_post_code, address_city, address_country, latitude, londitude', - ], 'types' => [ - '1' => ['showitem' => 'name, address_street_and_number, address_addition, address_post_code, address_city, address_country, latitude, londitude, --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.access, sys_language_uid, hidden, starttime, endtime, l10n_parent, l10n_diffsource'], + '1' => ['showitem' => 'name,address_street_and_number,address_addition,address_post_code,address_city,address_country,latitude,londitude,--div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.access,sys_language_uid,hidden,starttime,endtime,l10n_parent,l10n_diffsource'], ], 'columns' => [ 'sys_language_uid' => [ @@ -45,7 +42,6 @@ ], 'l10n_parent' => [ 'displayCond' => 'FIELD:sys_language_uid:>:0', - 'exclude' => true, 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent', 'config' => [ 'type' => 'select', diff --git a/Configuration/TCA/tx_jobapplications_domain_model_posting.php b/Configuration/TCA/tx_jobapplications_domain_model_posting.php index ec17ec8..3f3fc61 100644 --- a/Configuration/TCA/tx_jobapplications_domain_model_posting.php +++ b/Configuration/TCA/tx_jobapplications_domain_model_posting.php @@ -22,9 +22,6 @@ 'searchFields' => 'title,career_level,division,employment_type,terms_of_employment,company_description,job_description,role_description,skill_requirements,benefits,base_salary,required_documents,company_information', 'iconfile' => 'EXT:jobapplications/Resources/Public/Icons/Extension.svg' ], - 'interface' => [ - 'showRecordFieldList' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, starttime, endtime, title, date_posted, career_level, division, employment_type, terms_of_employment, company_description, job_description, role_description, skill_requirements, benefits, base_salary, required_documents, company_information, detail_view_image, list_view_image, location, contact', - ], 'columns' => [ 'sys_language_uid' => [ 'exclude' => true, @@ -45,7 +42,6 @@ ], 'l10n_parent' => [ 'displayCond' => 'FIELD:sys_language_uid:>:0', - 'exclude' => true, 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent', 'config' => [ 'type' => 'select', @@ -331,7 +327,8 @@ 'showAllLocalizationLink' => true, 'showSynchronizationLink' => true ], - 'foreign_types' => [ + 'maxitems' => 1, + 'overrideChildTca' => ['types' => [ '0' => [ 'showitem' => ' --palette--;;imageoverlayPalette, @@ -362,8 +359,7 @@ --palette--;;imageoverlayPalette, --palette--;;filePalette' ] - ], - 'maxitems' => 1 + ]] ], $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'] ), @@ -381,7 +377,8 @@ 'showAllLocalizationLink' => true, 'showSynchronizationLink' => true ], - 'foreign_types' => [ + 'maxitems' => 1, + 'overrideChildTca' => ['types' => [ '0' => [ 'showitem' => ' --palette--;;imageoverlayPalette, @@ -412,8 +409,7 @@ --palette--;;imageoverlayPalette, --palette--;;filePalette' ] - ], - 'maxitems' => 1 + ]] ], $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'] ), @@ -459,19 +455,7 @@ ], 'types' => [ '1' => [ - 'showitem' => ' - --palette--;;mainInfo, - --palette--;;relations, - --palette--;;dates, - base_salary, - --palette--;;circumstances, - --div--;LLL:EXT:jobapplications/Resources/Private/Language/locallang_db.xlf:tx_jobapplications_domain_model_posting.title.advanced, - --palette--;;general, - --div--;LLL:EXT:jobapplications/Resources/Private/Language/locallang_db.xlf:tx_jobapplications_domain_model_posting.title.texts, - company_description, job_description, role_description, skill_requirements, benefits, - required_documents, company_information, - --div--;LLL:EXT:jobapplications/Resources/Private/Language/locallang_db.xlf:tx_jobapplications_domain_model_posting.title.images, - --palette--;;images' + 'showitem' => '--palette--;;mainInfo,--palette--;;relations,--palette--;;dates,base_salary,--palette--;;circumstances,--div--;LLL:EXT:jobapplications/Resources/Private/Language/locallang_db.xlf:tx_jobapplications_domain_model_posting.title.advanced,--palette--;;general,--div--;LLL:EXT:jobapplications/Resources/Private/Language/locallang_db.xlf:tx_jobapplications_domain_model_posting.title.texts,company_description,job_description,role_description,skill_requirements,benefits,required_documents,company_information,--div--;LLL:EXT:jobapplications/Resources/Private/Language/locallang_db.xlf:tx_jobapplications_domain_model_posting.title.images,--palette--;;images' ], ], 'palettes' => [ diff --git a/Configuration/TCA/tx_jobapplications_domain_model_status.php b/Configuration/TCA/tx_jobapplications_domain_model_status.php index c8af110..d32c81f 100644 --- a/Configuration/TCA/tx_jobapplications_domain_model_status.php +++ b/Configuration/TCA/tx_jobapplications_domain_model_status.php @@ -20,11 +20,8 @@ 'searchFields' => 'name, followers', 'iconfile' => 'EXT:jobapplications/Resources/Public/Icons/Extension.svg' ], - 'interface' => [ - 'showRecordFieldList' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, name, is_end_status, is_new_status, followers', - ], 'types' => [ - '1' => ['showitem' => 'name, is_end_status, is_new_status, followers, --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.access, hidden, sys_language_uid, starttime, endtime, l10n_parent, l10n_diffsource'], + '1' => ['showitem' => 'name,is_end_status,is_new_status,followers,--div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.access,hidden,sys_language_uid,starttime,endtime,l10n_parent,l10n_diffsource'], ], 'columns' => [ 'crdate' => [ @@ -56,7 +53,6 @@ ], 'l10n_parent' => [ 'displayCond' => 'FIELD:sys_language_uid:>:0', - 'exclude' => true, 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent', 'config' => [ 'type' => 'select', @@ -142,7 +138,7 @@ 'type' => 'check', 'items' => [ '1' => [ - '0' => 'LLL:EXT:lang/locallang_core.xlf:labels.enabled' + '0' => 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.enabled' ] ], 'default' => 0, @@ -155,7 +151,7 @@ 'type' => 'check', 'items' => [ '1' => [ - '0' => 'LLL:EXT:lang/locallang_core.xlf:labels.enabled' + '0' => 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.enabled' ] ], 'default' => 0, diff --git a/Tests/Unit/Controller/ApplicationControllerTest.php b/Tests/Unit/Controller/ApplicationControllerTest.php index b83e21c..c4edbe5 100644 --- a/Tests/Unit/Controller/ApplicationControllerTest.php +++ b/Tests/Unit/Controller/ApplicationControllerTest.php @@ -1,14 +1,18 @@ getMockBuilder(\ITX\Jobapplications\Domain\Repository\ApplicationRepository::class) + $applicationRepository = $this->getMockBuilder(ApplicationRepository::class) ->setMethods(['add']) ->disableOriginalConstructor() ->getMock(); @@ -36,7 +40,7 @@ public function createActionAddsTheGivenApplicationToApplicationRepository() protected function setUp() { parent::setUp(); - $this->subject = $this->getMockBuilder(\ITX\Jobapplications\Controller\ApplicationController::class) + $this->subject = $this->getMockBuilder(ApplicationController::class) ->setMethods(['redirect', 'forward', 'addFlashMessage']) ->disableOriginalConstructor() ->getMock(); diff --git a/Tests/Unit/Controller/ContactControllerTest.php b/Tests/Unit/Controller/ContactControllerTest.php index a28d238..22d1d30 100644 --- a/Tests/Unit/Controller/ContactControllerTest.php +++ b/Tests/Unit/Controller/ContactControllerTest.php @@ -1,14 +1,20 @@ getMockBuilder(\TYPO3\CMS\Extbase\Persistence\ObjectStorage::class) + $allContacts = $this->getMockBuilder(ObjectStorage::class) ->disableOriginalConstructor() ->getMock(); - $contactRepository = $this->getMockBuilder(\ITX\Jobapplications\Domain\Repository\ContactRepository::class) + $contactRepository = $this->getMockBuilder(ContactRepository::class) ->setMethods(['findAll']) ->disableOriginalConstructor() ->getMock(); $contactRepository->expects(self::once())->method('findAll')->will(self::returnValue($allContacts)); $this->inject($this->subject, 'contactRepository', $contactRepository); - $view = $this->getMockBuilder(\TYPO3\CMS\Extbase\Mvc\View\ViewInterface::class)->getMock(); + $view = $this->getMockBuilder(ViewInterface::class)->getMock(); $view->expects(self::once())->method('assign')->with('contacts', $allContacts); $this->inject($this->subject, 'view', $view); @@ -44,9 +50,9 @@ public function listActionFetchesAllContactsFromRepositoryAndAssignsThemToView() */ public function showActionAssignsTheGivenContactToView() { - $contact = new \ITX\Jobapplications\Domain\Model\Contact(); + $contact = new Contact(); - $view = $this->getMockBuilder(\TYPO3\CMS\Extbase\Mvc\View\ViewInterface::class)->getMock(); + $view = $this->getMockBuilder(ViewInterface::class)->getMock(); $this->inject($this->subject, 'view', $view); $view->expects(self::once())->method('assign')->with('contact', $contact); @@ -58,9 +64,9 @@ public function showActionAssignsTheGivenContactToView() */ public function createActionAddsTheGivenContactToContactRepository() { - $contact = new \ITX\Jobapplications\Domain\Model\Contact(); + $contact = new Contact(); - $contactRepository = $this->getMockBuilder(\ITX\Jobapplications\Domain\Repository\ContactRepository::class) + $contactRepository = $this->getMockBuilder(ContactRepository::class) ->setMethods(['add']) ->disableOriginalConstructor() ->getMock(); @@ -76,9 +82,9 @@ public function createActionAddsTheGivenContactToContactRepository() */ public function editActionAssignsTheGivenContactToView() { - $contact = new \ITX\Jobapplications\Domain\Model\Contact(); + $contact = new Contact(); - $view = $this->getMockBuilder(\TYPO3\CMS\Extbase\Mvc\View\ViewInterface::class)->getMock(); + $view = $this->getMockBuilder(ViewInterface::class)->getMock(); $this->inject($this->subject, 'view', $view); $view->expects(self::once())->method('assign')->with('contact', $contact); @@ -90,9 +96,9 @@ public function editActionAssignsTheGivenContactToView() */ public function updateActionUpdatesTheGivenContactInContactRepository() { - $contact = new \ITX\Jobapplications\Domain\Model\Contact(); + $contact = new Contact(); - $contactRepository = $this->getMockBuilder(\ITX\Jobapplications\Domain\Repository\ContactRepository::class) + $contactRepository = $this->getMockBuilder(ContactRepository::class) ->setMethods(['update']) ->disableOriginalConstructor() ->getMock(); @@ -108,9 +114,9 @@ public function updateActionUpdatesTheGivenContactInContactRepository() */ public function deleteActionRemovesTheGivenContactFromContactRepository() { - $contact = new \ITX\Jobapplications\Domain\Model\Contact(); + $contact = new Contact(); - $contactRepository = $this->getMockBuilder(\ITX\Jobapplications\Domain\Repository\ContactRepository::class) + $contactRepository = $this->getMockBuilder(ContactRepository::class) ->setMethods(['remove']) ->disableOriginalConstructor() ->getMock(); @@ -124,7 +130,7 @@ public function deleteActionRemovesTheGivenContactFromContactRepository() protected function setUp() { parent::setUp(); - $this->subject = $this->getMockBuilder(\ITX\Jobapplications\Controller\ContactController::class) + $this->subject = $this->getMockBuilder(ContactController::class) ->setMethods(['redirect', 'forward', 'addFlashMessage']) ->disableOriginalConstructor() ->getMock(); diff --git a/Tests/Unit/Controller/LocationControllerTest.php b/Tests/Unit/Controller/LocationControllerTest.php index fd61d76..34edf37 100644 --- a/Tests/Unit/Controller/LocationControllerTest.php +++ b/Tests/Unit/Controller/LocationControllerTest.php @@ -1,14 +1,20 @@ getMockBuilder(\TYPO3\CMS\Extbase\Persistence\ObjectStorage::class) + $allLocations = $this->getMockBuilder(ObjectStorage::class) ->disableOriginalConstructor() ->getMock(); - $locationRepository = $this->getMockBuilder(\ITX\Jobapplications\Domain\Repository\LocationRepository::class) + $locationRepository = $this->getMockBuilder(LocationRepository::class) ->setMethods(['findAll']) ->disableOriginalConstructor() ->getMock(); $locationRepository->expects(self::once())->method('findAll')->will(self::returnValue($allLocations)); $this->inject($this->subject, 'locationRepository', $locationRepository); - $view = $this->getMockBuilder(\TYPO3\CMS\Extbase\Mvc\View\ViewInterface::class)->getMock(); + $view = $this->getMockBuilder(ViewInterface::class)->getMock(); $view->expects(self::once())->method('assign')->with('locations', $allLocations); $this->inject($this->subject, 'view', $view); @@ -44,9 +50,9 @@ public function listActionFetchesAllLocationsFromRepositoryAndAssignsThemToView( */ public function showActionAssignsTheGivenLocationToView() { - $location = new \ITX\Jobapplications\Domain\Model\Location(); + $location = new Location(); - $view = $this->getMockBuilder(\TYPO3\CMS\Extbase\Mvc\View\ViewInterface::class)->getMock(); + $view = $this->getMockBuilder(ViewInterface::class)->getMock(); $this->inject($this->subject, 'view', $view); $view->expects(self::once())->method('assign')->with('location', $location); @@ -58,9 +64,9 @@ public function showActionAssignsTheGivenLocationToView() */ public function createActionAddsTheGivenLocationToLocationRepository() { - $location = new \ITX\Jobapplications\Domain\Model\Location(); + $location = new Location(); - $locationRepository = $this->getMockBuilder(\ITX\Jobapplications\Domain\Repository\LocationRepository::class) + $locationRepository = $this->getMockBuilder(LocationRepository::class) ->setMethods(['add']) ->disableOriginalConstructor() ->getMock(); @@ -76,9 +82,9 @@ public function createActionAddsTheGivenLocationToLocationRepository() */ public function editActionAssignsTheGivenLocationToView() { - $location = new \ITX\Jobapplications\Domain\Model\Location(); + $location = new Location(); - $view = $this->getMockBuilder(\TYPO3\CMS\Extbase\Mvc\View\ViewInterface::class)->getMock(); + $view = $this->getMockBuilder(ViewInterface::class)->getMock(); $this->inject($this->subject, 'view', $view); $view->expects(self::once())->method('assign')->with('location', $location); @@ -90,9 +96,9 @@ public function editActionAssignsTheGivenLocationToView() */ public function updateActionUpdatesTheGivenLocationInLocationRepository() { - $location = new \ITX\Jobapplications\Domain\Model\Location(); + $location = new Location(); - $locationRepository = $this->getMockBuilder(\ITX\Jobapplications\Domain\Repository\LocationRepository::class) + $locationRepository = $this->getMockBuilder(LocationRepository::class) ->setMethods(['update']) ->disableOriginalConstructor() ->getMock(); @@ -108,9 +114,9 @@ public function updateActionUpdatesTheGivenLocationInLocationRepository() */ public function deleteActionRemovesTheGivenLocationFromLocationRepository() { - $location = new \ITX\Jobapplications\Domain\Model\Location(); + $location = new Location(); - $locationRepository = $this->getMockBuilder(\ITX\Jobapplications\Domain\Repository\LocationRepository::class) + $locationRepository = $this->getMockBuilder(LocationRepository::class) ->setMethods(['remove']) ->disableOriginalConstructor() ->getMock(); @@ -124,7 +130,7 @@ public function deleteActionRemovesTheGivenLocationFromLocationRepository() protected function setUp() { parent::setUp(); - $this->subject = $this->getMockBuilder(\ITX\Jobapplications\Controller\LocationController::class) + $this->subject = $this->getMockBuilder(LocationController::class) ->setMethods(['redirect', 'forward', 'addFlashMessage']) ->disableOriginalConstructor() ->getMock(); diff --git a/Tests/Unit/Controller/PostingControllerTest.php b/Tests/Unit/Controller/PostingControllerTest.php index bed57eb..9f3f4d2 100644 --- a/Tests/Unit/Controller/PostingControllerTest.php +++ b/Tests/Unit/Controller/PostingControllerTest.php @@ -1,14 +1,20 @@ getMockBuilder(\TYPO3\CMS\Extbase\Persistence\ObjectStorage::class) + $allPostings = $this->getMockBuilder(ObjectStorage::class) ->disableOriginalConstructor() ->getMock(); - $postingRepository = $this->getMockBuilder(\ITX\Jobapplications\Domain\Repository\PostingRepository::class) + $postingRepository = $this->getMockBuilder(PostingRepository::class) ->setMethods(['findAll']) ->disableOriginalConstructor() ->getMock(); $postingRepository->expects(self::once())->method('findAll')->will(self::returnValue($allPostings)); $this->inject($this->subject, 'postingRepository', $postingRepository); - $view = $this->getMockBuilder(\TYPO3\CMS\Extbase\Mvc\View\ViewInterface::class)->getMock(); + $view = $this->getMockBuilder(ViewInterface::class)->getMock(); $view->expects(self::once())->method('assign')->with('postings', $allPostings); $this->inject($this->subject, 'view', $view); @@ -44,9 +50,9 @@ public function listActionFetchesAllPostingsFromRepositoryAndAssignsThemToView() */ public function showActionAssignsTheGivenPostingToView() { - $posting = new \ITX\Jobapplications\Domain\Model\Posting(); + $posting = new Posting(); - $view = $this->getMockBuilder(\TYPO3\CMS\Extbase\Mvc\View\ViewInterface::class)->getMock(); + $view = $this->getMockBuilder(ViewInterface::class)->getMock(); $this->inject($this->subject, 'view', $view); $view->expects(self::once())->method('assign')->with('posting', $posting); @@ -56,7 +62,7 @@ public function showActionAssignsTheGivenPostingToView() protected function setUp() { parent::setUp(); - $this->subject = $this->getMockBuilder(\ITX\Jobapplications\Controller\PostingController::class) + $this->subject = $this->getMockBuilder(PostingController::class) ->setMethods(['redirect', 'forward', 'addFlashMessage']) ->disableOriginalConstructor() ->getMock(); diff --git a/Tests/Unit/Domain/Model/ApplicationTest.php b/Tests/Unit/Domain/Model/ApplicationTest.php index 8cccc3f..a5f6012 100644 --- a/Tests/Unit/Domain/Model/ApplicationTest.php +++ b/Tests/Unit/Domain/Model/ApplicationTest.php @@ -1,14 +1,18 @@ subject->setCv($fileReferenceFixture); self::assertAttributeEquals( @@ -358,7 +362,7 @@ public function getCoverLetterReturnsInitialValueForFileReference() */ public function setCoverLetterForFileReferenceSetsCoverLetter() { - $fileReferenceFixture = new \TYPO3\CMS\Extbase\Domain\Model\FileReference(); + $fileReferenceFixture = new FileReference(); $this->subject->setCoverLetter($fileReferenceFixture); self::assertAttributeEquals( @@ -384,7 +388,7 @@ public function getTestimonialsReturnsInitialValueForFileReference() */ public function setTestimonialsForFileReferenceSetsTestimonials() { - $fileReferenceFixture = new \TYPO3\CMS\Extbase\Domain\Model\FileReference(); + $fileReferenceFixture = new FileReference(); $this->subject->setTestimonials($fileReferenceFixture); self::assertAttributeEquals( @@ -410,7 +414,7 @@ public function getOtherFilesReturnsInitialValueForFileReference() */ public function setOtherFilesForFileReferenceSetsOtherFiles() { - $fileReferenceFixture = new \TYPO3\CMS\Extbase\Domain\Model\FileReference(); + $fileReferenceFixture = new FileReference(); $this->subject->setOtherFiles($fileReferenceFixture); self::assertAttributeEquals( @@ -461,7 +465,7 @@ public function getPostingReturnsInitialValueForPosting() */ public function setPostingForPostingSetsPosting() { - $postingFixture = new \ITX\Jobapplications\Domain\Model\Posting(); + $postingFixture = new Posting(); $this->subject->setPosting($postingFixture); self::assertAttributeEquals( @@ -474,7 +478,7 @@ public function setPostingForPostingSetsPosting() protected function setUp() { parent::setUp(); - $this->subject = new \ITX\Jobapplications\Domain\Model\Application(); + $this->subject = new Application(); } protected function tearDown() diff --git a/Tests/Unit/Domain/Model/ContactTest.php b/Tests/Unit/Domain/Model/ContactTest.php index f19816d..71c029a 100644 --- a/Tests/Unit/Domain/Model/ContactTest.php +++ b/Tests/Unit/Domain/Model/ContactTest.php @@ -1,14 +1,16 @@ subject = new \ITX\Jobapplications\Domain\Model\Contact(); + $this->subject = new Contact(); } protected function tearDown() diff --git a/Tests/Unit/Domain/Model/LocationTest.php b/Tests/Unit/Domain/Model/LocationTest.php index b1225cd..0690386 100644 --- a/Tests/Unit/Domain/Model/LocationTest.php +++ b/Tests/Unit/Domain/Model/LocationTest.php @@ -1,14 +1,16 @@ subject = new \ITX\Jobapplications\Domain\Model\Location(); + $this->subject = new Location(); } protected function tearDown() diff --git a/Tests/Unit/Domain/Model/PostingTest.php b/Tests/Unit/Domain/Model/PostingTest.php index f37129f..df590a9 100644 --- a/Tests/Unit/Domain/Model/PostingTest.php +++ b/Tests/Unit/Domain/Model/PostingTest.php @@ -1,14 +1,19 @@ subject->setDetailViewImage($fileReferenceFixture); self::assertAttributeEquals( @@ -408,7 +413,7 @@ public function getListViewImageReturnsInitialValueForFileReference() */ public function setListViewImageForFileReferenceSetsListViewImage() { - $fileReferenceFixture = new \TYPO3\CMS\Extbase\Domain\Model\FileReference(); + $fileReferenceFixture = new FileReference(); $this->subject->setListViewImage($fileReferenceFixture); self::assertAttributeEquals( @@ -434,7 +439,7 @@ public function getLocationReturnsInitialValueForLocation() */ public function setLocationForLocationSetsLocation() { - $locationFixture = new \ITX\Jobapplications\Domain\Model\Location(); + $locationFixture = new Location(); $this->subject->setLocation($locationFixture); self::assertAttributeEquals( @@ -460,7 +465,7 @@ public function getContactReturnsInitialValueForContact() */ public function setContactForContactSetsContact() { - $contactFixture = new \ITX\Jobapplications\Domain\Model\Contact(); + $contactFixture = new Contact(); $this->subject->setContact($contactFixture); self::assertAttributeEquals( @@ -473,7 +478,7 @@ public function setContactForContactSetsContact() protected function setUp() { parent::setUp(); - $this->subject = new \ITX\Jobapplications\Domain\Model\Posting(); + $this->subject = new Posting(); } protected function tearDown() diff --git a/ext_emconf.php b/ext_emconf.php index c2654af..a5babdd 100644 --- a/ext_emconf.php +++ b/ext_emconf.php @@ -31,9 +31,7 @@ 'author_company' => 'it.x informationssysteme gmbh', 'author_email' => 'typo-itx@itx.de', 'state' => 'stable', - 'uploadfolder' => 1, - 'createDirs' => '', - 'clearCacheOnLoad' => 1, + 'clearCacheOnLoad' => true, 'version' => '1.0.4', 'constraints' => [ 'depends' => [ diff --git a/ext_localconf.php b/ext_localconf.php index 793ae1f..fc7c622 100644 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -1,56 +1,60 @@ 'list' + PostingController::class => 'list' ], // non-cacheable actions [ - 'Posting' => 'list' + PostingController::class => 'list' ] ); \TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin( - 'ITX.Jobapplications', + 'Jobapplications', 'DetailView', [ - 'Posting' => 'show', + PostingController::class => 'show', ] ); \TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin( - 'ITX.Jobapplications', + 'Jobapplications', 'ApplicationForm', [ - 'Application' => 'new, create' + ApplicationController::class => 'new, create' ], [ - 'Application' => 'create, new' + ApplicationController::class => 'create, new' ] ); \TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin( - 'ITX.Jobapplications', + 'Jobapplications', 'ContactDisplay', [ - 'Contact' => 'list' + \ITX\Jobapplications\Controller\ContactController::class => 'list' ] ); \TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin( - 'ITX.Jobapplications', + 'Jobapplications', 'SuccessPage', [ - 'Application' => 'success' + ApplicationController::class => 'success' ], [ - 'Application' => 'success' + ApplicationController::class => 'success' ] ); @@ -79,7 +83,7 @@ function () { provider = ITX\Jobapplications\PageTitle\JobsPageTitleProvider before = record after = altPageTitle - } + } } ')); $iconRegistry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Imaging\IconRegistry::class); diff --git a/ext_tables.php b/ext_tables.php index c1d4b94..3d68ee8 100644 --- a/ext_tables.php +++ b/ext_tables.php @@ -1,5 +1,5 @@ 'listApplications, dashboard, showApplication, settings' + \ITX\Jobapplications\Controller\BackendController::class => 'listApplications, dashboard, showApplication, settings' ], [ 'access' => 'user,group', From 0bafaf4015ba25f06fb123d9803e9b5c14ab02cf Mon Sep 17 00:00:00 2001 From: sdl Date: Mon, 10 Jan 2022 21:23:59 +0100 Subject: [PATCH 15/61] changed version and removed vhs dependencies --- Documentation/Introduction/Index.rst | 4 +- .../Private/Partials/Posting/MetaTags.html | 17 +- .../Private/Templates/Application/New.html | 10 +- .../Templates/Application/Success.html | 13 +- .../Templates/Mail/JobsApplicantMail.html | 13 +- .../Templates/Mail/JobsApplicantMail.txt | 10 +- Resources/Private/Templates/Posting/List.html | 20 +- composer.json | 7 +- ext_emconf.php | 3 +- .../Traits/PageRendererTrait.php | 33 ++++ .../Traits/TagViewHelperTrait.php | 174 ++++++++++++++++++ 11 files changed, 254 insertions(+), 50 deletions(-) create mode 100644 packages/jobapplications/Traits/PageRendererTrait.php create mode 100644 packages/jobapplications/Traits/TagViewHelperTrait.php diff --git a/Documentation/Introduction/Index.rst b/Documentation/Introduction/Index.rst index 3c0b85e..503cfe7 100644 --- a/Documentation/Introduction/Index.rst +++ b/Documentation/Introduction/Index.rst @@ -31,7 +31,7 @@ Manage job postings * write your own page title for the detail page by using placeholders * use **frontend filters** for job posting attributes "Division", "Career Level", "Emplyoment Type" and "Location" * time at which date the posting should go live and possibly end - * support for **typo3 categories** + * support for **TYPO3 categories** * OpenGraph data automatically populated * Structured data for **Google Jobs integration** * **Google Indexing API Implementation** for Google Jobs: Sends crawl requests automatically when editing a job posting, so Google Jobs always has the latest data @@ -41,7 +41,7 @@ Application Form * **fully fledged application form** with standard fields like name, email, phone, address as well as optional fields like "Salary Expectation", "Earliest Date of Joining" and a "Message" field. * supports pdf file uploads - * have a four single file upload fields or one multi file upload field + * have four single file upload fields or one multi file upload field * privacy agreement checkbox, which links to your privacy agreement page * forward the applicant to a success page with a customized message which again supports placeholders for the applicants name diff --git a/Resources/Private/Partials/Posting/MetaTags.html b/Resources/Private/Partials/Posting/MetaTags.html index 434460f..5fa8c22 100644 --- a/Resources/Private/Partials/Posting/MetaTags.html +++ b/Resources/Private/Partials/Posting/MetaTags.html @@ -1,10 +1,15 @@ + xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" + xmlns:jobs="http://typo3.org/ns/ITX/Jobapplications/ViewHelpers"> - - - + + + - - + + to Do: + replace url + + + \ No newline at end of file diff --git a/Resources/Private/Templates/Application/New.html b/Resources/Private/Templates/Application/New.html index c8c7bf9..e484773 100644 --- a/Resources/Private/Templates/Application/New.html +++ b/Resources/Private/Templates/Application/New.html @@ -1,12 +1,10 @@ - + - - - - - + + +
diff --git a/Resources/Private/Templates/Application/Success.html b/Resources/Private/Templates/Application/Success.html index b28f8bb..bdd427f 100644 --- a/Resources/Private/Templates/Application/Success.html +++ b/Resources/Private/Templates/Application/Success.html @@ -1,21 +1,20 @@ + xmlns:jobs="http://typo3.org/ns/ITX/Jobapplications/ViewHelpers"> - - - + + + - + - + diff --git a/Resources/Private/Templates/Mail/JobsApplicantMail.html b/Resources/Private/Templates/Mail/JobsApplicantMail.html index 63003b0..4431f94 100644 --- a/Resources/Private/Templates/Mail/JobsApplicantMail.html +++ b/Resources/Private/Templates/Mail/JobsApplicantMail.html @@ -1,7 +1,6 @@ + xmlns:jobs="http://typo3.org/ns/ITX/Jobapplications/ViewHelpers"> @@ -14,7 +13,7 @@ - + {titleBar} @@ -27,8 +26,8 @@ - - + + @@ -38,9 +37,9 @@ - + - + {msg} diff --git a/Resources/Private/Templates/Mail/JobsApplicantMail.txt b/Resources/Private/Templates/Mail/JobsApplicantMail.txt index dc3af1f..48011f6 100644 --- a/Resources/Private/Templates/Mail/JobsApplicantMail.txt +++ b/Resources/Private/Templates/Mail/JobsApplicantMail.txt @@ -6,9 +6,9 @@ - - - + + + @@ -17,8 +17,8 @@ - - + + {titleBar} \ No newline at end of file diff --git a/Resources/Private/Templates/Posting/List.html b/Resources/Private/Templates/Posting/List.html index 22ba988..4dde4a4 100644 --- a/Resources/Private/Templates/Posting/List.html +++ b/Resources/Private/Templates/Posting/List.html @@ -3,11 +3,9 @@ - - - - - + + +
@@ -25,9 +23,9 @@

- + - {division} + {division} @@ -37,9 +35,9 @@

- + - {careerLevel} + {careerLevel} @@ -51,7 +49,7 @@

- + @@ -64,7 +62,7 @@

- {location.name} + {location.name}

diff --git a/composer.json b/composer.json index 17940ff..4e9ab84 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,7 @@ "type": "typo3-cms-extension", "description": "This extension enables you to manage job postings, has an application form for applicants to apply and an Application Managment Backend Module", "license": "GPL-3.0-or-later", - "version": "1.0.4", + "version": "2.0.0", "homepage": "http://www.itx.de", "authors": [ { @@ -23,10 +23,9 @@ "docs": "https://docs.typo3.org/p/itx/jobapplications/master/en-us/" }, "require": { - "typo3/cms-core": "^10.4", + "typo3/cms-core": "^10.4 || ^11.5", "typo3/cms-scheduler": "*", - "typo3/cms-dashboard": "*", - "fluidtypo3/vhs": "^6" + "typo3/cms-dashboard": "*" }, "require-dev": { "phpstan/phpstan": "^1.2" diff --git a/ext_emconf.php b/ext_emconf.php index a5babdd..39cff24 100644 --- a/ext_emconf.php +++ b/ext_emconf.php @@ -35,8 +35,7 @@ 'version' => '1.0.4', 'constraints' => [ 'depends' => [ - 'typo3' => '9.5.0 - 10.4.99', - 'vhs' => '6.0.0 - 6.2.99' + 'typo3' => '10.4.13-11.9.99' ], 'conflicts' => [], 'suggests' => [], diff --git a/packages/jobapplications/Traits/PageRendererTrait.php b/packages/jobapplications/Traits/PageRendererTrait.php new file mode 100644 index 0000000..d6bd440 --- /dev/null +++ b/packages/jobapplications/Traits/PageRendererTrait.php @@ -0,0 +1,33 @@ +registerUniversalTagAttributes(); + } + + /** + * Registers all standard and HTML5 universal attributes. + * Should be used inside registerArguments(); + * + * @return void + * @api + */ + protected function registerUniversalTagAttributes() + { + parent::registerUniversalTagAttributes(); + $this->registerArgument( + 'forceClosingTag', + 'boolean', + 'If TRUE, forces the created tag to use a closing tag. If FALSE, allows self-closing tags.', + false, + false + ); + $this->registerArgument( + 'hideIfEmpty', + 'boolean', + 'Hide the tag completely if there is no tag content', + false, + false + ); + $this->registerTagAttribute( + 'contenteditable', + 'string', + 'Specifies whether the contents of the element are editable.' + ); + $this->registerTagAttribute( + 'contextmenu', + 'string', + 'The value of the id attribute on the menu with which to associate the element as a context menu.' + ); + $this->registerTagAttribute( + 'draggable', + 'string', + 'Specifies whether the element is draggable.' + ); + $this->registerTagAttribute( + 'dropzone', + 'string', + 'Specifies what types of content can be dropped on the element, and instructs the UA about which ' . + 'actions to take with content when it is dropped on the element.' + ); + $this->registerTagAttribute( + 'translate', + 'string', + 'Specifies whether an element’s attribute values and contents of its children are to be translated ' . + 'when the page is localized, or whether to leave them unchanged.' + ); + $this->registerTagAttribute( + 'spellcheck', + 'string', + 'Specifies whether the element represents an element whose contents are subject to spell checking and ' . + 'grammar checking.' + ); + $this->registerTagAttribute( + 'hidden', + 'string', + 'Specifies that the element represents an element that is not yet, or is no longer, relevant.' + ); + } + + /** + * Renders the provided tag with the given name and any + * (additional) attributes not already provided as arguments. + * + * @param string $tagName + * @param mixed $content + * @param array $attributes + * @param array $nonEmptyAttributes + * @return string + */ + protected function renderTag( + $tagName, + $content = null, + array $attributes = [], + array $nonEmptyAttributes = ['id', 'class'] + ) { + $trimmedContent = trim((string) $content); + $forceClosingTag = (boolean) $this->arguments['forceClosingTag']; + if (true === empty($trimmedContent) && true === (boolean) $this->arguments['hideIfEmpty']) { + return ''; + } + if ('none' === $tagName || true === empty($tagName)) { + // skip building a tag if special keyword "none" is used, or tag name is empty + return $trimmedContent; + } + $this->tag->setTagName($tagName); + $this->tag->addAttributes($attributes); + $this->tag->forceClosingTag($forceClosingTag); + if (null !== $content) { + $this->tag->setContent($trimmedContent); + } + // process some attributes differently - if empty, remove the property: + foreach ($nonEmptyAttributes as $propertyName) { + $value = $this->arguments[$propertyName]; + if (true === empty($value)) { + $this->tag->removeAttribute($propertyName); + } else { + $this->tag->addAttribute($propertyName, $value); + } + } + return $this->tag->render(); + } + + /** + * Renders the provided tag and optionally appends or prepends + * it to the main tag's content depending on 'mode' which can + * be one of 'none', 'append' or 'prepend' + * + * @param string $tagName + * @param array $attributes + * @param boolean $forceClosingTag + * @param string $mode + * @return string + */ + protected function renderChildTag($tagName, $attributes = [], $forceClosingTag = false, $mode = 'none') + { + $tagBuilder = clone $this->tag; + $tagBuilder->reset(); + $tagBuilder->setTagName($tagName); + $tagBuilder->addAttributes($attributes); + $tagBuilder->forceClosingTag($forceClosingTag); + $childTag = $tagBuilder->render(); + if ('append' === $mode || 'prepend' === $mode) { + $content = $this->tag->getContent(); + if ('append' === $mode) { + $content = $content . $childTag; + } else { + $content = $childTag . $content; + } + $this->tag->setContent($content); + } + return $childTag; + } +} From 998f0c3c95a95b5eb627bc64c1983a8db4b2aef9 Mon Sep 17 00:00:00 2001 From: sdl Date: Mon, 10 Jan 2022 21:25:08 +0100 Subject: [PATCH 16/61] added new viewhelper --- .../Condition/InArrayViewhelper.php | 46 ++++++ .../Format/ReplaceStringViewhelpher.php | 34 ++++ .../ViewHelpers/GroupByCategoryViewHelper.php | 145 ++++++++++++++++++ .../Page/Header/MetaViewHelper.php | 95 ++++++++++++ ext_emconf.php | 2 +- 5 files changed, 321 insertions(+), 1 deletion(-) create mode 100644 Classes/ViewHelpers/ViewHelpers/Condition/InArrayViewhelper.php create mode 100644 Classes/ViewHelpers/ViewHelpers/Format/ReplaceStringViewhelpher.php create mode 100644 Classes/ViewHelpers/ViewHelpers/GroupByCategoryViewHelper.php create mode 100644 Classes/ViewHelpers/ViewHelpers/Page/Header/MetaViewHelper.php diff --git a/Classes/ViewHelpers/ViewHelpers/Condition/InArrayViewhelper.php b/Classes/ViewHelpers/ViewHelpers/Condition/InArrayViewhelper.php new file mode 100644 index 0000000..2c49fbc --- /dev/null +++ b/Classes/ViewHelpers/ViewHelpers/Condition/InArrayViewhelper.php @@ -0,0 +1,46 @@ +registerArgument('haystack', 'mixed', 'View helper haystack ', true); + $this->registerArgument('needle', 'string', 'View helper needle', true); + } + + // php in_array viewhelper + public function render() + { + + $needle = $this->arguments['needle']; + $haystack = $this->arguments['haystack']; + + if (!is_array($haystack)) + { + return $this->renderElseChild(); + } + + if (in_array($needle, $haystack)) + { + return $this->renderThenChild(); + } + else + { + return $this->renderElseChild(); + } + } + } \ No newline at end of file diff --git a/Classes/ViewHelpers/ViewHelpers/Format/ReplaceStringViewhelpher.php b/Classes/ViewHelpers/ViewHelpers/Format/ReplaceStringViewhelpher.php new file mode 100644 index 0000000..17c47b3 --- /dev/null +++ b/Classes/ViewHelpers/ViewHelpers/Format/ReplaceStringViewhelpher.php @@ -0,0 +1,34 @@ +registerArgument('substring', 'string', 'View helper substring ', TRUE); + $this->registerArgument('content', 'string', 'View helper content', TRUE); + $this->registerArgument('replacement', 'string', 'View helper replacement', TRUE); + } + + /** + * Render method + * + * @return string + */ + public function render() + { + return str_replace($this->arguments['substring'], $this->arguments['replacement'], $this->arguments['content']); + } + } \ No newline at end of file diff --git a/Classes/ViewHelpers/ViewHelpers/GroupByCategoryViewHelper.php b/Classes/ViewHelpers/ViewHelpers/GroupByCategoryViewHelper.php new file mode 100644 index 0000000..a8b06f1 --- /dev/null +++ b/Classes/ViewHelpers/ViewHelpers/GroupByCategoryViewHelper.php @@ -0,0 +1,145 @@ +getVariableProvider(); + if (!isset($arguments['postings'])) + { + return ''; + } + if (is_object($arguments['postings']) && !$arguments['postings'] instanceof \Traversable) + { + throw new Exception('GroupByCategoryViewHelper only supports arrays and objects implementing \Traversable interface', 1248728393); + } + + $iterationData = []; + if (isset($arguments['iteration'])) + { + $iterationData = [ + 'index' => 0, + 'cycle' => 1, + 'total' => count($arguments['postings']) + ]; + } + + /** Postings grouped by category */ + $groupCategoriesList = []; + $groupPostingsList = []; + $uncategorizedPostings = []; + foreach ($arguments['postings'] as $posting) + { + /** @var $posting Posting */ + $categories = $posting->getCategories()->toArray(); + $hasCategories = false; + foreach ($categories as $category) + { + $hasCategories = true; + + if (empty($arguments['categoryRestriction']) || in_array((string)$category->getUid(), $arguments['categoryRestriction'], true)) + { + /** @var $category Category */ + if (!array_key_exists($category->getUid(), $groupCategoriesList)) + { + $groupCategoriesList[$category->getUid()] = $category; + } + + $groupPostingsList[$category->getUid()][] = $posting; + } + } + + if ($hasCategories === false) + { + $uncategorizedPostings[] = $posting; + } + } + + $output = ''; + foreach ($groupPostingsList as $categoryUid => $postingArray) + { + $templateVariableContainer->add($arguments['groupAs'], $postingArray); + $templateVariableContainer->add($arguments['categoryAs'], $groupCategoriesList[$categoryUid]); + if (isset($arguments['key'])) + { + $templateVariableContainer->add($arguments['key'], $categoryUid); + } + if (isset($arguments['iteration'])) + { + $iterationData['isFirst'] = $iterationData['cycle'] === 1; + $iterationData['isLast'] = $iterationData['cycle'] === $iterationData['total']; + $iterationData['isEven'] = $iterationData['cycle'] % 2 === 0; + $iterationData['isOdd'] = !$iterationData['isEven']; + $templateVariableContainer->add($arguments['iteration'], $iterationData); + $iterationData['index']++; + $iterationData['cycle']++; + } + $output .= $renderChildrenClosure(); + $templateVariableContainer->remove($arguments['groupAs']); + $templateVariableContainer->remove($arguments['categoryAs']); + if (isset($arguments['key'])) + { + $templateVariableContainer->remove($arguments['key']); + } + if (isset($arguments['iteration'])) + { + $templateVariableContainer->remove($arguments['iteration']); + } + } + + $templateVariableContainer->add($arguments['uncategorized'], $uncategorizedPostings); + + return $output; + } + + /** + * @return void + */ + public function initializeArguments() + { + parent::initializeArguments(); + $this->registerArgument('postings', 'array', 'The postings to group', true); + $this->registerArgument('groupAs', 'string', 'The name of the group iteration variable', true); + $this->registerArgument('categoryAs', 'string', 'Variable to current category to', true); + $this->registerArgument('categoryRestriction', 'array', 'Restrict categories to specific categories'); + $this->registerArgument('key', 'string', 'Variable to assign current key to', false); + $this->registerArgument('iteration', 'string', 'The name of the variable to store iteration information (index, cycle, isFirst, isLast, isEven, isOdd)'); + $this->registerArgument('uncategorized', 'string', 'The name of the variable to store uncategorized postings in'); + } + } diff --git a/Classes/ViewHelpers/ViewHelpers/Page/Header/MetaViewHelper.php b/Classes/ViewHelpers/ViewHelpers/Page/Header/MetaViewHelper.php new file mode 100644 index 0000000..41f27b3 --- /dev/null +++ b/Classes/ViewHelpers/ViewHelpers/Page/Header/MetaViewHelper.php @@ -0,0 +1,95 @@ +registerTagAttribute('name', 'string', 'Name property of meta tag'); + $this->registerTagAttribute('http-equiv', 'string', 'Property: http-equiv'); + $this->registerTagAttribute('property', 'string', 'Property of meta tag'); + $this->registerTagAttribute('content', 'string', 'Content of meta tag'); + $this->registerTagAttribute('scheme', 'string', 'Property: scheme'); + $this->registerTagAttribute('lang', 'string', 'Property: lang'); + $this->registerTagAttribute('dir', 'string', 'Property: dir'); + } + + /** + * Render method + * + * @return void + */ + public function render() + { + if ('BE' === TYPO3_MODE) + { + return; + } + $content = $this->arguments['content']; + if (!empty($content)) + { + $pageRenderer = static::getPageRenderer(); + if (!method_exists($pageRenderer, 'setMetaTag')) + { + $pageRenderer->addMetaTag($this->renderTag($this->tagName, null, ['content' => $content])); + } + else + { + $properties = []; + $type = 'name'; + $name = $this->tag->getAttribute('name'); + if (!empty($this->tag->getAttribute('property'))) + { + $type = 'property'; + $name = $this->tag->getAttribute('property'); + } + elseif (!empty($this->tag->getAttribute('http-equiv'))) + { + $type = 'http-equiv'; + $name = $this->tag->getAttribute('http-equiv'); + } + foreach (['http-equiv', 'property', 'scheme', 'lang', 'dir'] as $propertyName) + { + if (!empty($this->tag->getAttribute($propertyName))) + { + $properties[$propertyName] = $this->tag->getAttribute($propertyName); + } + } + $pageRenderer->setMetaTag($type, $name, $content, $properties); + } + } + } + } diff --git a/ext_emconf.php b/ext_emconf.php index 39cff24..27c57de 100644 --- a/ext_emconf.php +++ b/ext_emconf.php @@ -32,7 +32,7 @@ 'author_email' => 'typo-itx@itx.de', 'state' => 'stable', 'clearCacheOnLoad' => true, - 'version' => '1.0.4', + 'version' => '2.0.0', 'constraints' => [ 'depends' => [ 'typo3' => '10.4.13-11.9.99' From eb54988bb70776df1c30cc09e7cfdab26ed89170 Mon Sep 17 00:00:00 2001 From: Benjamin Jasper Date: Thu, 3 Mar 2022 09:37:26 +0100 Subject: [PATCH 17/61] fix: set static analysis to php 8 --- .github/workflows/static-analysis.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/static-analysis.yaml b/.github/workflows/static-analysis.yaml index 2663b37..049b0c1 100644 --- a/.github/workflows/static-analysis.yaml +++ b/.github/workflows/static-analysis.yaml @@ -16,7 +16,7 @@ jobs: ${{ runner.os }}-composer- - uses: shivammathur/setup-php@v2 with: - php-version: 7.3 + php-version: 8.0 coverage: none - run: composer install --no-progress From f4a0a0ffc50eed6f57e44d3a1d1724a340b84334 Mon Sep 17 00:00:00 2001 From: Benjamin Jasper Date: Thu, 3 Mar 2022 09:38:24 +0100 Subject: [PATCH 18/61] fix: fixed static analysis --- .github/workflows/static-analysis.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/static-analysis.yaml b/.github/workflows/static-analysis.yaml index 049b0c1..76ebf6e 100644 --- a/.github/workflows/static-analysis.yaml +++ b/.github/workflows/static-analysis.yaml @@ -1,3 +1,6 @@ +name: Static analysis + +on: [ push, pull_request ] jobs: phpstan: From ef9f0a61cb5f4a8d1974a83eedf52598c08f4833 Mon Sep 17 00:00:00 2001 From: Benjamin Jasper Date: Thu, 3 Mar 2022 09:41:17 +0100 Subject: [PATCH 19/61] fix: fixed position of traits --- .../jobapplications => Classes}/Traits/PageRendererTrait.php | 0 .../jobapplications => Classes}/Traits/TagViewHelperTrait.php | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {packages/jobapplications => Classes}/Traits/PageRendererTrait.php (100%) rename {packages/jobapplications => Classes}/Traits/TagViewHelperTrait.php (100%) diff --git a/packages/jobapplications/Traits/PageRendererTrait.php b/Classes/Traits/PageRendererTrait.php similarity index 100% rename from packages/jobapplications/Traits/PageRendererTrait.php rename to Classes/Traits/PageRendererTrait.php diff --git a/packages/jobapplications/Traits/TagViewHelperTrait.php b/Classes/Traits/TagViewHelperTrait.php similarity index 100% rename from packages/jobapplications/Traits/TagViewHelperTrait.php rename to Classes/Traits/TagViewHelperTrait.php From b32ff019a94a0df0693bcb205ebb51f9dab8bcd9 Mon Sep 17 00:00:00 2001 From: Benjamin Jasper Date: Thu, 3 Mar 2022 09:43:20 +0100 Subject: [PATCH 20/61] fix: fixed new viewhelper --- .../ViewHelpers/ViewHelpers/Page/Header/MetaViewHelper.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Classes/ViewHelpers/ViewHelpers/Page/Header/MetaViewHelper.php b/Classes/ViewHelpers/ViewHelpers/Page/Header/MetaViewHelper.php index 41f27b3..fa7aaab 100644 --- a/Classes/ViewHelpers/ViewHelpers/Page/Header/MetaViewHelper.php +++ b/Classes/ViewHelpers/ViewHelpers/Page/Header/MetaViewHelper.php @@ -54,10 +54,6 @@ public function initializeArguments() */ public function render() { - if ('BE' === TYPO3_MODE) - { - return; - } $content = $this->arguments['content']; if (!empty($content)) { From f127dde30832ef2ebe434130d19769cfdb2f6fb8 Mon Sep 17 00:00:00 2001 From: Benjamin Jasper Date: Thu, 3 Mar 2022 10:32:49 +0100 Subject: [PATCH 21/61] fix: fixed a few issues --- .../Condition/InArrayViewhelper.php | 2 +- .../ReplaceStringViewHelper.php} | 0 .../Page/Header/MetaViewHelper.php | 0 .../ViewHelpers/GroupByCategoryViewHelper.php | 145 ------------------ Configuration/Services.yaml | 12 +- ext_localconf.php | 2 +- 6 files changed, 12 insertions(+), 149 deletions(-) rename Classes/ViewHelpers/{ViewHelpers => }/Condition/InArrayViewhelper.php (94%) rename Classes/ViewHelpers/{ViewHelpers/Format/ReplaceStringViewhelpher.php => Format/ReplaceStringViewHelper.php} (100%) rename Classes/ViewHelpers/{ViewHelpers => }/Page/Header/MetaViewHelper.php (100%) delete mode 100644 Classes/ViewHelpers/ViewHelpers/GroupByCategoryViewHelper.php diff --git a/Classes/ViewHelpers/ViewHelpers/Condition/InArrayViewhelper.php b/Classes/ViewHelpers/Condition/InArrayViewhelper.php similarity index 94% rename from Classes/ViewHelpers/ViewHelpers/Condition/InArrayViewhelper.php rename to Classes/ViewHelpers/Condition/InArrayViewhelper.php index 2c49fbc..e824e21 100644 --- a/Classes/ViewHelpers/ViewHelpers/Condition/InArrayViewhelper.php +++ b/Classes/ViewHelpers/Condition/InArrayViewhelper.php @@ -1,6 +1,6 @@ getVariableProvider(); - if (!isset($arguments['postings'])) - { - return ''; - } - if (is_object($arguments['postings']) && !$arguments['postings'] instanceof \Traversable) - { - throw new Exception('GroupByCategoryViewHelper only supports arrays and objects implementing \Traversable interface', 1248728393); - } - - $iterationData = []; - if (isset($arguments['iteration'])) - { - $iterationData = [ - 'index' => 0, - 'cycle' => 1, - 'total' => count($arguments['postings']) - ]; - } - - /** Postings grouped by category */ - $groupCategoriesList = []; - $groupPostingsList = []; - $uncategorizedPostings = []; - foreach ($arguments['postings'] as $posting) - { - /** @var $posting Posting */ - $categories = $posting->getCategories()->toArray(); - $hasCategories = false; - foreach ($categories as $category) - { - $hasCategories = true; - - if (empty($arguments['categoryRestriction']) || in_array((string)$category->getUid(), $arguments['categoryRestriction'], true)) - { - /** @var $category Category */ - if (!array_key_exists($category->getUid(), $groupCategoriesList)) - { - $groupCategoriesList[$category->getUid()] = $category; - } - - $groupPostingsList[$category->getUid()][] = $posting; - } - } - - if ($hasCategories === false) - { - $uncategorizedPostings[] = $posting; - } - } - - $output = ''; - foreach ($groupPostingsList as $categoryUid => $postingArray) - { - $templateVariableContainer->add($arguments['groupAs'], $postingArray); - $templateVariableContainer->add($arguments['categoryAs'], $groupCategoriesList[$categoryUid]); - if (isset($arguments['key'])) - { - $templateVariableContainer->add($arguments['key'], $categoryUid); - } - if (isset($arguments['iteration'])) - { - $iterationData['isFirst'] = $iterationData['cycle'] === 1; - $iterationData['isLast'] = $iterationData['cycle'] === $iterationData['total']; - $iterationData['isEven'] = $iterationData['cycle'] % 2 === 0; - $iterationData['isOdd'] = !$iterationData['isEven']; - $templateVariableContainer->add($arguments['iteration'], $iterationData); - $iterationData['index']++; - $iterationData['cycle']++; - } - $output .= $renderChildrenClosure(); - $templateVariableContainer->remove($arguments['groupAs']); - $templateVariableContainer->remove($arguments['categoryAs']); - if (isset($arguments['key'])) - { - $templateVariableContainer->remove($arguments['key']); - } - if (isset($arguments['iteration'])) - { - $templateVariableContainer->remove($arguments['iteration']); - } - } - - $templateVariableContainer->add($arguments['uncategorized'], $uncategorizedPostings); - - return $output; - } - - /** - * @return void - */ - public function initializeArguments() - { - parent::initializeArguments(); - $this->registerArgument('postings', 'array', 'The postings to group', true); - $this->registerArgument('groupAs', 'string', 'The name of the group iteration variable', true); - $this->registerArgument('categoryAs', 'string', 'Variable to current category to', true); - $this->registerArgument('categoryRestriction', 'array', 'Restrict categories to specific categories'); - $this->registerArgument('key', 'string', 'Variable to assign current key to', false); - $this->registerArgument('iteration', 'string', 'The name of the variable to store iteration information (index, cycle, isFirst, isLast, isEven, isOdd)'); - $this->registerArgument('uncategorized', 'string', 'The name of the variable to store uncategorized postings in'); - } - } diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml index 283dd83..93a8639 100644 --- a/Configuration/Services.yaml +++ b/Configuration/Services.yaml @@ -1,13 +1,21 @@ # Variant 1, widget identifier as attribute services: + _defaults: + autowire: true + autoconfigure: true + public: false + + ITX\Jobapplications\: + resource: '../Classes/*' + exclude: + - '../Classes/Domain/Model/*' + ITX\Jobapplications\Widgets\Provider\PostingsActiveProvider: ITX\Jobapplications\Widgets\Provider\ApplicationsPerPostingBarChartProvider: ITX\Jobapplications\Widgets\Provider\BackendModuleButtonProvider: arguments: - $title: '' - $link: '' $target: '' dashboard.widget.postingsActive: diff --git a/ext_localconf.php b/ext_localconf.php index fc7c622..92f5181 100644 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -133,7 +133,7 @@ function () { $GLOBALS['TYPO3_CONF_VARS']['FE']['eID_include']['jobapplications_revert'] = \ITX\Jobapplications\Controller\AjaxController::class.'::revertAction'; // Cache - if (!is_array($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['jobapplications_cache'])) + if (!isset($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['jobapplications_cache']) || !is_array($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['jobapplications_cache'])) { $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['jobapplications_cache'] = []; } From 4cbf36b4e20269fb3d79800c6b9f465d69f4d327 Mon Sep 17 00:00:00 2001 From: Benjamin Jasper Date: Thu, 3 Mar 2022 11:35:36 +0100 Subject: [PATCH 22/61] fix: added first php 8 fixes --- Classes/Controller/ApplicationController.php | 2 +- Classes/Controller/PostingController.php | 8 ++++---- .../Private/Partials/Posting/MetaTags.html | 6 ++++-- Resources/Private/Templates/Posting/List.html | 20 +++++++++---------- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Classes/Controller/ApplicationController.php b/Classes/Controller/ApplicationController.php index 9289304..de198f6 100644 --- a/Classes/Controller/ApplicationController.php +++ b/Classes/Controller/ApplicationController.php @@ -349,7 +349,7 @@ public function createAction(Application $newApplication, Posting $posting = nul } // Check which kind of uploads were sent - if ($this->isStringArray($arguments['files'])) + if ($this->isStringArray($arguments['files'] ?? [])) { $uploadMode = self::UPLOAD_MODE_FILES; } diff --git a/Classes/Controller/PostingController.php b/Classes/Controller/PostingController.php index 73094cd..9a6a643 100644 --- a/Classes/Controller/PostingController.php +++ b/Classes/Controller/PostingController.php @@ -198,10 +198,10 @@ private function getCachedFilterOptions($categories): array public function getFilterOptions($categories): array { return [ - 'division' => $this->postingRepository->findAllDivisions($categories), - 'careerLevel' => $this->postingRepository->findAllCareerLevels($categories), - 'employmentType' => $this->postingRepository->findAllEmploymentTypes($categories), - 'location' => $this->locationRepository->findAll($categories)->toArray(), + //'division' => $this->postingRepository->findAllDivisions($categories), + //'careerLevel' => $this->postingRepository->findAllCareerLevels($categories), + //'employmentType' => $this->postingRepository->findAllEmploymentTypes($categories), + //'location' => $this->locationRepository->findAll($categories)->toArray(), ]; } diff --git a/Resources/Private/Partials/Posting/MetaTags.html b/Resources/Private/Partials/Posting/MetaTags.html index 5fa8c22..54181c6 100644 --- a/Resources/Private/Partials/Posting/MetaTags.html +++ b/Resources/Private/Partials/Posting/MetaTags.html @@ -6,10 +6,12 @@ - + \ No newline at end of file diff --git a/Resources/Private/Templates/Posting/List.html b/Resources/Private/Templates/Posting/List.html index 4dde4a4..ddaf2a3 100644 --- a/Resources/Private/Templates/Posting/List.html +++ b/Resources/Private/Templates/Posting/List.html @@ -25,7 +25,7 @@

- {division} + {division} @@ -37,7 +37,7 @@

- {careerLevel} + {careerLevel} @@ -49,7 +49,7 @@

- + @@ -62,7 +62,7 @@

- {location.name} + {location.name}

@@ -81,13 +81,11 @@

- -
- - - -
-
+
+ + + +
From cd69f84951ebfab6d08d8286810d7726673d4ac1 Mon Sep 17 00:00:00 2001 From: Benjamin Jasper Date: Thu, 3 Mar 2022 15:15:25 +0100 Subject: [PATCH 23/61] fix: replaced objectManager where possible --- Classes/Controller/ApplicationController.php | 53 ++++--- Classes/Controller/BackendController.php | 17 +-- Classes/Hooks/TCEmainHook.php | 58 ++++---- Classes/Service/ApplicationFileService.php | 67 +++++---- Classes/Task/AnonymizeApplications.php | 55 +++++--- Classes/Task/CleanUpApplications.php | 47 ++++--- .../Utility/GoogleIndexingApiConnector.php | 130 +++++++++--------- .../ViewHelpers/GroupByCategoryViewHelper.php | 8 +- ...ApplicationsPerPostingBarChartProvider.php | 24 ++-- .../Provider/PostingsActiveProvider.php | 17 ++- Configuration/Services.yaml | 1 - .../Templates/Backend/ListApplications.html | 5 +- Resources/Private/Templates/Posting/List.html | 1 + Resources/Public/Css/backend.css | 2 +- Resources/Public/Css/backend.less | 3 +- composer.json | 1 + 16 files changed, 262 insertions(+), 227 deletions(-) diff --git a/Classes/Controller/ApplicationController.php b/Classes/Controller/ApplicationController.php index 59c6f85..fc3c47e 100644 --- a/Classes/Controller/ApplicationController.php +++ b/Classes/Controller/ApplicationController.php @@ -24,41 +24,42 @@ * * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ - use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; - use TYPO3\CMS\Core\Log\LogManager; - use Psr\Http\Message\ResponseInterface; + + use ITX\Jobapplications\Domain\Model\Application; use ITX\Jobapplications\Domain\Model\Contact; - use TYPO3\CMS\Core\Resource\Driver\LocalDriver; + use ITX\Jobapplications\Domain\Model\Posting; + use ITX\Jobapplications\Domain\Model\Status; use ITX\Jobapplications\Domain\Repository\ApplicationRepository; - use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager; - use ITX\Jobapplications\Service\ApplicationFileService; - use TYPO3\CMS\Extbase\SignalSlot\Dispatcher; use ITX\Jobapplications\Domain\Repository\PostingRepository; use ITX\Jobapplications\Domain\Repository\StatusRepository; - use ITX\Jobapplications\Domain\Model\Application; - use ITX\Jobapplications\Domain\Model\Posting; - use ITX\Jobapplications\Domain\Model\Status; use ITX\Jobapplications\PageTitle\JobsPageTitleProvider; + use ITX\Jobapplications\Service\ApplicationFileService; use ITX\Jobapplications\Utility\Mail\MailInterface; use ITX\Jobapplications\Utility\Typo3VersionUtility; use ITX\Jobapplications\Utility\UploadFileUtility; + use Psr\Http\Message\ResponseInterface; use Psr\Log\LogLevel; use Symfony\Component\Mime\Address; use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Localization\Exception\FileNotFoundException; + use TYPO3\CMS\Core\Log\LogManager; use TYPO3\CMS\Core\Mail\FluidEmail; use TYPO3\CMS\Core\Mail\Mailer; use TYPO3\CMS\Core\Messaging\FlashMessage; + use TYPO3\CMS\Core\Resource\Driver\LocalDriver; use TYPO3\CMS\Core\Resource\File; use TYPO3\CMS\Core\Resource\FileInterface; - use TYPO3\CMS\Core\Resource\ResourceStorageInterface; use TYPO3\CMS\Core\Resource\ResourceStorage; + use TYPO3\CMS\Core\Resource\ResourceStorageInterface; use TYPO3\CMS\Core\Resource\StorageRepository; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\MathUtility; + use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; use TYPO3\CMS\Extbase\Mvc\View\ViewInterface; + use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager; use TYPO3\CMS\Extbase\Property\TypeConverter\DateTimeConverter; + use TYPO3\CMS\Extbase\SignalSlot\Dispatcher; use TYPO3\CMS\Extbase\Utility\LocalizationUtility; /** @@ -111,6 +112,13 @@ class ApplicationController extends ActionController */ private $statusRepository; + protected StorageRepository $storageRepository; + + public function __construct(StorageRepository $storageRepository) + { + $this->storageRepository = $storageRepository; + } + /** * initialize create action * adjusts date time format to y-m-d @@ -222,6 +230,7 @@ public function newAction(Posting $posting = null): ResponseInterface { $this->view->assign("fileError", 0); } + return $this->htmlResponse(); } @@ -259,6 +268,7 @@ public function successAction($firstName, $lastName, $salutation, $problems, $po $this->view->assign('salutation', $salutation); $this->view->assign('problems', $problems); $posting ? $this->view->assign('salutationValue', $salutationValue) : false; + return $this->htmlResponse(); } @@ -455,7 +465,7 @@ public function createAction(Application $newApplication, Posting $posting = nul { if ($file instanceof FileInterface) { - $mail->attach($file->getForLocalProcessing(false)); + $mail->attachFromPath($file->getForLocalProcessing(false)); } } } @@ -464,21 +474,21 @@ public function createAction(Application $newApplication, Posting $posting = nul { if ($file instanceof FileInterface) { - $mail->attach($file->getForLocalProcessing(false)); + $mail->attachFromPath($file->getForLocalProcessing(false)); } } //Figure out who the email will be sent to and how - if ($this->settings['sendEmailToInternal'] != "" && $this->settings['sendEmailToContact'] == "1") + if ($this->settings['sendEmailToInternal'] !== "" && $this->settings['sendEmailToContact'] === '1') { $mail->to(new Address($contact->getEmail(), $contact->getFirstName().' '.$contact->getLastName())); $mail->bcc(new Address($this->settings['sendEmailToInternal'])); } - else if ($this->settings['sendEmailToContact'] != "1" && $this->settings['sendEmailToInternal'] != "") + else if ($this->settings['sendEmailToContact'] !== '1' && $this->settings['sendEmailToInternal'] !== "") { $mail->to(new Address($this->settings['sendEmailToInternal'], 'Internal')); } - else if ($this->settings['sendEmailToContact'] == "1" && $this->settings['sendEmailToInternal'] != "1") + else if ($this->settings['sendEmailToContact'] === '1' && $this->settings['sendEmailToInternal'] !== '1') { $mail->to(new Address($contact->getEmail(), $contact->getFirstName()." ".$contact->getLastName())); } @@ -620,15 +630,14 @@ private function handleFileUpload(string $folder = $this->applicationFileService->getApplicantFolder($domainObject); - /* @var \TYPO3\CMS\Core\Resource\StorageRepository $storageRepository */ - $storageRepository = $this->objectManager->get(StorageRepository::class); - - $storage = $storageRepository->findByUid($fileStorage); - if (!$storage instanceof ResourceStorageInterface) { + $storage = $this->storageRepository->findByUid($fileStorage); + if (!$storage instanceof ResourceStorageInterface) + { throw new \RuntimeException(sprintf("Resource storage with uid %d could not be found.", $fileStorage)); } - if (!$storage instanceof ResourceStorage) { + if (!$storage instanceof ResourceStorage) + { throw new FileNotFoundException("Could not find fileadmin with uid 1"); } diff --git a/Classes/Controller/BackendController.php b/Classes/Controller/BackendController.php index 1b8816f..af61c86 100644 --- a/Classes/Controller/BackendController.php +++ b/Classes/Controller/BackendController.php @@ -102,7 +102,7 @@ public function listApplicationsAction() $sessionData = $GLOBALS['BE_USER']->getSessionData('tx_jobapplications'); $contact = $this->getActiveBeContact(); - $dailyLogin = $sessionData['dailyLogin']; + $dailyLogin = $sessionData['dailyLogin'] ?? null; if ((empty($dailyLogin) && $contact instanceof Contact) || ($dailyLogin === false && $contact instanceof Contact)) { $this->redirect('dashboard'); @@ -120,10 +120,10 @@ public function listApplicationsAction() } else { - $selectedPosting = $sessionData['selectedPosting']; - $archivedSelected = $sessionData['archivedSelected']; - $selectedContact = $sessionData['selectedContact']; - $selectedStatus = $sessionData['selectedStatus']; + $selectedPosting = $sessionData['selectedPosting'] ?? null; + $archivedSelected = $sessionData['archivedSelected'] ?? null; + $selectedContact = $sessionData['selectedContact'] ?? null; + $selectedStatus = $sessionData['selectedStatus'] ?? null; } // Handling a status change, triggered in listApplications View @@ -152,9 +152,9 @@ public function listApplicationsAction() $applications = $this->applicationRepository->findByFilter($selectedContact, $selectedPosting, $selectedStatus, 0, 'crdate', 'DESC'); // Set posting-selectBox content dynamically based on selected contact - if ((empty($selectedPosting) && !empty($selectedContact))) + if (empty($selectedPosting) && $selectedContact !== null) { - $postingsFilter = $this->postingRepository->findByContact(intval($selectedContact)); + $postingsFilter = $this->postingRepository->findByContact($selectedContact); } else { @@ -204,6 +204,7 @@ private function getActiveBeContact() * @throws \TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException * @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException * @throws \TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException + * @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException */ public function showApplicationAction(Application $application) { @@ -272,7 +273,7 @@ public function dashboardAction(): ResponseInterface $session = $backendUser->getSessionData('tx_jobapplications') ?? []; - if ((empty($session['dailyLogin']) && $contact instanceof Contact) || ($session['dailyLogin'] === false && $contact instanceof Contact)) + if ((isset($session['dailyLogin']) && $contact instanceof Contact) || (!isset($session['dailyLogin']) && $contact instanceof Contact)) { $session['dailyLogin'] = true; $backendUser->setAndSaveSessionData('tx_jobapplications', $session); diff --git a/Classes/Hooks/TCEmainHook.php b/Classes/Hooks/TCEmainHook.php index 3a63c2f..a52ce05 100644 --- a/Classes/Hooks/TCEmainHook.php +++ b/Classes/Hooks/TCEmainHook.php @@ -23,6 +23,22 @@ */ class TCEmainHook { + protected GoogleIndexingApiConnector $connector; + protected ApplicationFileService $applicationFileService; + protected ApplicationRepository $applicationRepository; + protected DataMapper $dataMapper; + + public function __construct() + { + /** @var ObjectManager $objectManager */ + $objectManager = GeneralUtility::makeInstance(ObjectManager::class); + + $this->connector = $objectManager->get(GoogleIndexingApiConnector::class); + $this->applicationFileService = $objectManager->get(ApplicationFileService::class); + $this->applicationRepository = $objectManager->get(ApplicationRepository::class); + $this->dataMapper = $objectManager->get(DataMapper::class); + } + /** * @param $status * @param $table @@ -32,7 +48,7 @@ class TCEmainHook * * @throws \Exception */ - public function processDatamap_afterDatabaseOperations($status, $table, $id, array $fieldArray, DataHandler &$pObj) + public function processDatamap_afterDatabaseOperations($status, $table, $id, array $fieldArray, DataHandler $pObj): void { if ($table === 'tx_jobapplications_domain_model_posting') @@ -47,19 +63,13 @@ public function processDatamap_afterDatabaseOperations($status, $table, $id, arr if ($status === "new") { - /** @var DataMapper $dataMapper */ - $objectManager = GeneralUtility::makeInstance(ObjectManager::class); - $dataMapper = $objectManager->get(DataMapper::class); - $uid = $pObj->substNEWwithIDs[$id]; $fieldArray['uid'] = $uid; - $posting = $dataMapper->map(Posting::class, [$fieldArray]); - - $connector = new GoogleIndexingApiConnector(); + $posting = $this->dataMapper->map(Posting::class, [$fieldArray]); - $connector->updateGoogleIndex($uid, false, $posting); + $this->connector->updateGoogleIndex($uid, false, $posting); } } } @@ -73,7 +83,7 @@ public function processDatamap_afterDatabaseOperations($status, $table, $id, arr * * @throws \Exception */ - public function processDatamap_postProcessFieldArray($command, $table, $uid, $value, DataHandler &$pObj) + public function processDatamap_postProcessFieldArray($command, $table, $uid, $value, DataHandler $pObj) { if ($table === "tx_jobapplications_domain_model_posting") { @@ -86,14 +96,13 @@ public function processDatamap_postProcessFieldArray($command, $table, $uid, $va if ($command === "update") { - $connector = new GoogleIndexingApiConnector(); if ($value['hidden'] === '1') { - $connector->updateGoogleIndex($uid, true); + $this->connector->updateGoogleIndex($uid, true); } else { - $connector->updateGoogleIndex($uid); + $this->connector->updateGoogleIndex($uid, false); } } } @@ -121,36 +130,25 @@ public function processCmdmap_deleteAction($table, $uid, array $record, &$record return; } - $connector = new GoogleIndexingApiConnector(); - $connector->updateGoogleIndex($uid, true); + $this->connector->updateGoogleIndex($uid, true); } if ($table === "tx_jobapplications_domain_model_application") { - /** @var ObjectManager $objectManager */ - $objectManager = GeneralUtility::makeInstance(ObjectManager::class); - /** @var ApplicationFileService $fileService */ - $fileService = $objectManager->get(ApplicationFileService::class); - /** @var ApplicationRepository $applicationRepository */ - $applicationRepository = $objectManager->get(ApplicationRepository::class); - if ($record['hidden'] === 1) { - - /** @var DataMapper $dataMapper */ - $dataMapper = $objectManager->get(DataMapper::class); - $applications = $dataMapper->map(Application::class, [$record]); + $applications = $this->dataMapper->map(Application::class, [$record]); $application = $applications[0]; } else { /** @var Application $application */ - $application = $applicationRepository->findByUid($uid); + $application = $this->applicationRepository->findByUid($uid); } - $path = $fileService->getApplicantFolder($application); - $fileStorage = $fileService->getFileStorage($application); - $fileService->deleteApplicationFolder($path, $fileStorage); + $path = $this->fileService->getApplicantFolder($application); + $fileStorage = $this->fileService->getFileStorage($application); + $this->fileService->deleteApplicationFolder($path, $fileStorage); } } } \ No newline at end of file diff --git a/Classes/Service/ApplicationFileService.php b/Classes/Service/ApplicationFileService.php index 01f6117..7b5da22 100644 --- a/Classes/Service/ApplicationFileService.php +++ b/Classes/Service/ApplicationFileService.php @@ -4,16 +4,15 @@ use ITX\Jobapplications\Domain\Model\Application; use TYPO3\CMS\Core\Resource\Driver\LocalDriver; - use TYPO3\CMS\Core\Resource\StorageRepository; - use TYPO3\CMS\Core\Resource\Folder; - use TYPO3\CMS\Core\Localization\Exception\FileNotFoundException; use TYPO3\CMS\Core\Resource\Exception\FileOperationErrorException; use TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException; use TYPO3\CMS\Core\Resource\Exception\InsufficientUserPermissionsException; + use TYPO3\CMS\Core\Resource\Exception\InvalidFileNameException; use TYPO3\CMS\Core\Resource\Exception\InvalidPathException; + use TYPO3\CMS\Core\Resource\Folder; use TYPO3\CMS\Core\Resource\ResourceStorageInterface; - use TYPO3\CMS\Core\Utility\GeneralUtility; - use TYPO3\CMS\Extbase\Object\ObjectManager; + use TYPO3\CMS\Core\Resource\StorageRepository; + use TYPO3\CMS\Extbase\Domain\Model\FileReference; /** * This file is part of the "jobapplications" Extension for TYPO3 CMS. @@ -25,15 +24,21 @@ class ApplicationFileService { public const APP_FILE_FOLDER = "applications/"; + protected StorageRepository $storageRepository; + + public function __construct(StorageRepository $storageRepository) + { + $this->storageRepository = $storageRepository; + } + /** * Helper function to generate the folder for an application * * @param $applicationObject * * @return string - * @throws \TYPO3\CMS\Core\Resource\Exception\InvalidFileNameException + * @throws InvalidFileNameException */ - public function getApplicantFolder(Application $applicationObject): string { return self::APP_FILE_FOLDER.(new LocalDriver) @@ -50,35 +55,45 @@ public function getApplicantFolder(Application $applicationObject): string * * @return string */ - public function getFileStorage(\ITX\Jobapplications\Domain\Model\Application $applicationObject): ?int + public function getFileStorage(Application $applicationObject): ?int { - if ($applicationObject->getFiles()->count() > 0) { - /** @var \TYPO3\CMS\Extbase\Domain\Model\FileReference $file */ + if ($applicationObject->getFiles() !== null && $applicationObject->getFiles()->count() > 0) + { + /** @var FileReference $file */ $file = $applicationObject->getFiles()->toArray()[0]; + return $file->getOriginalResource()->getStorage()->getUid(); } - if ($applicationObject->getCv() !== null && $applicationObject->getCv()->count() > 0) { - /** @var \TYPO3\CMS\Extbase\Domain\Model\FileReference $file */ + if ($applicationObject->getCv() !== null && $applicationObject->getCv()->count() > 0) + { + /** @var FileReference $file */ $file = $applicationObject->getCv()->toArray()[0]; + return $file->getOriginalResource()->getStorage()->getUid(); } - if ($applicationObject->getCoverLetter() !== null && $applicationObject->getCoverLetter()->count() > 0) { - /** @var \TYPO3\CMS\Extbase\Domain\Model\FileReference $file */ + if ($applicationObject->getCoverLetter() !== null && $applicationObject->getCoverLetter()->count() > 0) + { + /** @var FileReference $file */ $file = $applicationObject->getCoverLetter()->toArray()[0]; + return $file->getOriginalResource()->getStorage()->getUid(); } - if ($applicationObject->getTestimonials() !== null && $applicationObject->getTestimonials()->count() > 0) { - /** @var \TYPO3\CMS\Extbase\Domain\Model\FileReference $file */ + if ($applicationObject->getTestimonials() !== null && $applicationObject->getTestimonials()->count() > 0) + { + /** @var FileReference $file */ $file = $applicationObject->getTestimonials()->toArray()[0]; + return $file->getOriginalResource()->getStorage()->getUid(); } - if ($applicationObject->getOtherFiles() !== null && $applicationObject->getOtherFiles()->count() > 0) { - /** @var \TYPO3\CMS\Extbase\Domain\Model\FileReference $file */ + if ($applicationObject->getOtherFiles() !== null && $applicationObject->getOtherFiles()->count() > 0) + { + /** @var FileReference $file */ $file = $applicationObject->getOtherFiles()->toArray()[0]; + return $file->getOriginalResource()->getStorage()->getUid(); } @@ -88,27 +103,25 @@ public function getFileStorage(\ITX\Jobapplications\Domain\Model\Application $ap /** * Deletes the entire Folder * - * @param $folderPath string + * @param $folderPath string * @param $fileStorage int|null * * @throws InsufficientFolderAccessPermissionsException */ public function deleteApplicationFolder(string $folderPath, ?int $fileStorage): void { - if ($fileStorage === null) { + if ($fileStorage === null) + { return; } - $objectManager = GeneralUtility::makeInstance(ObjectManager::class); - - /* @var \TYPO3\CMS\Core\Resource\StorageRepository $storageRepository */ - $storageRepository = $objectManager->get(\TYPO3\CMS\Core\Resource\StorageRepository::class); - $storage = $storageRepository->findByUid($fileStorage); - if (!$storage instanceof ResourceStorageInterface) { + $storage = $this->storageRepository->findByUid($fileStorage); + if (!$storage instanceof ResourceStorageInterface) + { throw new \RuntimeException(sprintf("Resource storage with uid %d could not be found.", $fileStorage)); } - /** @var \TYPO3\CMS\Core\Resource\Folder|null $folder */ + /** @var Folder|null $folder */ $folder = null; if ($storage->hasFolder($folderPath)) { diff --git a/Classes/Task/AnonymizeApplications.php b/Classes/Task/AnonymizeApplications.php index c5d2aba..5417797 100644 --- a/Classes/Task/AnonymizeApplications.php +++ b/Classes/Task/AnonymizeApplications.php @@ -24,12 +24,14 @@ * * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ - use TYPO3\CMS\Scheduler\Task\AbstractTask; - use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager; + + use ITX\Jobapplications\Domain\Model\Application; use ITX\Jobapplications\Domain\Repository\ApplicationRepository; use ITX\Jobapplications\Service\ApplicationFileService; - use TYPO3\CMS\Core\Utility\GeneralUtility; - use TYPO3\CMS\Extbase\Object\ObjectManager; + use TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException; + use TYPO3\CMS\Core\Resource\Exception\InvalidFileNameException; + use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager; + use TYPO3\CMS\Scheduler\Task\AbstractTask; /** * Task for deleting all applications older than a specific amount of time @@ -38,50 +40,59 @@ */ class AnonymizeApplications extends AbstractTask { - public $days = null; - public $status = 0; + public int $days = 90; + public int $status = 0; + + protected PersistenceManager $persistenceManager; + protected ApplicationRepository $applicationRepository; + protected ApplicationFileService $applicationFileService; + + public function __construct(PersistenceManager $persistenceManager, ApplicationRepository $applicationRepository, ApplicationFileService $applicationFileService) + { + $this->persistenceManager = $persistenceManager; + $this->applicationRepository = $applicationRepository; + $this->applicationFileService = $applicationFileService; + + parent::__construct(); + } /** * This is the main method that is called when a task is executed * Should return TRUE on successful execution, FALSE on error. * * @return bool Returns TRUE on successful execution, FALSE on error - * @throws \TYPO3\CMS\Core\Resource\Exception\InvalidFileNameException - * @throws \TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException + * @throws InvalidFileNameException + * @throws InsufficientFolderAccessPermissionsException + * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException */ public function execute() { $anonymizeChars = "***"; - /* @var $objectManager ObjectManager */ - $objectManager = GeneralUtility::makeInstance(ObjectManager::class); - $persistenceManager = $objectManager->get(PersistenceManager::class); - $applicationRepository = $objectManager->get(ApplicationRepository::class); - $applicationFileService = $objectManager->get(ApplicationFileService::class); // Calculate Timestamp for how old the application must be to give to the repo $now = new \DateTime(); $timestamp = $now->modify("-".$this->days." days")->getTimestamp(); - if ($status = 1) + if ($this->status = 1) { - $applications = $applicationRepository->findNotAnonymizedOlderThan($timestamp, true); + $applications = $this->applicationRepository->findNotAnonymizedOlderThan($timestamp, true); } else { - $applications = $applicationRepository->findNotAnonymizedOlderThan($timestamp); + $applications = $this->applicationRepository->findNotAnonymizedOlderThan($timestamp); } $resultCount = count($applications); - /* @var \ITX\Jobapplications\Domain\Model\Application $application */ + /* @var Application $application */ foreach ($applications as $application) { // Actual anonymization + deleting application files - /* @var \ITX\Jobapplications\Service\ApplicationFileService $applicationFileService */ - $fileStorage = $applicationFileService->getFileStorage($application); + /* @var ApplicationFileService $applicationFileService */ + $fileStorage = $this->applicationFileService->getFileStorage($application); - $applicationFileService->deleteApplicationFolder($applicationFileService->getApplicantFolder($application), $fileStorage); + $this->applicationFileService->deleteApplicationFolder($this->applicationFileService->getApplicantFolder($application), $fileStorage); $application->setFirstName($anonymizeChars); $application->setLastName($anonymizeChars); @@ -96,12 +107,12 @@ public function execute() $application->setSalaryExpectation($anonymizeChars); $application->setEarliestDateOfJoining(new \DateTime("@0")); - $applicationRepository->update($application); + $this->applicationRepository->update($application); } if ($resultCount > 0) { - $persistenceManager->persistAll(); + $this->persistenceManager->persistAll(); } $this->logger->info('[ITX\\Jobapplications\\Task\\AnonymizeApplications]: '.$resultCount.' Applications anonymized.'); diff --git a/Classes/Task/CleanUpApplications.php b/Classes/Task/CleanUpApplications.php index 7cd83a2..3ea51c3 100644 --- a/Classes/Task/CleanUpApplications.php +++ b/Classes/Task/CleanUpApplications.php @@ -24,12 +24,14 @@ * * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ - use TYPO3\CMS\Scheduler\Task\AbstractTask; - use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager; + use ITX\Jobapplications\Domain\Repository\ApplicationRepository; use ITX\Jobapplications\Service\ApplicationFileService; - use TYPO3\CMS\Core\Utility\GeneralUtility; - use TYPO3\CMS\Extbase\Object\ObjectManager; + use TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException; + use TYPO3\CMS\Core\Resource\Exception\InvalidFileNameException; + use TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException; + use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager; + use TYPO3\CMS\Scheduler\Task\AbstractTask; /** * Task for deleting all applications older than a specific amount of time @@ -38,49 +40,54 @@ */ class CleanUpApplications extends AbstractTask { - public $days = null; - public $status = 0; + public int $days = 90; + public int $status = 0; + + public function __construct(PersistenceManager $persistenceManager, ApplicationRepository $applicationRepository, ApplicationFileService $applicationFileService) + { + $this->persistenceManager = $persistenceManager; + $this->applicationRepository = $applicationRepository; + $this->applicationFileService = $applicationFileService; + + parent::__construct(); + } /** * This is the main method that is called when a task is executed * Should return TRUE on successful execution, FALSE on error. * * @return bool Returns TRUE on successful execution, FALSE on error - * @throws \TYPO3\CMS\Core\Resource\Exception\InvalidFileNameException - * @throws \TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException + * @throws InvalidFileNameException + * @throws InsufficientFolderAccessPermissionsException + * @throws InvalidQueryException */ public function execute() { - $objectManager = GeneralUtility::makeInstance(ObjectManager::class); - $persistenceManager = $objectManager->get(PersistenceManager::class); - $applicationRepository = $objectManager->get(ApplicationRepository::class); - $applicationFileService = $objectManager->get(ApplicationFileService::class); - $now = new \DateTime(); $timestamp = $now->modify("-".$this->days." days")->getTimestamp(); - if ($status = 1) + if ($this->status = 1) { - $applications = $applicationRepository->findOlderThan($timestamp, true); + $applications = $this->applicationRepository->findOlderThan($timestamp, true); } else { - $applications = $applicationRepository->findOlderThan($timestamp); + $applications = $this->applicationRepository->findOlderThan($timestamp); } $resultCount = count($applications); foreach ($applications as $application) { - $fileStorage = $applicationFileService->getFileStorage($application); - $applicationRepository->remove($application); + $fileStorage = $this->applicationFileService->getFileStorage($application); + $this->applicationRepository->remove($application); - $applicationFileService->deleteApplicationFolder($applicationFileService->getApplicantFolder($application), $fileStorage); + $this->applicationFileService->deleteApplicationFolder($this->applicationFileService->getApplicantFolder($application), $fileStorage); } if ($resultCount > 0) { - $persistenceManager->persistAll(); + $this->persistenceManager->persistAll(); } $this->logger->info('[ITX\\Jobapplications\\Task\\CleanUpApplications]: '.$resultCount.' Applications deleted.'); diff --git a/Classes/Utility/GoogleIndexingApiConnector.php b/Classes/Utility/GoogleIndexingApiConnector.php index f415efa..ebd9212 100644 --- a/Classes/Utility/GoogleIndexingApiConnector.php +++ b/Classes/Utility/GoogleIndexingApiConnector.php @@ -24,19 +24,19 @@ namespace ITX\Jobapplications\Utility; - use TYPO3\CMS\Core\Core\Environment; use ITX\Jobapplications\Domain\Model\Posting; use ITX\Jobapplications\Domain\Repository\PostingRepository; use ITX\Jobapplications\Domain\Repository\TtContentRepository; + use JsonException; use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; + use TYPO3\CMS\Core\Core\Environment; use TYPO3\CMS\Core\Http\RequestFactory; + use TYPO3\CMS\Core\Messaging\AbstractMessage; use TYPO3\CMS\Core\Messaging\FlashMessage; - use TYPO3\CMS\Core\Messaging\FlashMessageQueue; use TYPO3\CMS\Core\Messaging\FlashMessageService; use TYPO3\CMS\Core\Service\FlexFormService; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Domain\Model\Category; - use TYPO3\CMS\Extbase\Object\ObjectManager; use TYPO3\CMS\Extbase\Persistence\Generic\QueryResult; /** @@ -46,30 +46,36 @@ */ class GoogleIndexingApiConnector { - /** @var ObjectManager */ - protected $objectManager; - - /** @var array */ - protected $googleConfig; + protected array $googleConfig; - /** @var RequestFactory */ - protected $requestFactory; - - /** @var array */ - protected $backendConfiguration; + protected array $backendConfiguration; /** @var boolean */ - protected $supressFlashMessages; + protected bool $supressFlashMessages; + + protected RequestFactory $requestFactory; + protected TtContentRepository $ttContentRepository; + protected PostingRepository $postingRepository; + protected FlashMessageService $flashMessageService; + protected FlexFormService $flexFormService; /** * GoogleIndexingApiConnector constructor. * - * @param bool $supressFlashMessages + * @throws JsonException */ - public function __construct($supressFlashMessages = false) + public function __construct(RequestFactory $requestFactory, TtContentRepository $ttContentRepository, + PostingRepository $postingRepository, FlashMessageService $flashMessageService, + FlexFormService $flexFormService) { + $this->requestFactory = $requestFactory; + $this->ttContentRepository = $ttContentRepository; + $this->postingRepository = $postingRepository; + $this->flashMessageService = $flashMessageService; + $this->flexFormService = $flexFormService; + $this->backendConfiguration = GeneralUtility::makeInstance(ExtensionConfiguration::class) - ->get('jobapplications'); + ->get('jobapplications'); if ($this->backendConfiguration['key_path'] !== '') { $fileName = GeneralUtility::getFileAbsFileName($this->backendConfiguration['key_path']); @@ -80,35 +86,30 @@ public function __construct($supressFlashMessages = false) ), true, 512, JSON_THROW_ON_ERROR); } } + } - $this->objectManager = GeneralUtility::makeInstance(ObjectManager::class); - $this->requestFactory = $this->objectManager->get(RequestFactory::class); - - $this->supressFlashMessages = $supressFlashMessages; + public function setSupressFlashMessages(bool $shouldSupress) + { + $this->supressFlashMessages = $shouldSupress; } /** * Sends requests to Google Indexing API * - * @param $uid - * @param bool $delete - * @param Posting $specificPosting + * @param $uid + * @param bool $delete + * @param Posting|null $specificPosting * * @return bool * @throws \Exception */ - public function updateGoogleIndex($uid, $delete = false, $specificPosting = null): ?bool + public function updateGoogleIndex($uid, bool $delete, Posting $specificPosting = null): ?bool { if (Environment::getContext()->isDevelopment() && $this->backendConfiguration['indexing_api_dev'] === "0") { return false; } - /** @var PostingRepository $postingRepository */ - $postingRepository = $this->objectManager->get(PostingRepository::class); - /** @var TtContentRepository $ttContentRepository */ - $ttContentRepository = $this->objectManager->get(TtContentRepository::class); - /** @var Posting $posting */ if ($specificPosting instanceof Posting) { @@ -116,7 +117,7 @@ public function updateGoogleIndex($uid, $delete = false, $specificPosting = null } else { - $query = $postingRepository->createQuery(); + $query = $this->postingRepository->createQuery(); $query->getQuerySettings()->setIgnoreEnableFields(true) ->setRespectStoragePage(false); $query->matching( @@ -136,7 +137,7 @@ public function updateGoogleIndex($uid, $delete = false, $specificPosting = null $uriBuilder = new FrontendUriBuilder(); /** @var QueryResult $contentElements */ - $contentElements = $ttContentRepository->findByListType("jobapplications_frontend"); + $contentElements = $this->ttContentRepository->findByListType("jobapplications_frontend"); $contentElements = $contentElements->toArray(); @@ -184,7 +185,7 @@ public function updateGoogleIndex($uid, $delete = false, $specificPosting = null * @param string $header * @param bool $error */ - private function sendFlashMessage(string $msg, string $header = "", bool $error = false) + private function sendFlashMessage(string $msg, string $header = "", bool $error = false): void { $debug = $this->backendConfiguration['indexing_api_debug']; @@ -193,20 +194,17 @@ private function sendFlashMessage(string $msg, string $header = "", bool $error return; } - $type = FlashMessage::OK; + $type = AbstractMessage::OK; if ($error) { - $type = FlashMessage::WARNING; + $type = AbstractMessage::WARNING; } /** @var FlashMessage $message */ $message = GeneralUtility::makeInstance(FlashMessage::class, $msg, $header, $type, true); - /** @var FlashMessageService $flashMessageService */ - $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class); - /** @var FlashMessageQueue $messageQueue */ - $messageQueue = $flashMessageService->getMessageQueueByIdentifier(); + $messageQueue = $this->flashMessageService->getMessageQueueByIdentifier(); // @extensionScannerIgnoreLine $messageQueue->addMessage($message); } @@ -216,16 +214,14 @@ private function sendFlashMessage(string $msg, string $header = "", bool $error * * @param $contentElements array * @param $posting Posting + * + * @return mixed */ - private function findBestPluginPageFit($contentElements, $posting) + private function findBestPluginPageFit(array $contentElements, Posting $posting): mixed { - - /** @var FlexFormService $flexformService */ - $flexformService = $this->objectManager->get(FlexFormService::class); - $postingCategories = $posting->getCategories()->toArray(); - $fallback = $flexformService->convertFlexFormContentToArray($contentElements[0]->getPiFlexform(), "lDEF")['settings']['detailViewUid']; + $fallback = $this->flexFormService->convertFlexFormContentToArray($contentElements[0]->getPiFlexform())['settings']['detailViewUid']; $result = null; @@ -236,12 +232,12 @@ private function findBestPluginPageFit($contentElements, $posting) { foreach ($contentElements as $contentElement) { - $flexformArray = $flexformService->convertFlexFormContentToArray($contentElement->getPiFlexform(), "lDEF"); + $flexformArray = $this->flexFormService->convertFlexFormContentToArray($contentElement->getPiFlexform()); $categories = explode(",", $flexformArray['settings']['categories']); $postingCategoryUid = $postingCategory->getUid(); - if (in_array($postingCategoryUid, $categories)) + if (in_array($postingCategoryUid, $categories, true)) { if (count($categories) === 1) { @@ -261,7 +257,7 @@ private function findBestPluginPageFit($contentElements, $posting) { foreach ($contentElements as $contentElement) { - $flexformArray = $flexformService->convertFlexFormContentToArray($contentElement->getPiFlexform(), "lDEF"); + $flexformArray = $this->flexFormService->convertFlexFormContentToArray($contentElement->getPiFlexform(), "lDEF"); $categories = explode(",", $flexformArray['settings']['categories']); @@ -281,8 +277,9 @@ private function findBestPluginPageFit($contentElements, $posting) * @param bool $deleteInsteadOfUpdate * * @return bool true success, false something went wrong + * @throws JsonException */ - public function makeRequest(string $url, $deleteInsteadOfUpdate = false): ?bool + public function makeRequest(string $url, bool $deleteInsteadOfUpdate): ?bool { $accessToken = ""; @@ -342,7 +339,7 @@ public function makeRequest(string $url, $deleteInsteadOfUpdate = false): ?bool "Content-Type" => "application/json", 'Authorization' => "Bearer ".$accessToken ], - "body" => json_encode($actualBody), + "body" => json_encode($actualBody, JSON_THROW_ON_ERROR), "http_errors" => false ]; @@ -359,11 +356,12 @@ public function makeRequest(string $url, $deleteInsteadOfUpdate = false): ?bool } /** - * Authenticates with google oauth api + * Authenticates with Google OAuth API * * @return string Bearer token + * @throws JsonException */ - private function makeAuthReq() + private function makeAuthReq(): string { // Authentication $jwtHeader = [ @@ -371,7 +369,7 @@ private function makeAuthReq() "typ" => "JWT" ]; - $jwtHeaderBase64 = base64_encode(json_encode($jwtHeader)); + $jwtHeaderBase64 = base64_encode(json_encode($jwtHeader, JSON_THROW_ON_ERROR)); $jwtClaimSet = [ "iss" => $this->googleConfig["client_email"], @@ -381,7 +379,7 @@ private function makeAuthReq() "iat" => time() ]; - $jwtClaimSetBase64 = base64_encode(json_encode($jwtClaimSet)); + $jwtClaimSetBase64 = base64_encode(json_encode($jwtClaimSet, JSON_THROW_ON_ERROR)); $signatureInput = $jwtHeaderBase64.".".$jwtClaimSetBase64; @@ -411,7 +409,7 @@ private function makeAuthReq() "headers" => [ "Content-Type" => "application/json" ], - "body" => json_encode($accessTokenRequestData), + "body" => json_encode($accessTokenRequestData, JSON_THROW_ON_ERROR), "http_errors" => false ]; @@ -425,20 +423,18 @@ private function makeAuthReq() return ""; } - else - { - $accessRepsonseJson = json_decode($accessResponse->getBody()->getContents(), true); - $accessToken = $accessRepsonseJson["access_token"]; - $sessionData = [ - "indexingAccessToken" => [ - "token" => $accessToken, - "validUntil" => time() + (int)$accessRepsonseJson["expires_in"] - ] - ]; + $accessRepsonseJson = json_decode($accessResponse->getBody()->getContents(), true, 512, JSON_THROW_ON_ERROR); - $GLOBALS["BE_USER"]->setAndSaveSessionData("tx_jobapplications", $sessionData); - } + $accessToken = $accessRepsonseJson["access_token"]; + $sessionData = [ + "indexingAccessToken" => [ + "token" => $accessToken, + "validUntil" => time() + (int)$accessRepsonseJson["expires_in"] + ] + ]; + + $GLOBALS["BE_USER"]->setAndSaveSessionData("tx_jobapplications", $sessionData); if (!$accessToken) { diff --git a/Classes/ViewHelpers/GroupByCategoryViewHelper.php b/Classes/ViewHelpers/GroupByCategoryViewHelper.php index a8b06f1..acc4b26 100644 --- a/Classes/ViewHelpers/GroupByCategoryViewHelper.php +++ b/Classes/ViewHelpers/GroupByCategoryViewHelper.php @@ -6,12 +6,14 @@ * This file belongs to the package "TYPO3 Fluid". * See LICENSE.txt that was shipped with this package. */ - use TYPO3Fluid\Fluid\Core\ViewHelper\Exception; + + use Closure; use ITX\Jobapplications\Domain\Model\Posting; use TYPO3\CMS\Extbase\Domain\Model\Category; use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface; use TYPO3Fluid\Fluid\Core\ViewHelper; use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper; + use TYPO3Fluid\Fluid\Core\ViewHelper\Exception; use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic; /** @@ -32,13 +34,13 @@ class GroupByCategoryViewHelper extends AbstractViewHelper /** * @param array $arguments - * @param \Closure $renderChildrenClosure + * @param Closure $renderChildrenClosure * @param RenderingContextInterface $renderingContext * * @return string * @throws ViewHelper\Exception */ - public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext) + public static function renderStatic(array $arguments, Closure $renderChildrenClosure, RenderingContextInterface $renderingContext) { $templateVariableContainer = $renderingContext->getVariableProvider(); if (!isset($arguments['postings'])) diff --git a/Classes/Widgets/Provider/ApplicationsPerPostingBarChartProvider.php b/Classes/Widgets/Provider/ApplicationsPerPostingBarChartProvider.php index e332313..ec117c8 100644 --- a/Classes/Widgets/Provider/ApplicationsPerPostingBarChartProvider.php +++ b/Classes/Widgets/Provider/ApplicationsPerPostingBarChartProvider.php @@ -26,7 +26,6 @@ use TYPO3\CMS\Dashboard\Widgets\ChartDataProviderInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; - use TYPO3\CMS\Extbase\Object\ObjectManager; use ITX\Jobapplications\Domain\Repository\PostingRepository; use ITX\Jobapplications\Domain\Model\Posting; use ITX\Jobapplications\Domain\Repository\ApplicationRepository; @@ -41,27 +40,26 @@ class ApplicationsPerPostingBarChartProvider implements ChartDataProviderInterface { /** @var array */ - protected $labels = []; + protected array $labels = []; - public function getChartData(): array - { - /** @var \TYPO3\CMS\Extbase\Object\ObjectManager $objectmanager */ - $objectmanager = GeneralUtility::makeInstance(ObjectManager::class); - - /** @var \ITX\Jobapplications\Domain\Repository\PostingRepository $postingRepo */ - $postingRepo = $objectmanager->get(PostingRepository::class); + protected ApplicationRepository $applicationRepository; + protected PostingRepository $postingRepository; - /** @var ApplicationRepository $applicationRepo */ - $applicationRepo = $objectmanager->get(ApplicationRepository::class); + public function __construct(PostingRepository $postingRepository, ApplicationRepository $applicationRepository) { + $this->postingRepository = $postingRepository; + $this->applicationRepository = $applicationRepository; + } - $postings = $postingRepo->findAllIncludingHiddenAndDeleted(); + public function getChartData(): array + { + $postings = $this->postingRepository->findAllIncludingHiddenAndDeleted(); $data = []; /** @var Posting $posting */ foreach ($postings as $posting) { - $applicationCount = $applicationRepo->findByPostingIncludingHiddenAndDeleted($posting->getUid())->count(); + $applicationCount = $this->applicationRepository->findByPostingIncludingHiddenAndDeleted($posting->getUid())->count(); $this->labels[] = $posting->getTitle(); $data[] = $applicationCount; } diff --git a/Classes/Widgets/Provider/PostingsActiveProvider.php b/Classes/Widgets/Provider/PostingsActiveProvider.php index e974923..8dcf52e 100644 --- a/Classes/Widgets/Provider/PostingsActiveProvider.php +++ b/Classes/Widgets/Provider/PostingsActiveProvider.php @@ -24,8 +24,6 @@ namespace ITX\Jobapplications\Widgets\Provider; - use TYPO3\CMS\Core\Utility\GeneralUtility; - use TYPO3\CMS\Extbase\Object\ObjectManager; use ITX\Jobapplications\Domain\Repository\PostingRepository; use TYPO3\CMS\Dashboard\Widgets\NumberWithIconDataProviderInterface; @@ -36,14 +34,15 @@ */ class PostingsActiveProvider implements NumberWithIconDataProviderInterface { - public function getNumber(): int - { - /** @var \TYPO3\CMS\Extbase\Object\ObjectManager $objectmanager */ - $objectmanager = GeneralUtility::makeInstance(ObjectManager::class); + protected PostingRepository $postingRepository; - /** @var \ITX\Jobapplications\Domain\Repository\PostingRepository $postingRepo */ - $postingRepo = $objectmanager->get(PostingRepository::class); + public function __construct(PostingRepository $postingRepository) + { + $this->postingRepository = $postingRepository; + } - return $postingRepo->findAllIgnoreStoragePage()->count(); + public function getNumber(): int + { + return $this->postingRepository->findAllIgnoreStoragePage()->count(); } } \ No newline at end of file diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml index 93a8639..700a838 100644 --- a/Configuration/Services.yaml +++ b/Configuration/Services.yaml @@ -1,4 +1,3 @@ -# Variant 1, widget identifier as attribute services: _defaults: autowire: true diff --git a/Resources/Private/Backend/Templates/Backend/ListApplications.html b/Resources/Private/Backend/Templates/Backend/ListApplications.html index cd6a45f..c582039 100644 --- a/Resources/Private/Backend/Templates/Backend/ListApplications.html +++ b/Resources/Private/Backend/Templates/Backend/ListApplications.html @@ -62,9 +62,9 @@

- +
    - +
  • @@ -113,7 +113,6 @@

-
diff --git a/Resources/Private/Templates/Posting/List.html b/Resources/Private/Templates/Posting/List.html index ddaf2a3..5beb33f 100644 --- a/Resources/Private/Templates/Posting/List.html +++ b/Resources/Private/Templates/Posting/List.html @@ -81,6 +81,7 @@

+
diff --git a/Resources/Public/Css/backend.css b/Resources/Public/Css/backend.css index 29a6be4..2cd2823 100644 --- a/Resources/Public/Css/backend.css +++ b/Resources/Public/Css/backend.css @@ -1 +1 @@ -@font-face{font-family:'Roboto';font-style:normal;font-weight:400;font-display:swap;src:local('Roboto'),local('Roboto-Regular'),url(https://fonts.gstatic.com/s/roboto/v20/KFOmCnqEu92Fr1Mu4mxP.ttf) format('truetype')}html{box-sizing:border-box;font-size:10px}body{font-family:Roboto,Arial,Helvetica,sans-serif;font-size:1.4rem}div{display:block;box-sizing:border-box}h1{text-align:center;font-size:3.2rem}h2{font-size:2.5rem}h3{font-size:1.9rem}hr{border-top:1px solid rgba(0,0,0,0.13)}#typo3-inner-docbody{padding:0;margin:0}.checkbox-wrapper{margin-top:3.5rem}.checkbox-wrapper label{display:block;float:left}.checkbox-wrapper input[type="checkbox"]{display:block;float:left;margin-top:-1px;margin-left:1rem;width:2rem;height:2rem}.checkbox-wrapper input[type="checkbox"]:hover{cursor:pointer}.btn-jobapplications{background-color:transparent;border:none;color:#000;padding:1rem 2rem;margin:0 2rem;border:2px solid #E62E29;transition:background-color .1s,color .1s,opacity .1s;text-align:center;font-size:1.4rem}.btn-jobapplications:hover{background-color:#E62E29;color:#fff;text-decoration:none}.btn-jobapplications.btn-secondary{border:2px solid #919191}.btn-jobapplications.btn-secondary:hover{background-color:#919191;color:#fff}.btn-jobapplications.btn-critical{border:2px solid #E62E29;background-color:#E62E29;color:white}.btn-jobapplications.btn-critical:hover{opacity:90%;color:#fff}.listapplication-wrapper{padding:2rem}.listapplication-wrapper .top .filter form{width:100%;display:inline-block;margin-bottom:0 !important}.listapplication-wrapper .top .filter form .filter-element{float:left}.listapplication-wrapper .top .filter form .filter-element select{display:block;height:4rem;padding:.375rem .75rem;font-weight:400;font-size:1.4rem;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:0;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;margin:auto 2rem auto 0}.listapplication-wrapper .top .filter form .filter-element label{display:inline-block}.listapplication-wrapper .top .filter form .filter-buttons{float:right}.listapplication-wrapper .top .filter form .filter-buttons .form-btn{margin-top:2.2rem;float:left}.listapplication-wrapper .form-btn{display:block}.listapplication-wrapper .app-list{margin:0;height:auto;overflow-y:auto;display:block}.listapplication-wrapper .app-list ul.application-list{padding:0;text-decoration:none;list-style:none}.listapplication-wrapper .app-list ul.application-list li{width:100%;margin-bottom:1rem;display:inline-block;padding:2rem;border:solid 1px rgba(0,0,0,0.13);border-radius:8px}.listapplication-wrapper .app-list ul.application-list li .list-item-container{display:flex;flex-flow:row;justify-content:space-between;font-size:1.4rem}.listapplication-wrapper .app-list ul.application-list li .list-item-container div{margin-top:auto;margin-bottom:auto}.listapplication-wrapper .app-list ul.application-list li .list-item-container span,.listapplication-wrapper .app-list ul.application-list li .list-item-container a{display:inline-block}.listapplication-wrapper .app-list ul.application-list li.archived{background-color:rgba(0,0,0,0.13)}.listapplication-wrapper .app-list .row-section{width:33%}.listapplication-wrapper .app-list .row-section.left{text-align:left}.listapplication-wrapper .app-list .row-section.middle{text-align:center}.listapplication-wrapper .app-list .row-section.right{display:flex;text-align:right}.listapplication-wrapper .app-list .row-section.right .status-select select{margin-left:0px !important}.listapplication-wrapper .app-list .row-section.right span{text-align:center;margin:auto}@media only screen and (max-width:1290px){.listapplication-wrapper .app-list .row-section.right .status-select,.listapplication-wrapper .app-list .row-section.right span{text-align:left;float:left;width:60%;margin-bottom:.5rem !important}.listapplication-wrapper .app-list .row-section.right .btn-jobapplications{width:40%;margin:1vw 0 0}}.showapplication-wrapper{padding:2rem}.showapplication-wrapper .personal-description{padding:5rem;width:66%;margin:auto;border:solid 1px rgba(0,0,0,0.13);border-radius:8px;text-align:center;font-size:1.4rem}.showapplication-wrapper .personal-description.archived{background-color:rgba(0,0,0,0.13)}.showapplication-wrapper .personal-description .row{width:100%;margin:0}.showapplication-wrapper .personal-description .row label{display:block;float:left;width:45%;text-align:right}.showapplication-wrapper .personal-description .row span{display:block;width:55%;float:left;text-align:left}.showapplication-wrapper .personal-description .row p{display:block;width:55%;float:left;white-space:-moz-pre-wrap;white-space:pre-wrap;text-align:left}.showapplication-wrapper .personal-description .row.message-row{margin:.5rem auto}.showapplication-wrapper .personal-description .row.file-container{display:flex;flex-direction:row;justify-content:center;flex-wrap:wrap}.showapplication-wrapper .personal-description .row.file-container .file{display:block;background-color:#fff;border-radius:25px;border:1px solid rgba(0,0,0,0.13);padding:.5rem 1rem;margin:1.5rem 1rem;text-decoration:none}.showapplication-wrapper .personal-description .row.file-container .file:hover{background-color:#e2e2e2;text-decoration:none;cursor:pointer}.showapplication-wrapper .personal-description .row.file-container .file .icon-pdf{display:inline-block;width:2rem}.showapplication-wrapper .personal-description .row.file-container .file .icon-download{float:right;margin-top:.5rem}.showapplication-wrapper .personal-description .row.file-container .file span{display:inline-block;text-align:center;float:none;white-space:nowrap;width:auto;padding:0 2rem}.showapplication-wrapper .personal-description .row .name{font-size:1.6rem;padding-bottom:2rem;width:80%;margin:auto;float:left}.showapplication-wrapper .personal-description .row .date{float:right;width:auto}.showapplication-wrapper .personal-description .row .placeholder{float:left;width:auto;width:10%}.showapplication-wrapper .container-buttons{width:66%;margin:2rem auto auto;display:flex;text-align:center;justify-content:space-between}.showapplication-wrapper .container-buttons .btn-jobapplications{margin:unset}.status-select{width:auto;margin:0 !important;margin-bottom:-5px !important;display:inline-block;margin-top:.8rem !important;float:left}.status-select .spinner{display:none;margin-top:1px;margin-left:2px;width:auto;float:left;height:20px}.status-select .spinner-active{display:block}.status-select select{float:left;border:none;margin-top:2px;margin-left:-3px;background-color:transparent;cursor:pointer}.status-select select.list{-webkit-appearance:none;-moz-appearance:none;appearance:none}.status-select select option{text-align:right}.status-select select:focus{border:none}#show-spinner{width:auto;margin-top:0 !important;float:left}.dashboard{width:100%;margin:0;height:100%}.dashboard .top{margin-top:2rem;padding:0 10%}.dashboard .top h3{text-align:center;margin:1rem 0}.dashboard .middle{padding:5% 10%;display:flex;flex-wrap:wrap;flex-direction:row;justify-content:center;width:100%;position:absolute;height:100%;top:0}.dashboard .middle .button-box{display:inline-block;background-color:#E62E29;border:.2rem solid #E62E29;width:26vh;height:26vh;padding:1rem;transition:background-color .1s,color .1s,border .1s,box-shadow .1s,font-size .1s;box-shadow:0 1px 6px 0 rgba(32,33,36,0.28);text-align:center;color:#fff;text-decoration:none;font-size:1.6rem;line-height:1.5;margin:auto 2rem}.dashboard .middle .button-box span{display:block;position:relative;letter-spacing:1px;top:50%;transform:translateY(-50%);text-decoration:none}.dashboard .middle .button-box:hover{border:.2rem solid #fff;font-size:1.5rem;cursor:pointer;text-decoration:none;color:#fff;box-shadow:none;line-height:1.5}.dashboard .middle .settings{background-color:#ffd02a;border:.2rem solid #ffd02a}.footer{position:absolute;bottom:1rem;width:98%;text-align:center}.settings{padding:2rem}.settings .middle{display:flex;padding:2rem}.settings .middle .container{padding:1rem;width:45%;margin:0 5%;border:solid 1px rgba(0,0,0,0.13);border-radius:8px} \ No newline at end of file +@font-face{font-family:'Roboto';font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v29/KFOmCnqEu92Fr1Mu4mxP.ttf) format('truetype')}html{box-sizing:border-box;font-size:10px !important}body{font-family:Roboto,Arial,Helvetica,sans-serif;font-size:1.4rem}div{display:block;box-sizing:border-box}h1{text-align:center;font-size:3.2rem}h2{font-size:2.5rem}h3{font-size:1.9rem}hr{border-top:1px solid rgba(0,0,0,0.13)}#typo3-inner-docbody{padding:0;margin:0}.checkbox-wrapper{margin-top:3.5rem}.checkbox-wrapper label{display:block;float:left}.checkbox-wrapper input[type="checkbox"]{display:block;float:left;margin-top:-1px;margin-left:1rem;width:2rem;height:2rem}.checkbox-wrapper input[type="checkbox"]:hover{cursor:pointer}.btn-jobapplications{background-color:transparent;border:none;color:#000;padding:1rem 2rem;margin:0 2rem;border:2px solid #E62E29;transition:background-color .1s,color .1s,opacity .1s;text-align:center;font-size:1.4rem}.btn-jobapplications:hover{background-color:#E62E29;color:#fff;text-decoration:none}.btn-jobapplications.btn-secondary{border:2px solid #919191}.btn-jobapplications.btn-secondary:hover{background-color:#919191;color:#fff}.btn-jobapplications.btn-critical{border:2px solid #E62E29;background-color:#E62E29;color:white}.btn-jobapplications.btn-critical:hover{opacity:90%;color:#fff}.listapplication-wrapper{padding:2rem}.listapplication-wrapper .top .filter form{width:100%;display:inline-block;margin-bottom:0 !important}.listapplication-wrapper .top .filter form .filter-element{float:left}.listapplication-wrapper .top .filter form .filter-element select{display:block;height:4rem;padding:.375rem .75rem;font-weight:400;font-size:1.4rem;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:0;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;margin:auto 2rem auto 0}.listapplication-wrapper .top .filter form .filter-element label{display:inline-block}.listapplication-wrapper .top .filter form .filter-buttons{float:right}.listapplication-wrapper .top .filter form .filter-buttons .form-btn{margin-top:2.2rem;float:left}.listapplication-wrapper .form-btn{display:block}.listapplication-wrapper .app-list{margin:0;height:auto;overflow-y:auto;display:block}.listapplication-wrapper .app-list ul.application-list{padding:0;text-decoration:none;list-style:none}.listapplication-wrapper .app-list ul.application-list li{width:100%;margin-bottom:1rem;display:inline-block;padding:2rem;border:solid 1px rgba(0,0,0,0.13);border-radius:8px}.listapplication-wrapper .app-list ul.application-list li .list-item-container{display:flex;flex-flow:row;justify-content:space-between;font-size:1.4rem}.listapplication-wrapper .app-list ul.application-list li .list-item-container div{margin-top:auto;margin-bottom:auto}.listapplication-wrapper .app-list ul.application-list li .list-item-container span,.listapplication-wrapper .app-list ul.application-list li .list-item-container a{display:inline-block}.listapplication-wrapper .app-list ul.application-list li.archived{background-color:rgba(0,0,0,0.13)}.listapplication-wrapper .app-list .row-section{width:33%}.listapplication-wrapper .app-list .row-section.left{text-align:left}.listapplication-wrapper .app-list .row-section.middle{text-align:center}.listapplication-wrapper .app-list .row-section.right{display:flex;text-align:right}.listapplication-wrapper .app-list .row-section.right .status-select select{margin-left:0px !important}.listapplication-wrapper .app-list .row-section.right span{text-align:center;margin:auto}@media only screen and (max-width:1290px){.listapplication-wrapper .app-list .row-section.right .status-select,.listapplication-wrapper .app-list .row-section.right span{text-align:left;float:left;width:60%;margin-bottom:.5rem !important}.listapplication-wrapper .app-list .row-section.right .btn-jobapplications{width:40%;margin:1vw 0 0}}.showapplication-wrapper{padding:2rem}.showapplication-wrapper .personal-description{padding:5rem;width:66%;margin:auto;border:solid 1px rgba(0,0,0,0.13);border-radius:8px;text-align:center;font-size:1.4rem}.showapplication-wrapper .personal-description.archived{background-color:rgba(0,0,0,0.13)}.showapplication-wrapper .personal-description .row{width:100%;margin:0}.showapplication-wrapper .personal-description .row label{display:block;float:left;width:45%;text-align:right}.showapplication-wrapper .personal-description .row span{display:block;width:55%;float:left;text-align:left}.showapplication-wrapper .personal-description .row p{display:block;width:55%;float:left;white-space:-moz-pre-wrap;white-space:pre-wrap;text-align:left}.showapplication-wrapper .personal-description .row.message-row{margin:.5rem auto}.showapplication-wrapper .personal-description .row.file-container{display:flex;flex-direction:row;justify-content:center;flex-wrap:wrap}.showapplication-wrapper .personal-description .row.file-container .file{display:block;background-color:#fff;border-radius:25px;border:1px solid rgba(0,0,0,0.13);padding:.5rem 1rem;margin:1.5rem 1rem;width:auto;text-decoration:none}.showapplication-wrapper .personal-description .row.file-container .file:hover{background-color:#e2e2e2;text-decoration:none;cursor:pointer}.showapplication-wrapper .personal-description .row.file-container .file .icon-pdf{display:inline-block;width:2rem}.showapplication-wrapper .personal-description .row.file-container .file .icon-download{float:right;margin-top:.5rem}.showapplication-wrapper .personal-description .row.file-container .file span{display:inline-block;text-align:center;float:none;white-space:nowrap;width:auto;padding:0 2rem}.showapplication-wrapper .personal-description .row .name{font-size:1.6rem;padding-bottom:2rem;width:80%;margin:auto;float:left}.showapplication-wrapper .personal-description .row .date{float:right;width:auto}.showapplication-wrapper .personal-description .row .placeholder{float:left;width:auto;width:10%}.showapplication-wrapper .container-buttons{width:66%;margin:2rem auto auto;display:flex;text-align:center;justify-content:space-between}.showapplication-wrapper .container-buttons .btn-jobapplications{margin:unset}.status-select{width:auto;margin:0 !important;margin-bottom:-5px !important;display:inline-block;margin-top:.8rem !important;float:left}.status-select .spinner{display:none;margin-top:1px;margin-left:2px;width:auto;float:left;height:20px}.status-select .spinner-active{display:block}.status-select select{float:left;border:none;margin-top:2px;margin-left:-3px;background-color:transparent;cursor:pointer}.status-select select.list{-webkit-appearance:none;-moz-appearance:none;appearance:none}.status-select select option{text-align:right}.status-select select:focus{border:none}#show-spinner{width:auto;margin-top:0 !important;float:left}.dashboard{width:100%;margin:0;height:100%}.dashboard .top{margin-top:2rem;padding:0 10%}.dashboard .top h3{text-align:center;margin:1rem 0}.dashboard .middle{padding:5% 10%;display:flex;flex-wrap:wrap;flex-direction:row;justify-content:center;width:100%;position:absolute;height:100%;top:0}.dashboard .middle .button-box{display:inline-block;background-color:#E62E29;border:.2rem solid #E62E29;width:26vh;height:26vh;padding:1rem;transition:background-color .1s,color .1s,border .1s,box-shadow .1s,font-size .1s;box-shadow:0 1px 6px 0 rgba(32,33,36,0.28);text-align:center;color:#fff;text-decoration:none;font-size:1.6rem;line-height:1.5;margin:auto 2rem}.dashboard .middle .button-box span{display:block;position:relative;letter-spacing:1px;top:50%;transform:translateY(-50%);text-decoration:none}.dashboard .middle .button-box:hover{border:.2rem solid #fff;font-size:1.5rem;cursor:pointer;text-decoration:none;color:#fff;box-shadow:none;line-height:1.5}.dashboard .middle .settings{background-color:#ffd02a;border:.2rem solid #ffd02a}.footer{position:absolute;bottom:1rem;width:98%;text-align:center}.settings{padding:2rem}.settings .middle{display:flex;padding:2rem}.settings .middle .container{padding:1rem;width:45%;margin:0 5%;border:solid 1px rgba(0,0,0,0.13);border-radius:8px} \ No newline at end of file diff --git a/Resources/Public/Css/backend.less b/Resources/Public/Css/backend.less index ab64752..da589e4 100644 --- a/Resources/Public/Css/backend.less +++ b/Resources/Public/Css/backend.less @@ -9,7 +9,7 @@ html { box-sizing: border-box; - font-size: 10px; + font-size: 10px !important; } body { @@ -298,6 +298,7 @@ hr { border: 1px solid @color-grey; padding: 0.5rem 1rem; margin: 1.5rem 1rem; + width: auto; text-decoration: none; &:hover { diff --git a/composer.json b/composer.json index 6b48e2c..01be551 100644 --- a/composer.json +++ b/composer.json @@ -24,6 +24,7 @@ }, "require": { "php": ">=8.0", + "ext-openssl": "*", "typo3/cms-core": "^10.4 || ^11.5", "typo3/cms-scheduler": "*", "typo3/cms-dashboard": "*" From b6dc75954b53f91206529b389e8bdfb3652fcf57 Mon Sep 17 00:00:00 2001 From: Benjamin Jasper Date: Thu, 3 Mar 2022 15:24:27 +0100 Subject: [PATCH 24/61] fix: fixed issues outlined by phpstan --- Classes/Controller/BackendController.php | 24 +++++++++++++----------- Classes/Hooks/TCEmainHook.php | 6 +++--- Classes/Task/CleanUpApplications.php | 8 +++++++- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/Classes/Controller/BackendController.php b/Classes/Controller/BackendController.php index af61c86..4484feb 100644 --- a/Classes/Controller/BackendController.php +++ b/Classes/Controller/BackendController.php @@ -89,6 +89,13 @@ class BackendController extends ActionController */ protected $applicationFileService; + protected GoogleIndexingApiConnector $connector; + + public function __construct(GoogleIndexingApiConnector $connector) + { + $this->connector = $connector; + } + /** * action listApplications * @@ -321,7 +328,6 @@ public function settingsAction(): ResponseInterface if ($this->request->hasArgument('batch_index')) { - $connector = new GoogleIndexingApiConnector(true); $postings = $this->postingRepository->findAllIncludingHiddenAndDeleted(); $removeCounter = 0; @@ -333,7 +339,7 @@ public function settingsAction(): ResponseInterface { if ($posting->isHidden() || $posting->isDeleted()) { - if (!$connector->updateGoogleIndex($posting->getUid(), true, $posting)) + if (!$this->connector->updateGoogleIndex($posting->getUid(), true, $posting)) { $error_bit = true; } @@ -342,17 +348,13 @@ public function settingsAction(): ResponseInterface $removeCounter++; } } + else if (!$this->connector->updateGoogleIndex($posting->getUid(), false, $posting)) + { + $error_bit = true; + } else { - if (!$connector->updateGoogleIndex($posting->getUid(), false, $posting)) - { - $error_bit = true; - } - else - { - $updateCounter++; - } - + $updateCounter++; } } if ($error_bit) diff --git a/Classes/Hooks/TCEmainHook.php b/Classes/Hooks/TCEmainHook.php index a52ce05..f40e5de 100644 --- a/Classes/Hooks/TCEmainHook.php +++ b/Classes/Hooks/TCEmainHook.php @@ -146,9 +146,9 @@ public function processCmdmap_deleteAction($table, $uid, array $record, &$record $application = $this->applicationRepository->findByUid($uid); } - $path = $this->fileService->getApplicantFolder($application); - $fileStorage = $this->fileService->getFileStorage($application); - $this->fileService->deleteApplicationFolder($path, $fileStorage); + $path = $this->applicationFileService->getApplicantFolder($application); + $fileStorage = $this->applicationFileService->getFileStorage($application); + $this->applicationFileService->deleteApplicationFolder($path, $fileStorage); } } } \ No newline at end of file diff --git a/Classes/Task/CleanUpApplications.php b/Classes/Task/CleanUpApplications.php index 3ea51c3..e132d89 100644 --- a/Classes/Task/CleanUpApplications.php +++ b/Classes/Task/CleanUpApplications.php @@ -43,7 +43,13 @@ class CleanUpApplications extends AbstractTask public int $days = 90; public int $status = 0; - public function __construct(PersistenceManager $persistenceManager, ApplicationRepository $applicationRepository, ApplicationFileService $applicationFileService) + protected PersistenceManager $persistenceManager; + protected ApplicationRepository $applicationRepository; + protected ApplicationFileService $applicationFileService; + + public function __construct(PersistenceManager $persistenceManager, + ApplicationRepository $applicationRepository, + ApplicationFileService $applicationFileService) { $this->persistenceManager = $persistenceManager; $this->applicationRepository = $applicationRepository; From b8caec60630bcc50c602c302859d2dff904b0056 Mon Sep 17 00:00:00 2001 From: Benjamin Jasper Date: Thu, 3 Mar 2022 15:28:13 +0100 Subject: [PATCH 25/61] fix: fixed issues outlined by phpstan --- Classes/Utility/GoogleIndexingApiConnector.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classes/Utility/GoogleIndexingApiConnector.php b/Classes/Utility/GoogleIndexingApiConnector.php index ebd9212..5a74a41 100644 --- a/Classes/Utility/GoogleIndexingApiConnector.php +++ b/Classes/Utility/GoogleIndexingApiConnector.php @@ -162,7 +162,7 @@ public function updateGoogleIndex($uid, bool $delete, Posting $specificPosting = } else { - $result = $this->makeRequest($url); + $result = $this->makeRequest($url, false); } if ($result && $delete === false) From 78f5cfa6e78ff21a569eeaf11b70d11ea15a32e6 Mon Sep 17 00:00:00 2001 From: Benjamin Jasper Date: Thu, 3 Mar 2022 15:29:19 +0100 Subject: [PATCH 26/61] build: test with phpstan level 2 --- phpstan.neon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpstan.neon b/phpstan.neon index e7a89e6..a37df58 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,4 +1,4 @@ parameters: - level: 1 + level: 2 paths: - Classes \ No newline at end of file From 8b74ab411069a17e116266e7d21b772d06844df5 Mon Sep 17 00:00:00 2001 From: Benjamin Jasper Date: Thu, 3 Mar 2022 16:18:32 +0100 Subject: [PATCH 27/61] build: reverted to phpstan level 1 --- Classes/Controller/ApplicationController.php | 67 ++++++++++---------- Classes/Controller/ContactController.php | 15 ++--- Classes/Controller/PostingController.php | 25 ++++---- phpstan.neon | 2 +- 4 files changed, 53 insertions(+), 56 deletions(-) diff --git a/Classes/Controller/ApplicationController.php b/Classes/Controller/ApplicationController.php index fc3c47e..cd06c17 100644 --- a/Classes/Controller/ApplicationController.php +++ b/Classes/Controller/ApplicationController.php @@ -48,6 +48,11 @@ use TYPO3\CMS\Core\Mail\Mailer; use TYPO3\CMS\Core\Messaging\FlashMessage; use TYPO3\CMS\Core\Resource\Driver\LocalDriver; + use TYPO3\CMS\Core\Resource\Exception\ExistingTargetFileNameException; + 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\Exception\InvalidFileNameException; use TYPO3\CMS\Core\Resource\File; use TYPO3\CMS\Core\Resource\FileInterface; use TYPO3\CMS\Core\Resource\ResourceStorage; @@ -56,10 +61,14 @@ use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\MathUtility; use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; + use TYPO3\CMS\Extbase\Mvc\Exception\StopActionException; use TYPO3\CMS\Extbase\Mvc\View\ViewInterface; + use TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException; use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager; use TYPO3\CMS\Extbase\Property\TypeConverter\DateTimeConverter; use TYPO3\CMS\Extbase\SignalSlot\Dispatcher; + use TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotException; + use TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotReturnException; use TYPO3\CMS\Extbase\Utility\LocalizationUtility; /** @@ -307,16 +316,15 @@ private function isStringArray(?array $array): bool * @param Application $newApplication * @param Posting|null $posting * - * @throws \TYPO3\CMS\Core\Resource\Exception\ExistingTargetFileNameException - * @throws \TYPO3\CMS\Core\Resource\Exception\ExistingTargetFolderException - * @throws \TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException - * @throws \TYPO3\CMS\Core\Resource\Exception\InsufficientFolderWritePermissionsException - * @throws \TYPO3\CMS\Core\Resource\Exception\InvalidFileNameException - * @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException - * @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException - * @throws \TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotException - * @throws \TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotReturnException - * @throws \TYPO3\CMS\Form\Domain\Exception\IdentifierNotValidException + * @throws ExistingTargetFileNameException + * @throws ExistingTargetFolderException + * @throws InsufficientFolderAccessPermissionsException + * @throws InsufficientFolderWritePermissionsException + * @throws InvalidFileNameException + * @throws StopActionException + * @throws IllegalObjectTypeException + * @throws InvalidSlotException + * @throws InvalidSlotReturnException */ public function createAction(Application $newApplication, Posting $posting = null): void { @@ -578,11 +586,11 @@ public function createAction(Application $newApplication, Posting $posting = nul * @param string $fileNamePrefix * * @return array - * @throws \TYPO3\CMS\Core\Resource\Exception\ExistingTargetFileNameException - * @throws \TYPO3\CMS\Core\Resource\Exception\ExistingTargetFolderException - * @throws \TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException - * @throws \TYPO3\CMS\Core\Resource\Exception\InsufficientFolderWritePermissionsException - * @throws \TYPO3\CMS\Core\Resource\Exception\InvalidFileNameException + * @throws ExistingTargetFileNameException + * @throws ExistingTargetFolderException + * @throws InsufficientFolderAccessPermissionsException + * @throws InsufficientFolderWritePermissionsException + * @throws InvalidFileNameException */ private function processFiles(Application $newApplication, array $fileIds, string $fieldName, int $fileStorage, string $fileNamePrefix = ''): array { @@ -611,21 +619,21 @@ private function processFiles(Application $newApplication, array $fileIds, strin } /** - * @param string $filePath - * @param string $fileName - * @param \ITX\Jobapplications\Domain\Model\Application $domainObject - * @param int $fileStorage - * @param string $prefix + * @param string $filePath + * @param string $fileName + * @param Application $domainObject + * @param int $fileStorage + * @param string $prefix * * @return File|FileInterface - * @throws \TYPO3\CMS\Core\Resource\Exception\ExistingTargetFileNameException - * @throws \TYPO3\CMS\Core\Resource\Exception\ExistingTargetFolderException - * @throws \TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException - * @throws \TYPO3\CMS\Core\Resource\Exception\InsufficientFolderWritePermissionsException - * @throws \TYPO3\CMS\Core\Resource\Exception\InvalidFileNameException + * @throws ExistingTargetFileNameException + * @throws ExistingTargetFolderException + * @throws InsufficientFolderAccessPermissionsException + * @throws InsufficientFolderWritePermissionsException + * @throws InvalidFileNameException */ - private function handleFileUpload(string $filePath, string $fileName, - \ITX\Jobapplications\Domain\Model\Application $domainObject, int $fileStorage, string $prefix = ''): FileInterface + private function handleFileUpload(string $filePath, string $fileName, + Application $domainObject, int $fileStorage, string $prefix = ''): File|FileInterface { $folder = $this->applicationFileService->getApplicantFolder($domainObject); @@ -636,11 +644,6 @@ private function handleFileUpload(string throw new \RuntimeException(sprintf("Resource storage with uid %d could not be found.", $fileStorage)); } - if (!$storage instanceof ResourceStorage) - { - throw new FileNotFoundException("Could not find fileadmin with uid 1"); - } - //build the new storage folder if ($storage->hasFolder($folder)) { diff --git a/Classes/Controller/ContactController.php b/Classes/Controller/ContactController.php index 8418790..33754e4 100644 --- a/Classes/Controller/ContactController.php +++ b/Classes/Controller/ContactController.php @@ -2,9 +2,9 @@ namespace ITX\Jobapplications\Controller; - use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; - use Psr\Http\Message\ResponseInterface; use ITX\Jobapplications\Domain\Repository\ContactRepository; + use Psr\Http\Message\ResponseInterface; + use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; use TYPO3\CMS\Extbase\Mvc\View\ViewInterface; /*************************************************************** @@ -35,13 +35,7 @@ */ class ContactController extends ActionController { - - /** - * contactRepository - * - * @var \ITX\Jobapplications\Domain\Repository\ContactRepository - */ - protected $contactRepository = null; + protected ContactRepository $contactRepository; /** * Initializes the view before invoking an action method. @@ -65,7 +59,7 @@ public function initializeView(ViewInterface $view) * * @param ITX\Jobapplications\Domain\Model\Contact * - * @return void + * @return ResponseInterface */ public function listAction(): ResponseInterface { @@ -87,6 +81,7 @@ public function listAction(): ResponseInterface $contactObjects = array_replace(array_flip($contacts), $contactByUid); $this->view->assign('contacts', $contactObjects); + return $this->htmlResponse(); } diff --git a/Classes/Controller/PostingController.php b/Classes/Controller/PostingController.php index 9a6a643..f0118a1 100644 --- a/Classes/Controller/PostingController.php +++ b/Classes/Controller/PostingController.php @@ -2,22 +2,22 @@ namespace ITX\Jobapplications\Controller; - use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; - use Psr\Http\Message\ResponseInterface; - use TYPO3\CMS\Extbase\Persistence\QueryInterface; - use TYPO3\CMS\Core\Cache\CacheManager; - use ITX\Jobapplications\Domain\Repository\PostingRepository; - use ITX\Jobapplications\Domain\Repository\LocationRepository; - use TYPO3\CMS\Extbase\SignalSlot\Dispatcher; use ITX\Jobapplications\Domain\Model\Constraint; use ITX\Jobapplications\Domain\Model\Posting; + use ITX\Jobapplications\Domain\Repository\LocationRepository; + use ITX\Jobapplications\Domain\Repository\PostingRepository; use ITX\Jobapplications\PageTitle\JobsPageTitleProvider; + use Psr\Http\Message\ResponseInterface; + use TYPO3\CMS\Core\Cache\CacheManager; use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface; use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; use TYPO3\CMS\Core\Http\ImmediateResponseException; use TYPO3\CMS\Core\Page\PageRenderer; use TYPO3\CMS\Core\Utility\GeneralUtility; + use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; use TYPO3\CMS\Extbase\Mvc\View\ViewInterface; + use TYPO3\CMS\Extbase\Persistence\QueryInterface; + use TYPO3\CMS\Extbase\SignalSlot\Dispatcher; use TYPO3\CMS\Frontend\Controller\ErrorController; /*************************************************************** @@ -75,15 +75,12 @@ class PostingController extends ActionController * * @param void */ - public function initializeShowAction() + public function initializeShowAction(): void { // If application form an posting are on the same page, the posting object is part of the application plugin. - if (!$this->request->hasArgument("posting")) + if (!$this->request->hasArgument("posting") && isset($_REQUEST["tx_jobapplications_applicationform"]["posting"])) { - if (isset($_REQUEST["tx_jobapplications_applicationform"]["posting"])) - { - $this->request->setArgument("posting", $_REQUEST["tx_jobapplications_applicationform"]["posting"]); - } + $this->request->setArgument("posting", $_REQUEST["tx_jobapplications_applicationform"]["posting"]); } } @@ -162,6 +159,7 @@ public function listAction(Constraint $constraint = null): ResponseInterface $this->view->assign('isFiltering', $isFiltering); $this->view->assign('filterOptions', $filterOptions); $this->view->assign('constraint', $constraint); + return $this->htmlResponse(); } @@ -349,6 +347,7 @@ public function showAction(Posting $posting = null): ResponseInterface } $this->view->assign('posting', $posting); + return $this->htmlResponse(); } diff --git a/phpstan.neon b/phpstan.neon index a37df58..e7a89e6 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,4 +1,4 @@ parameters: - level: 2 + level: 1 paths: - Classes \ No newline at end of file From ce5d9c0617afc4a0b2e79dc0eb344b213e13d561 Mon Sep 17 00:00:00 2001 From: Benjamin Jasper Date: Fri, 4 Mar 2022 16:06:09 +0100 Subject: [PATCH 28/61] fix: fixed filters, upgraded selectize and reworked pagination --- Classes/Controller/BackendController.php | 31 +- Classes/Controller/PostingController.php | 43 +- .../Domain/Repository/PostingRepository.php | 24 +- .../Templates/Backend/ListApplications.html | 3 +- Resources/Private/Partials/Pagination.html | 17 + Resources/Private/Templates/Posting/List.html | 7 +- .../Css/Vendor/selectize.bootstrap3.css | 417 -- .../Css/Vendor/selectize.bootstrap5.css | 6 + Resources/Public/Css/Vendor/selectize.css | 327 +- Resources/Public/Js/Vendor/selectize.js | 3893 +---------------- Resources/Public/Js/Vendor/selectize.min.js | 6 +- 11 files changed, 113 insertions(+), 4661 deletions(-) create mode 100644 Resources/Private/Partials/Pagination.html delete mode 100644 Resources/Public/Css/Vendor/selectize.bootstrap3.css create mode 100644 Resources/Public/Css/Vendor/selectize.bootstrap5.css diff --git a/Classes/Controller/BackendController.php b/Classes/Controller/BackendController.php index 4484feb..3e7c0b4 100644 --- a/Classes/Controller/BackendController.php +++ b/Classes/Controller/BackendController.php @@ -25,6 +25,7 @@ namespace ITX\Jobapplications\Controller; + use TYPO3\CMS\Core\Pagination\SimplePagination; use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; use ITX\Jobapplications\Domain\Model\Application; use Psr\Http\Message\ResponseInterface; @@ -32,6 +33,10 @@ use ITX\Jobapplications\Domain\Repository\PostingRepository; use ITX\Jobapplications\Domain\Repository\ContactRepository; use ITX\Jobapplications\Domain\Repository\StatusRepository; + use TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException; + use TYPO3\CMS\Extbase\Pagination\QueryResultPaginator; + use TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException; + use TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException; use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager; use ITX\Jobapplications\Service\ApplicationFileService; use ITX\Jobapplications\Domain\Model\Contact; @@ -100,12 +105,15 @@ public function __construct(GoogleIndexingApiConnector $connector) * action listApplications * * @return void - * @throws \TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException - * @throws \TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException - * @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException + * @throws NoSuchArgumentException + * @throws UnknownObjectException + * @throws IllegalObjectTypeException */ public function listApplicationsAction() { + $page = $this->request->hasArgument('page') ? (int)$this->request->getArgument('page') : 1; + $itemsPerPage = 12; + $sessionData = $GLOBALS['BE_USER']->getSessionData('tx_jobapplications'); $contact = $this->getActiveBeContact(); @@ -179,11 +187,18 @@ public function listApplicationsAction() $sessionData['selectedStatus'] = $selectedStatus; $GLOBALS['BE_USER']->setAndSaveSessionData('tx_jobapplications', $sessionData); + $paginator = new QueryResultPaginator($applications, $page, $itemsPerPage); + + $pagination = new SimplePagination($paginator); + + $this->view->assign('paginator', $paginator); + $this->view->assign('pagination', $pagination); + $this->view->assign('applications', $paginator->getPaginatedItems()); + $this->view->assign('selectedPosting', $selectedPosting); $this->view->assign('archivedSelected', $archivedSelected); $this->view->assign('selectedContact', $selectedContact); $this->view->assign('selectedStatus', $selectedStatus); - $this->view->assign('applications', $applications); $this->view->assign('postings', $postingsFilter); $this->view->assign('contacts', $contactsFilter); $this->view->assign('statuses', $statusesFilter); @@ -206,11 +221,11 @@ private function getActiveBeContact() * * @param \ITX\Jobapplications\Domain\Model\Application $application * - * @throws \TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException + * @throws UnknownObjectException * @throws \TYPO3\CMS\Core\Resource\Exception\InvalidFileNameException * @throws \TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException - * @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException - * @throws \TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException + * @throws IllegalObjectTypeException + * @throws NoSuchArgumentException * @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException */ public function showApplicationAction(Application $application) @@ -305,7 +320,7 @@ public function dashboardAction(): ResponseInterface * Action for settings page * * @throws InsufficientUserPermissionsException - * @throws \TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException + * @throws NoSuchArgumentException * @throws \Exception */ public function settingsAction(): ResponseInterface diff --git a/Classes/Controller/PostingController.php b/Classes/Controller/PostingController.php index 84de988..e153fc6 100644 --- a/Classes/Controller/PostingController.php +++ b/Classes/Controller/PostingController.php @@ -13,12 +13,19 @@ use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; use TYPO3\CMS\Core\Http\ImmediateResponseException; use TYPO3\CMS\Core\Page\PageRenderer; + use TYPO3\CMS\Core\Pagination\SimplePagination; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\MathUtility; use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; + use TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException; use TYPO3\CMS\Extbase\Mvc\View\ViewInterface; + use TYPO3\CMS\Extbase\Pagination\QueryResultPaginator; + use TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException; use TYPO3\CMS\Extbase\Persistence\QueryInterface; + use TYPO3\CMS\Extbase\Reflection\Exception\UnknownClassException; use TYPO3\CMS\Extbase\SignalSlot\Dispatcher; + use TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotException; + use TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotReturnException; use TYPO3\CMS\Frontend\Controller\ErrorController; /*************************************************************** @@ -103,13 +110,17 @@ public function initializeView(ViewInterface $view) } /** - * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException - * @throws \TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotException - * @throws \TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotReturnException - * @throws \TYPO3\CMS\Extbase\Reflection\Exception\UnknownClassException + * @throws InvalidQueryException + * @throws InvalidSlotException + * @throws InvalidSlotReturnException + * @throws UnknownClassException + * @throws NoSuchArgumentException */ public function listAction(Constraint $constraint = null): ResponseInterface { + $page = $this->request->hasArgument('page') ? (int)$this->request->getArgument('page') : 1; + $itemsPerPage = 1; + // Plugin selected categories $category_str = $this->settings["categories"]; $categories = !empty($category_str) ? explode(",", $category_str) : []; @@ -156,7 +167,13 @@ public function listAction(Constraint $constraint = null): ResponseInterface $isFiltering = true; } - $this->view->assign('postings', $postings); + $paginator = new QueryResultPaginator($postings, $page, $itemsPerPage); + + $pagination = new SimplePagination($paginator); + + $this->view->assign('postings', $paginator->getPaginatedItems()); + $this->view->assign('paginator', $paginator); + $this->view->assign('pagination', $pagination); $this->view->assign('isFiltering', $isFiltering); $this->view->assign('filterOptions', $filterOptions); $this->view->assign('constraint', $constraint); @@ -168,7 +185,7 @@ public function listAction(Constraint $constraint = null): ResponseInterface * @param array $categories * * @return array - * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException + * @throws InvalidQueryException */ private function getCachedFilterOptions(array $categories): array { @@ -206,15 +223,15 @@ private function getCachedFilterOptions(array $categories): array * @param $categories array categories * * @return array - * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException + * @throws InvalidQueryException */ public function getFilterOptions(array $categories): array { return [ - //'division' => $this->postingRepository->findAllDivisions($categories), - //'careerLevel' => $this->postingRepository->findAllCareerLevels($categories), - //'employmentType' => $this->postingRepository->findAllEmploymentTypes($categories), - //'location' => $this->locationRepository->findAll($categories)->toArray(), + 'division' => $this->postingRepository->findAllDivisions($categories), + 'careerLevel' => $this->postingRepository->findAllCareerLevels($categories), + 'employmentType' => $this->postingRepository->findAllEmploymentTypes($categories), + 'location' => $this->locationRepository->findAll($categories)->toArray(), ]; } @@ -226,8 +243,8 @@ public function getFilterOptions(array $categories): array * @throws \TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationExtensionNotConfiguredException * @throws \TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationPathDoesNotExistException * @throws \TYPO3\CMS\Core\Error\Http\PageNotFoundException - * @throws \TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotException - * @throws \TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotReturnException + * @throws InvalidSlotException + * @throws InvalidSlotReturnException */ public function showAction(Posting $posting = null): ResponseInterface { diff --git a/Classes/Domain/Repository/PostingRepository.php b/Classes/Domain/Repository/PostingRepository.php index a191276..3fb055e 100644 --- a/Classes/Domain/Repository/PostingRepository.php +++ b/Classes/Domain/Repository/PostingRepository.php @@ -43,13 +43,13 @@ class PostingRepository extends JobapplicationsRepository * * @param $category array * - * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface + * @return array|QueryResultInterface */ public function findByCategory(array $categories) { $query = $this->createQuery(); - $qb = parent::getQueryBuilder("tx_jobapplications_domain_model_posting"); + $qb = $this->getQueryBuilder("tx_jobapplications_domain_model_posting"); $qb ->select("*") @@ -57,7 +57,7 @@ public function findByCategory(array $categories) ->join("tx_jobapplications_domain_model_posting", "sys_category_record_mm", "sys_category_record_mm", "tx_jobapplications_domain_model_posting.uid = sys_category_record_mm.uid_foreign") ->andWhere($qb->expr()->in('pid', $query->getQuerySettings()->getStoragePageIds())); - $qb = parent::buildCategoriesToSQL($categories, $qb); + $qb = $this->buildCategoriesToSQL($categories, $qb); $query->statement($qb->getSQL()); @@ -67,12 +67,16 @@ public function findByCategory(array $categories) /** * Gets all divisions * - * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface + * @param array|null $categories + * + * @return array|QueryResultInterface */ - public function findAllDivisions(array $categories = null) + public function findAllDivisions(array $categories = null): QueryResultInterface|array { $qb = $this->getQueryBuilder("tx_jobapplications_domain_model_posting"); $query = $this->createQuery(); + $query->getQuerySettings()->setLanguageOverlayMode(false); + if (count($categories) === 0) { $qb @@ -103,13 +107,15 @@ public function findAllDivisions(array $categories = null) } /** - * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface + * @return array|QueryResultInterface */ public function findAllCareerLevels(array $categories = null) { $qb = $this->getQueryBuilder("tx_jobapplications_domain_model_posting"); $query = $this->createQuery(); + $query->getQuerySettings()->setLanguageOverlayMode(false); + if (count($categories) === 0) { $qb @@ -147,6 +153,8 @@ public function findAllEmploymentTypes(array $categories = null) $qb = $this->getQueryBuilder("tx_jobapplications_domain_model_posting"); $query = $this->createQuery(); + $query->getQuerySettings()->setLanguageOverlayMode(false); + if (count($categories) === 0) { $qb @@ -198,7 +206,7 @@ public function findAllEmploymentTypes(array $categories = null) /** * @param $categories * - * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface + * @return array|QueryResultInterface */ public function findAllCategories($categories) { @@ -361,7 +369,7 @@ public function findAllWithOrderIgnoreEnable(string $orderBy = "title", string $ } /** - * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface + * @return array|QueryResultInterface */ public function findAllIgnoreStoragePage() { diff --git a/Resources/Private/Backend/Templates/Backend/ListApplications.html b/Resources/Private/Backend/Templates/Backend/ListApplications.html index c582039..b8020ab 100644 --- a/Resources/Private/Backend/Templates/Backend/ListApplications.html +++ b/Resources/Private/Backend/Templates/Backend/ListApplications.html @@ -62,7 +62,6 @@

-
  • @@ -113,6 +112,8 @@

+ +
diff --git a/Resources/Private/Partials/Pagination.html b/Resources/Private/Partials/Pagination.html new file mode 100644 index 0000000..341bd00 --- /dev/null +++ b/Resources/Private/Partials/Pagination.html @@ -0,0 +1,17 @@ + + + \ No newline at end of file diff --git a/Resources/Private/Templates/Posting/List.html b/Resources/Private/Templates/Posting/List.html index 5beb33f..125ea97 100644 --- a/Resources/Private/Templates/Posting/List.html +++ b/Resources/Private/Templates/Posting/List.html @@ -5,7 +5,7 @@ - +
@@ -87,6 +87,11 @@

+
+
+ +
+
diff --git a/Resources/Public/Css/Vendor/selectize.bootstrap3.css b/Resources/Public/Css/Vendor/selectize.bootstrap3.css deleted file mode 100644 index 7c50f61..0000000 --- a/Resources/Public/Css/Vendor/selectize.bootstrap3.css +++ /dev/null @@ -1,417 +0,0 @@ -/** - * selectize.bootstrap3.css (v0.12.6) - Bootstrap 3 Theme - * Copyright (c) 2013–2015 Brian Reavis & contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this - * file except in compliance with the License. You may obtain a copy of the License at: - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under - * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF - * ANY KIND, either express or implied. See the License for the specific language - * governing permissions and limitations under the License. - * - * @author Brian Reavis - */ -.selectize-control.plugin-drag_drop.multi > .selectize-input > div.ui-sortable-placeholder { - visibility: visible !important; - background: #f2f2f2 !important; - background: rgba(0, 0, 0, 0.06) !important; - border: 0 none !important; - -webkit-box-shadow: inset 0 0 12px 4px #fff; - box-shadow: inset 0 0 12px 4px #fff; -} -.selectize-control.plugin-drag_drop .ui-sortable-placeholder::after { - content: '!'; - visibility: hidden; -} -.selectize-control.plugin-drag_drop .ui-sortable-helper { - -webkit-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); - box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); -} -.selectize-dropdown-header { - position: relative; - padding: 3px 12px; - border-bottom: 1px solid #d0d0d0; - background: #f8f8f8; - -webkit-border-radius: 4px 4px 0 0; - -moz-border-radius: 4px 4px 0 0; - border-radius: 4px 4px 0 0; -} -.selectize-dropdown-header-close { - position: absolute; - right: 12px; - top: 50%; - color: #333333; - opacity: 0.4; - margin-top: -12px; - line-height: 20px; - font-size: 20px !important; -} -.selectize-dropdown-header-close:hover { - color: #000000; -} -.selectize-dropdown.plugin-optgroup_columns .optgroup { - border-right: 1px solid #f2f2f2; - border-top: 0 none; - float: left; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} -.selectize-dropdown.plugin-optgroup_columns .optgroup:last-child { - border-right: 0 none; -} -.selectize-dropdown.plugin-optgroup_columns .optgroup:before { - display: none; -} -.selectize-dropdown.plugin-optgroup_columns .optgroup-header { - border-top: 0 none; -} -.selectize-control.plugin-remove_button [data-value] { - position: relative; - padding-right: 24px !important; -} -.selectize-control.plugin-remove_button [data-value] .remove { - z-index: 1; - /* fixes ie bug (see #392) */ - position: absolute; - top: 0; - right: 0; - bottom: 0; - width: 17px; - text-align: center; - font-weight: bold; - font-size: 12px; - color: inherit; - text-decoration: none; - vertical-align: middle; - display: inline-block; - padding: 1px 0 0 0; - border-left: 1px solid rgba(0, 0, 0, 0); - -webkit-border-radius: 0 2px 2px 0; - -moz-border-radius: 0 2px 2px 0; - border-radius: 0 2px 2px 0; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} -.selectize-control.plugin-remove_button [data-value] .remove:hover { - background: rgba(0, 0, 0, 0.05); -} -.selectize-control.plugin-remove_button [data-value].active .remove { - border-left-color: rgba(0, 0, 0, 0); -} -.selectize-control.plugin-remove_button .disabled [data-value] .remove:hover { - background: none; -} -.selectize-control.plugin-remove_button .disabled [data-value] .remove { - border-left-color: rgba(77, 77, 77, 0); -} -.selectize-control.plugin-remove_button .remove-single { - position: absolute; - right: 0; - top: 0; - font-size: 23px; -} -.selectize-control { - position: relative; -} -.selectize-dropdown, -.selectize-input, -.selectize-input input { - color: #333333; - font-family: inherit; - font-size: inherit; - line-height: 20px; - -webkit-font-smoothing: inherit; -} -.selectize-input, -.selectize-control.single .selectize-input.input-active { - background: #fff; - cursor: text; - display: inline-block; -} -.selectize-input { - border: 1px solid #ccc; - padding: 6px 12px; - display: inline-block; - width: 100%; - overflow: hidden; - position: relative; - z-index: 1; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - -webkit-box-shadow: none; - box-shadow: none; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} -.selectize-control.multi .selectize-input.has-items { - padding: 5px 12px 2px; -} -.selectize-input.full { - background-color: #fff; -} -.selectize-input.disabled, -.selectize-input.disabled * { - cursor: default !important; -} -.selectize-input.focus { - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15); -} -.selectize-input.dropdown-active { - -webkit-border-radius: 4px 4px 0 0; - -moz-border-radius: 4px 4px 0 0; - border-radius: 4px 4px 0 0; -} -.selectize-input > * { - vertical-align: baseline; - display: -moz-inline-stack; - display: inline-block; - zoom: 1; - *display: inline; -} -.selectize-control.multi .selectize-input > div { - cursor: pointer; - margin: 0 3px 3px 0; - padding: 1px 3px; - background: #efefef; - color: #333333; - border: 0 solid rgba(0, 0, 0, 0); -} -.selectize-control.multi .selectize-input > div.active { - background: #428bca; - color: #fff; - border: 0 solid rgba(0, 0, 0, 0); -} -.selectize-control.multi .selectize-input.disabled > div, -.selectize-control.multi .selectize-input.disabled > div.active { - color: #808080; - background: #ffffff; - border: 0 solid rgba(77, 77, 77, 0); -} -.selectize-input > input { - display: inline-block !important; - padding: 0 !important; - min-height: 0 !important; - max-height: none !important; - max-width: 100% !important; - margin: 0 !important; - text-indent: 0 !important; - border: 0 none !important; - background: none !important; - line-height: inherit !important; - -webkit-user-select: auto !important; - -webkit-box-shadow: none !important; - box-shadow: none !important; -} -.selectize-input > input::-ms-clear { - display: none; -} -.selectize-input > input:focus { - outline: none !important; -} -.selectize-input::after { - content: ' '; - display: block; - clear: left; -} -.selectize-input.dropdown-active::before { - content: ' '; - display: block; - position: absolute; - background: #ffffff; - height: 1px; - bottom: 0; - left: 0; - right: 0; -} -.selectize-dropdown { - position: absolute; - z-index: 10; - border: 1px solid #d0d0d0; - background: #fff; - margin: -1px 0 0 0; - border-top: 0 none; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); - -webkit-border-radius: 0 0 4px 4px; - -moz-border-radius: 0 0 4px 4px; - border-radius: 0 0 4px 4px; -} -.selectize-dropdown [data-selectable] { - cursor: pointer; - overflow: hidden; -} -.selectize-dropdown [data-selectable] .highlight { - background: rgba(255, 237, 40, 0.4); - -webkit-border-radius: 1px; - -moz-border-radius: 1px; - border-radius: 1px; -} -.selectize-dropdown .option, -.selectize-dropdown .optgroup-header { - padding: 3px 12px; -} -.selectize-dropdown .option, -.selectize-dropdown [data-disabled], -.selectize-dropdown [data-disabled] [data-selectable].option { - cursor: inherit; - opacity: 0.5; -} -.selectize-dropdown [data-selectable].option { - opacity: 1; -} -.selectize-dropdown .optgroup:first-child .optgroup-header { - border-top: 0 none; -} -.selectize-dropdown .optgroup-header { - color: #777777; - background: #fff; - cursor: default; -} -.selectize-dropdown .active { - background-color: #f5f5f5; - color: #262626; -} -.selectize-dropdown .active.create { - color: #262626; -} -.selectize-dropdown .create { - color: rgba(51, 51, 51, 0.5); -} -.selectize-dropdown-content { - overflow-y: auto; - overflow-x: hidden; - max-height: 200px; - -webkit-overflow-scrolling: touch; -} -.selectize-control.single .selectize-input, -.selectize-control.single .selectize-input input { - cursor: pointer; -} -.selectize-control.single .selectize-input.input-active, -.selectize-control.single .selectize-input.input-active input { - cursor: text; -} -.selectize-control.single .selectize-input:after { - content: ' '; - display: block; - position: absolute; - top: 50%; - right: 17px; - margin-top: -3px; - width: 0; - height: 0; - border-style: solid; - border-width: 5px 5px 0 5px; - border-color: #333333 transparent transparent transparent; -} -.selectize-control.single .selectize-input.dropdown-active:after { - margin-top: -4px; - border-width: 0 5px 5px 5px; - border-color: transparent transparent #333333 transparent; -} -.selectize-control.rtl.single .selectize-input:after { - left: 17px; - right: auto; -} -.selectize-control.rtl .selectize-input > input { - margin: 0 4px 0 -2px !important; -} -.selectize-control .selectize-input.disabled { - opacity: 0.5; - background-color: #fff; -} -.selectize-dropdown, -.selectize-dropdown.form-control { - height: auto; - padding: 0; - margin: 2px 0 0 0; - z-index: 1000; - background: #fff; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.15); - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); - box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); -} -.selectize-dropdown .optgroup-header { - font-size: 12px; - line-height: 1.42857143; -} -.selectize-dropdown .optgroup:first-child:before { - display: none; -} -.selectize-dropdown .optgroup:before { - content: ' '; - display: block; - height: 1px; - margin: 9px 0; - overflow: hidden; - background-color: #e5e5e5; - margin-left: -12px; - margin-right: -12px; -} -.selectize-dropdown-content { - padding: 5px 0; -} -.selectize-dropdown-header { - padding: 6px 12px; -} -.selectize-input { - min-height: 34px; -} -.selectize-input.dropdown-active { - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} -.selectize-input.dropdown-active::before { - display: none; -} -.selectize-input.focus { - border-color: #66afe9; - outline: 0; - -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); - box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); -} -.has-error .selectize-input { - border-color: #a94442; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} -.has-error .selectize-input:focus { - border-color: #843534; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; -} -.selectize-control.multi .selectize-input.has-items { - padding-left: 9px; - padding-right: 9px; -} -.selectize-control.multi .selectize-input > div { - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} -.form-control.selectize-control { - padding: 0; - height: auto; - border: none; - background: none; - -webkit-box-shadow: none; - box-shadow: none; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} diff --git a/Resources/Public/Css/Vendor/selectize.bootstrap5.css b/Resources/Public/Css/Vendor/selectize.bootstrap5.css new file mode 100644 index 0000000..5b01258 --- /dev/null +++ b/Resources/Public/Css/Vendor/selectize.bootstrap5.css @@ -0,0 +1,6 @@ +.selectize-control.plugin-drag_drop.multi>.selectize-input>div.ui-sortable-placeholder{visibility:visible !important;background:#f2f2f2 !important;background:rgba(0,0,0,.06) !important;border:0 none !important;box-shadow:inset 0 0 12px 4px #fff}.selectize-control.plugin-drag_drop .ui-sortable-placeholder::after{content:"!";visibility:hidden}.selectize-control.plugin-drag_drop .ui-sortable-helper{box-shadow:0 2px 5px rgba(0,0,0,.2)}.selectize-control .dropdown-header{position:relative;padding:6px .75rem;border-bottom:1px solid #d0d0d0;background:#f8f8f8;border-radius:.25rem .25rem 0 0}.selectize-control .dropdown-header-close{position:absolute;right:.75rem;top:50%;color:#343a40;opacity:.4;margin-top:-12px;line-height:20px;font-size:20px !important}.selectize-control .dropdown-header-close:hover{color:#000}.selectize-dropdown.plugin-optgroup_columns .selectize-dropdown-content{display:flex}.selectize-dropdown.plugin-optgroup_columns .optgroup{border-right:1px solid #f2f2f2;border-top:0 none;flex-grow:1;flex-basis:0;min-width:0}.selectize-dropdown.plugin-optgroup_columns .optgroup:last-child{border-right:0 none}.selectize-dropdown.plugin-optgroup_columns .optgroup:before{display:none}.selectize-dropdown.plugin-optgroup_columns .optgroup-header{border-top:0 none}.selectize-control.plugin-remove_button .item{display:inline-flex;align-items:center;padding-right:0 !important}.selectize-control.plugin-remove_button .item .remove{color:inherit;text-decoration:none;vertical-align:middle;display:inline-block;padding:1px 5px;border-left:1px solid #dee2e6;border-radius:0 2px 2px 0;box-sizing:border-box;margin-left:5px}.selectize-control.plugin-remove_button .item .remove:hover{background:rgba(0,0,0,.05)}.selectize-control.plugin-remove_button .item.active .remove{border-left-color:rgba(0,0,0,0)}.selectize-control.plugin-remove_button .disabled .item .remove:hover{background:none}.selectize-control.plugin-remove_button .disabled .item .remove{border-left-color:#fff}.selectize-control.plugin-remove_button .remove-single{position:absolute;right:0;top:0;font-size:23px}.selectize-control{position:relative}.selectize-dropdown,.selectize-input,.selectize-input input{color:#343a40;font-family:inherit;font-size:inherit;line-height:1.5;font-smoothing:inherit}.selectize-input,.selectize-control.single .selectize-input.input-active{background:#fff;cursor:text;display:inline-block}.selectize-input{border:1px solid #ced4da;padding:.375rem .75rem;display:inline-block;width:100%;overflow:hidden;position:relative;z-index:1;box-sizing:border-box;box-shadow:none;border-radius:.25rem}.selectize-control.multi .selectize-input.has-items{padding:calc( + 0.375rem - 1px - 0px + ) .75rem calc( + 0.375rem - 1px - 3px - + 0px + )}.selectize-input.full{background-color:#fff}.selectize-input.disabled,.selectize-input.disabled *{cursor:default !important}.selectize-input.focus{box-shadow:inset 0 1px 2px rgba(0,0,0,.15)}.selectize-input.dropdown-active{border-radius:.25rem .25rem 0 0}.selectize-input>*{vertical-align:baseline;display:inline-block;zoom:1}.selectize-control.multi .selectize-input>div{cursor:pointer;margin:0 3px 3px 0;padding:1px 5px;background:#efefef;color:#343a40;border:0px solid #dee2e6}.selectize-control.multi .selectize-input>div.active{background:#0d6efd;color:#fff;border:0px solid rgba(0,0,0,0)}.selectize-control.multi .selectize-input.disabled>div,.selectize-control.multi .selectize-input.disabled>div.active{color:#878787;background:#fff;border:0px solid #fff}.selectize-input>input{display:inline-block !important;padding:0 !important;min-height:0 !important;max-height:none !important;max-width:100% !important;margin:0 !important;text-indent:0 !important;border:0 none !important;background:none !important;line-height:inherit !important;user-select:auto !important;box-shadow:none !important}.selectize-input>input::-ms-clear{display:none}.selectize-input>input:focus{outline:none !important}.selectize-input>input[placeholder]{box-sizing:initial}.selectize-input.has-items>input{margin:0 0px !important}.selectize-input::after{content:" ";display:block;clear:left}.selectize-input.dropdown-active::before{content:" ";display:block;position:absolute;background:#fff;height:1px;bottom:0;left:0;right:0}.selectize-dropdown{position:absolute;top:100%;left:0;width:100%;z-index:10;border:1px solid #d0d0d0;background:#fff;margin:-1px 0 0 0;border-top:0 none;box-sizing:border-box;box-shadow:0 1px 3px rgba(0,0,0,.1);border-radius:0 0 .25rem .25rem}.selectize-dropdown [data-selectable]{cursor:pointer;overflow:hidden}.selectize-dropdown [data-selectable] .highlight{background:rgba(255,237,40,.4);border-radius:1px}.selectize-dropdown .option,.selectize-dropdown .optgroup-header,.selectize-dropdown .no-results,.selectize-dropdown .create{padding:3px .75rem}.selectize-dropdown .option,.selectize-dropdown [data-disabled],.selectize-dropdown [data-disabled] [data-selectable].option{cursor:inherit;opacity:.5}.selectize-dropdown [data-selectable].option{opacity:1;cursor:pointer}.selectize-dropdown .optgroup:first-child .optgroup-header{border-top:0 none}.selectize-dropdown .optgroup-header{color:#6c757d;background:#fff;cursor:default}.selectize-dropdown .active{background-color:#e9ecef;color:#1e2125}.selectize-dropdown .active.create{color:#1e2125}.selectize-dropdown .create{color:rgba(52,58,64,.5)}.selectize-dropdown-content{overflow-y:auto;overflow-x:hidden;max-height:200px;overflow-scrolling:touch}.selectize-dropdown-emptyoptionlabel{text-align:center}.selectize-dropdown .spinner{display:inline-block;width:30px;height:30px;margin:3px .75rem}.selectize-dropdown .spinner:after{content:" ";display:block;width:24px;height:24px;margin:3px;border-radius:50%;border:5px solid #d0d0d0;border-color:#d0d0d0 transparent #d0d0d0 transparent;animation:lds-dual-ring 1.2s linear infinite}@keyframes lds-dual-ring{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}.selectize-control.single .selectize-input,.selectize-control.single .selectize-input input{cursor:pointer}.selectize-control.single .selectize-input.input-active,.selectize-control.single .selectize-input.input-active input{cursor:text}.selectize-control.single .selectize-input:after{content:" ";display:block;position:absolute;top:50%;right:calc(0.75rem + 5px);margin-top:-3px;width:0;height:0;border-style:solid;border-width:5px 5px 0 5px;border-color:#343a40 transparent transparent transparent}.selectize-control.single .selectize-input.dropdown-active:after{margin-top:-4px;border-width:0 5px 5px 5px;border-color:transparent transparent #343a40 transparent}.selectize-control.rtl{text-align:right}.selectize-control.rtl.single .selectize-input:after{left:calc(0.75rem + 5px);right:auto}.selectize-control.rtl .selectize-input>input{margin:0 4px 0 -2px !important}.selectize-control .selectize-input.disabled{opacity:.5;background-color:#fff}.selectize-dropdown,.selectize-dropdown.form-control{height:auto;padding:0;margin:2px 0 0 0;z-index:1000;background:#fff;border:1px solid rgba(0,0,0,.15);border-radius:.25rem;box-shadow:0 6px 12px rgba(0,0,0,.175)}.selectize-dropdown .optgroup-header{font-size:.875rem;line-height:1.5}.selectize-dropdown .optgroup:first-child:before{display:none}.selectize-dropdown .optgroup:before{content:" ";display:block;height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid rgba(0,0,0,.15);margin-left:-0.75rem;margin-right:-0.75rem}.selectize-dropdown .create{padding-left:.75rem}.selectize-dropdown-content{padding:5px 0}.selectize-dropdown-emptyoptionlabel{text-align:center}.selectize-input{min-height:calc(1.5em + 0.75rem + 2px);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.selectize-input{transition:none}}.selectize-input.dropdown-active{border-radius:.25rem}.selectize-input.dropdown-active::before{display:none}.selectize-input.focus{border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.is-invalid .selectize-input{border-color:#dc3545;box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.is-invalid .selectize-input:focus{border-color:#bd2130;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #eb8c95}.selectize-control.form-control-sm .selectize-input.has-items{min-height:calc(1.5em + 0.5rem + 2px) !important;height:calc(1.5em + 0.5rem + 2px);padding:.25rem .5rem !important;font-size:.875rem;line-height:1.25}.selectize-control.multi .selectize-input.has-items{height:auto;padding-left:calc(0.75rem - 5px);padding-right:calc(0.75rem - 5px)}.selectize-control.multi .selectize-input>div{border-radius:calc(0.25rem - 1px)}.form-control.selectize-control{padding:0;height:auto;border:none;background:none;box-shadow:none;border-radius:0}.input-group .selectize-input{overflow:unset;border-radius:0 .25rem .25rem 0} \ No newline at end of file diff --git a/Resources/Public/Css/Vendor/selectize.css b/Resources/Public/Css/Vendor/selectize.css index 3ec90ad..605f837 100644 --- a/Resources/Public/Css/Vendor/selectize.css +++ b/Resources/Public/Css/Vendor/selectize.css @@ -1,6 +1,7 @@ /** - * selectize.css (v0.12.6) + * selectize.css (v0.13.4) * Copyright (c) 2013–2015 Brian Reavis & contributors + * Copyright (c) 2020 Selectize Team & contributors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this * file except in compliance with the License. You may obtain a copy of the License at: @@ -12,322 +13,12 @@ * governing permissions and limitations under the License. * * @author Brian Reavis + * @author Ris Adams */ -.selectize-control.plugin-drag_drop.multi > .selectize-input > div.ui-sortable-placeholder { - visibility: visible !important; - background: #f2f2f2 !important; - background: rgba(0, 0, 0, 0.06) !important; - border: 0 none !important; - -webkit-box-shadow: inset 0 0 12px 4px #fff; - box-shadow: inset 0 0 12px 4px #fff; -} -.selectize-control.plugin-drag_drop .ui-sortable-placeholder::after { - content: '!'; - visibility: hidden; -} -.selectize-control.plugin-drag_drop .ui-sortable-helper { - -webkit-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); - box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); -} -.selectize-dropdown-header { - position: relative; - padding: 5px 8px; - border-bottom: 1px solid #d0d0d0; - background: #f8f8f8; - -webkit-border-radius: 3px 3px 0 0; - -moz-border-radius: 3px 3px 0 0; - border-radius: 3px 3px 0 0; -} -.selectize-dropdown-header-close { - position: absolute; - right: 8px; - top: 50%; - color: #303030; - opacity: 0.4; - margin-top: -12px; - line-height: 20px; - font-size: 20px !important; -} -.selectize-dropdown-header-close:hover { - color: #000000; -} -.selectize-dropdown.plugin-optgroup_columns .optgroup { - border-right: 1px solid #f2f2f2; - border-top: 0 none; - float: left; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} -.selectize-dropdown.plugin-optgroup_columns .optgroup:last-child { - border-right: 0 none; -} -.selectize-dropdown.plugin-optgroup_columns .optgroup:before { - display: none; -} -.selectize-dropdown.plugin-optgroup_columns .optgroup-header { - border-top: 0 none; -} -.selectize-control.plugin-remove_button [data-value] { - position: relative; - padding-right: 24px !important; -} -.selectize-control.plugin-remove_button [data-value] .remove { - z-index: 1; - /* fixes ie bug (see #392) */ - position: absolute; - top: 0; - right: 0; - bottom: 0; - width: 17px; - text-align: center; - font-weight: bold; - font-size: 12px; - color: inherit; - text-decoration: none; - vertical-align: middle; - display: inline-block; - padding: 2px 0 0 0; - border-left: 1px solid #d0d0d0; - -webkit-border-radius: 0 2px 2px 0; - -moz-border-radius: 0 2px 2px 0; - border-radius: 0 2px 2px 0; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} -.selectize-control.plugin-remove_button [data-value] .remove:hover { - background: rgba(0, 0, 0, 0.05); -} -.selectize-control.plugin-remove_button [data-value].active .remove { - border-left-color: #cacaca; -} -.selectize-control.plugin-remove_button .disabled [data-value] .remove:hover { - background: none; -} -.selectize-control.plugin-remove_button .disabled [data-value] .remove { - border-left-color: #ffffff; -} -.selectize-control.plugin-remove_button .remove-single { - position: absolute; - right: 0; - top: 0; - font-size: 23px; -} -.selectize-control { - position: relative; -} -.selectize-dropdown, -.selectize-input, -.selectize-input input { - color: #303030; - font-family: inherit; - font-size: 13px; - line-height: 18px; - -webkit-font-smoothing: inherit; -} -.selectize-input, -.selectize-control.single .selectize-input.input-active { - background: #fff; - cursor: text; - display: inline-block; -} -.selectize-input { - border: 1px solid #d0d0d0; - padding: 8px 8px; - display: inline-block; - width: 100%; - overflow: hidden; - position: relative; - z-index: 1; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1); - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} -.selectize-control.multi .selectize-input.has-items { - padding: 6px 8px 3px; -} -.selectize-input.full { - background-color: #fff; -} -.selectize-input.disabled, -.selectize-input.disabled * { - cursor: default !important; -} -.selectize-input.focus { - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15); -} -.selectize-input.dropdown-active { - -webkit-border-radius: 3px 3px 0 0; - -moz-border-radius: 3px 3px 0 0; - border-radius: 3px 3px 0 0; -} -.selectize-input > * { - vertical-align: baseline; - display: -moz-inline-stack; - display: inline-block; - zoom: 1; - *display: inline; -} -.selectize-control.multi .selectize-input > div { - cursor: pointer; - margin: 0 3px 3px 0; - padding: 2px 6px; - background: #f2f2f2; - color: #303030; - border: 0 solid #d0d0d0; -} -.selectize-control.multi .selectize-input > div.active { - background: #e8e8e8; - color: #303030; - border: 0 solid #cacaca; -} -.selectize-control.multi .selectize-input.disabled > div, -.selectize-control.multi .selectize-input.disabled > div.active { - color: #7d7d7d; - background: #ffffff; - border: 0 solid #ffffff; -} -.selectize-input > input { - display: inline-block !important; - padding: 0 !important; - min-height: 0 !important; - max-height: none !important; - max-width: 100% !important; - margin: 0 2px 0 0 !important; - text-indent: 0 !important; - border: 0 none !important; - background: none !important; - line-height: inherit !important; - -webkit-user-select: auto !important; - -webkit-box-shadow: none !important; - box-shadow: none !important; -} -.selectize-input > input::-ms-clear { - display: none; -} -.selectize-input > input:focus { - outline: none !important; -} -.selectize-input::after { - content: ' '; - display: block; - clear: left; -} -.selectize-input.dropdown-active::before { - content: ' '; - display: block; - position: absolute; - background: #f0f0f0; - height: 1px; - bottom: 0; - left: 0; - right: 0; -} -.selectize-dropdown { - position: absolute; - z-index: 10; - border: 1px solid #d0d0d0; - background: #fff; - margin: -1px 0 0 0; - border-top: 0 none; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); - -webkit-border-radius: 0 0 3px 3px; - -moz-border-radius: 0 0 3px 3px; - border-radius: 0 0 3px 3px; -} -.selectize-dropdown [data-selectable] { - cursor: pointer; - overflow: hidden; -} -.selectize-dropdown [data-selectable] .highlight { - background: rgba(125, 168, 208, 0.2); - -webkit-border-radius: 1px; - -moz-border-radius: 1px; - border-radius: 1px; -} -.selectize-dropdown .option, -.selectize-dropdown .optgroup-header { - padding: 5px 8px; -} -.selectize-dropdown .option, -.selectize-dropdown [data-disabled], -.selectize-dropdown [data-disabled] [data-selectable].option { - cursor: inherit; - opacity: 0.5; -} -.selectize-dropdown [data-selectable].option { - opacity: 1; -} -.selectize-dropdown .optgroup:first-child .optgroup-header { - border-top: 0 none; -} -.selectize-dropdown .optgroup-header { - color: #303030; - background: #fff; - cursor: default; -} -.selectize-dropdown .active { - background-color: #f5fafd; - color: #495c68; -} -.selectize-dropdown .active.create { - color: #495c68; -} -.selectize-dropdown .create { - color: rgba(48, 48, 48, 0.5); -} -.selectize-dropdown-content { - overflow-y: auto; - overflow-x: hidden; - max-height: 200px; - -webkit-overflow-scrolling: touch; -} -.selectize-control.single .selectize-input, -.selectize-control.single .selectize-input input { - cursor: pointer; -} -.selectize-control.single .selectize-input.input-active, -.selectize-control.single .selectize-input.input-active input { - cursor: text; -} -.selectize-control.single .selectize-input:after { - content: ' '; - display: block; - position: absolute; - top: 50%; - right: 15px; - margin-top: -3px; - width: 0; - height: 0; - border-style: solid; - border-width: 5px 5px 0 5px; - border-color: #808080 transparent transparent transparent; -} -.selectize-control.single .selectize-input.dropdown-active:after { - margin-top: -4px; - border-width: 0 5px 5px 5px; - border-color: transparent transparent #808080 transparent; -} -.selectize-control.rtl.single .selectize-input:after { - left: 15px; - right: auto; -} -.selectize-control.rtl .selectize-input > input { - margin: 0 4px 0 -2px !important; -} -.selectize-control .selectize-input.disabled { - opacity: 0.5; - background-color: #fafafa; -} +.selectize-control.plugin-drag_drop.multi>.selectize-input>div.ui-sortable-placeholder{visibility:visible !important;background:#f2f2f2 !important;background:rgba(0,0,0,.06) !important;border:0 none !important;box-shadow:inset 0 0 12px 4px #fff}.selectize-control.plugin-drag_drop .ui-sortable-placeholder::after{content:"!";visibility:hidden}.selectize-control.plugin-drag_drop .ui-sortable-helper{box-shadow:0 2px 5px rgba(0,0,0,.2)}.selectize-control .dropdown-header{position:relative;padding:10px 8px;border-bottom:1px solid #d0d0d0;background:#f8f8f8;border-radius:3px 3px 0 0}.selectize-control .dropdown-header-close{position:absolute;right:8px;top:50%;color:#303030;opacity:.4;margin-top:-12px;line-height:20px;font-size:20px !important}.selectize-control .dropdown-header-close:hover{color:#000}.selectize-dropdown.plugin-optgroup_columns .selectize-dropdown-content{display:flex}.selectize-dropdown.plugin-optgroup_columns .optgroup{border-right:1px solid #f2f2f2;border-top:0 none;flex-grow:1;flex-basis:0;min-width:0}.selectize-dropdown.plugin-optgroup_columns .optgroup:last-child{border-right:0 none}.selectize-dropdown.plugin-optgroup_columns .optgroup:before{display:none}.selectize-dropdown.plugin-optgroup_columns .optgroup-header{border-top:0 none}.selectize-control.plugin-remove_button .item{display:inline-flex;align-items:center;padding-right:0 !important}.selectize-control.plugin-remove_button .item .remove{color:inherit;text-decoration:none;vertical-align:middle;display:inline-block;padding:2px 6px;border-left:1px solid #d0d0d0;border-radius:0 2px 2px 0;box-sizing:border-box;margin-left:6px}.selectize-control.plugin-remove_button .item .remove:hover{background:rgba(0,0,0,.05)}.selectize-control.plugin-remove_button .item.active .remove{border-left-color:#cacaca}.selectize-control.plugin-remove_button .disabled .item .remove:hover{background:none}.selectize-control.plugin-remove_button .disabled .item .remove{border-left-color:#fff}.selectize-control.plugin-remove_button .remove-single{position:absolute;right:0;top:0;font-size:23px}.selectize-control{position:relative}.selectize-dropdown,.selectize-input,.selectize-input input{color:#303030;font-family:inherit;font-size:13px;line-height:18px;font-smoothing:inherit}.selectize-input,.selectize-control.single .selectize-input.input-active{background:#fff;cursor:text;display:inline-block}.selectize-input{border:1px solid #d0d0d0;padding:8px 8px;display:inline-block;width:100%;overflow:hidden;position:relative;z-index:1;box-sizing:border-box;box-shadow:inset 0 1px 1px rgba(0,0,0,.1);border-radius:3px}.selectize-control.multi .selectize-input.has-items{padding:calc( + 8px - 2px - 0 + ) 8px calc( + 8px - 2px - 3px - + 0 + )}.selectize-input.full{background-color:#fff}.selectize-input.disabled,.selectize-input.disabled *{cursor:default !important}.selectize-input.focus{box-shadow:inset 0 1px 2px rgba(0,0,0,.15)}.selectize-input.dropdown-active{border-radius:3px 3px 0 0}.selectize-input>*{vertical-align:baseline;display:inline-block;zoom:1}.selectize-control.multi .selectize-input>div{cursor:pointer;margin:0 3px 3px 0;padding:2px 6px;background:#f2f2f2;color:#303030;border:0 solid #d0d0d0}.selectize-control.multi .selectize-input>div.active{background:#e8e8e8;color:#303030;border:0 solid #cacaca}.selectize-control.multi .selectize-input.disabled>div,.selectize-control.multi .selectize-input.disabled>div.active{color:#7d7d7d;background:#fff;border:0 solid #fff}.selectize-input>input{display:inline-block !important;padding:0 !important;min-height:0 !important;max-height:none !important;max-width:100% !important;margin:0 !important;text-indent:0 !important;border:0 none !important;background:none !important;line-height:inherit !important;user-select:auto !important;box-shadow:none !important}.selectize-input>input::-ms-clear{display:none}.selectize-input>input:focus{outline:none !important}.selectize-input>input[placeholder]{box-sizing:initial}.selectize-input.has-items>input{margin:0 0px !important}.selectize-input::after{content:" ";display:block;clear:left}.selectize-input.dropdown-active::before{content:" ";display:block;position:absolute;background:#f0f0f0;height:1px;bottom:0;left:0;right:0}.selectize-dropdown{position:absolute;top:100%;left:0;width:100%;z-index:10;border:1px solid #d0d0d0;background:#fff;margin:-1px 0 0 0;border-top:0 none;box-sizing:border-box;box-shadow:0 1px 3px rgba(0,0,0,.1);border-radius:0 0 3px 3px}.selectize-dropdown [data-selectable]{cursor:pointer;overflow:hidden}.selectize-dropdown [data-selectable] .highlight{background:rgba(125,168,208,.2);border-radius:1px}.selectize-dropdown .option,.selectize-dropdown .optgroup-header,.selectize-dropdown .no-results,.selectize-dropdown .create{padding:5px 8px}.selectize-dropdown .option,.selectize-dropdown [data-disabled],.selectize-dropdown [data-disabled] [data-selectable].option{cursor:inherit;opacity:.5}.selectize-dropdown [data-selectable].option{opacity:1;cursor:pointer}.selectize-dropdown .optgroup:first-child .optgroup-header{border-top:0 none}.selectize-dropdown .optgroup-header{color:#303030;background:#fff;cursor:default}.selectize-dropdown .active{background-color:#f5fafd;color:#495c68}.selectize-dropdown .active.create{color:#495c68}.selectize-dropdown .create{color:rgba(48,48,48,.5)}.selectize-dropdown-content{overflow-y:auto;overflow-x:hidden;max-height:200px;overflow-scrolling:touch}.selectize-dropdown-emptyoptionlabel{text-align:center}.selectize-dropdown .spinner{display:inline-block;width:30px;height:30px;margin:5px 8px}.selectize-dropdown .spinner:after{content:" ";display:block;width:24px;height:24px;margin:3px;border-radius:50%;border:5px solid #d0d0d0;border-color:#d0d0d0 transparent #d0d0d0 transparent;animation:lds-dual-ring 1.2s linear infinite}@keyframes lds-dual-ring{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}.selectize-control.single .selectize-input,.selectize-control.single .selectize-input input{cursor:pointer}.selectize-control.single .selectize-input.input-active,.selectize-control.single .selectize-input.input-active input{cursor:text}.selectize-control.single .selectize-input:after{content:" ";display:block;position:absolute;top:50%;right:15px;margin-top:-3px;width:0;height:0;border-style:solid;border-width:5px 5px 0 5px;border-color:gray transparent transparent transparent}.selectize-control.single .selectize-input.dropdown-active:after{margin-top:-4px;border-width:0 5px 5px 5px;border-color:transparent transparent gray transparent}.selectize-control.rtl{text-align:right}.selectize-control.rtl.single .selectize-input:after{left:15px;right:auto}.selectize-control.rtl .selectize-input>input{margin:0 4px 0 -2px !important}.selectize-control .selectize-input.disabled{opacity:.5;background-color:#fafafa} \ No newline at end of file diff --git a/Resources/Public/Js/Vendor/selectize.js b/Resources/Public/Js/Vendor/selectize.js index e064981..6b246bd 100644 --- a/Resources/Public/Js/Vendor/selectize.js +++ b/Resources/Public/Js/Vendor/selectize.js @@ -1,3891 +1,2 @@ -/** - * sifter.js - * Copyright (c) 2013 Brian Reavis & contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this - * file except in compliance with the License. You may obtain a copy of the License at: - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under - * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF - * ANY KIND, either express or implied. See the License for the specific language - * governing permissions and limitations under the License. - * - * @author Brian Reavis - */ - -(function(root, factory) { - if (typeof define === 'function' && define.amd) { - define('sifter', factory); - } else if (typeof exports === 'object') { - module.exports = factory(); - } else { - root.Sifter = factory(); - } -}(this, function() { - - /** - * Textually searches arrays and hashes of objects - * by property (or multiple properties). Designed - * specifically for autocomplete. - * - * @constructor - * @param {array|object} items - * @param {object} items - */ - var Sifter = function(items, settings) { - this.items = items; - this.settings = settings || {diacritics: true}; - }; - - /** - * Splits a search string into an array of individual - * regexps to be used to match results. - * - * @param {string} query - * @returns {array} - */ - Sifter.prototype.tokenize = function(query) { - query = trim(String(query || '').toLowerCase()); - if (!query || !query.length) return []; - - var i, n, regex, letter; - var tokens = []; - var words = query.split(/ +/); - - for (i = 0, n = words.length; i < n; i++) { - regex = escape_regex(words[i]); - if (this.settings.diacritics) { - for (letter in DIACRITICS) { - if (DIACRITICS.hasOwnProperty(letter)) { - regex = regex.replace(new RegExp(letter, 'g'), DIACRITICS[letter]); - } - } - } - tokens.push({ - string : words[i], - regex : new RegExp(regex, 'i') - }); - } - - return tokens; - }; - - /** - * Iterates over arrays and hashes. - * - * ``` - * this.iterator(this.items, function(item, id) { - * // invoked for each item - * }); - * ``` - * - * @param {array|object} object - */ - Sifter.prototype.iterator = function(object, callback) { - var iterator; - if (is_array(object)) { - iterator = Array.prototype.forEach || function(callback) { - for (var i = 0, n = this.length; i < n; i++) { - callback(this[i], i, this); - } - }; - } else { - iterator = function(callback) { - for (var key in this) { - if (this.hasOwnProperty(key)) { - callback(this[key], key, this); - } - } - }; - } - - iterator.apply(object, [callback]); - }; - - /** - * Returns a function to be used to score individual results. - * - * Good matches will have a higher score than poor matches. - * If an item is not a match, 0 will be returned by the function. - * - * @param {object|string} search - * @param {object} options (optional) - * @returns {function} - */ - Sifter.prototype.getScoreFunction = function(search, options) { - var self, fields, tokens, token_count, nesting; - - self = this; - search = self.prepareSearch(search, options); - tokens = search.tokens; - fields = search.options.fields; - token_count = tokens.length; - nesting = search.options.nesting; - - /** - * Calculates how close of a match the - * given value is against a search token. - * - * @param {mixed} value - * @param {object} token - * @return {number} - */ - var scoreValue = function(value, token) { - var score, pos; - - if (!value) return 0; - value = String(value || ''); - pos = value.search(token.regex); - if (pos === -1) return 0; - score = token.string.length / value.length; - if (pos === 0) score += 0.5; - return score; - }; - - /** - * Calculates the score of an object - * against the search query. - * - * @param {object} token - * @param {object} data - * @return {number} - */ - var scoreObject = (function() { - var field_count = fields.length; - if (!field_count) { - return function() { return 0; }; - } - if (field_count === 1) { - return function(token, data) { - return scoreValue(getattr(data, fields[0], nesting), token); - }; - } - return function(token, data) { - for (var i = 0, sum = 0; i < field_count; i++) { - sum += scoreValue(getattr(data, fields[i], nesting), token); - } - return sum / field_count; - }; - })(); - - if (!token_count) { - return function() { return 0; }; - } - if (token_count === 1) { - return function(data) { - return scoreObject(tokens[0], data); - }; - } - - if (search.options.conjunction === 'and') { - return function(data) { - var score; - for (var i = 0, sum = 0; i < token_count; i++) { - score = scoreObject(tokens[i], data); - if (score <= 0) return 0; - sum += score; - } - return sum / token_count; - }; - } else { - return function(data) { - for (var i = 0, sum = 0; i < token_count; i++) { - sum += scoreObject(tokens[i], data); - } - return sum / token_count; - }; - } - }; - - /** - * Returns a function that can be used to compare two - * results, for sorting purposes. If no sorting should - * be performed, `null` will be returned. - * - * @param {string|object} search - * @param {object} options - * @return function(a,b) - */ - Sifter.prototype.getSortFunction = function(search, options) { - var i, n, self, field, fields, fields_count, multiplier, multipliers, get_field, implicit_score, sort; - - self = this; - search = self.prepareSearch(search, options); - sort = (!search.query && options.sort_empty) || options.sort; - - /** - * Fetches the specified sort field value - * from a search result item. - * - * @param {string} name - * @param {object} result - * @return {mixed} - */ - get_field = function(name, result) { - if (name === '$score') return result.score; - return getattr(self.items[result.id], name, options.nesting); - }; - - // parse options - fields = []; - if (sort) { - for (i = 0, n = sort.length; i < n; i++) { - if (search.query || sort[i].field !== '$score') { - fields.push(sort[i]); - } - } - } - - // the "$score" field is implied to be the primary - // sort field, unless it's manually specified - if (search.query) { - implicit_score = true; - for (i = 0, n = fields.length; i < n; i++) { - if (fields[i].field === '$score') { - implicit_score = false; - break; - } - } - if (implicit_score) { - fields.unshift({field: '$score', direction: 'desc'}); - } - } else { - for (i = 0, n = fields.length; i < n; i++) { - if (fields[i].field === '$score') { - fields.splice(i, 1); - break; - } - } - } - - multipliers = []; - for (i = 0, n = fields.length; i < n; i++) { - multipliers.push(fields[i].direction === 'desc' ? -1 : 1); - } - - // build function - fields_count = fields.length; - if (!fields_count) { - return null; - } else if (fields_count === 1) { - field = fields[0].field; - multiplier = multipliers[0]; - return function(a, b) { - return multiplier * cmp( - get_field(field, a), - get_field(field, b) - ); - }; - } else { - return function(a, b) { - var i, result, a_value, b_value, field; - for (i = 0; i < fields_count; i++) { - field = fields[i].field; - result = multipliers[i] * cmp( - get_field(field, a), - get_field(field, b) - ); - if (result) return result; - } - return 0; - }; - } - }; - - /** - * Parses a search query and returns an object - * with tokens and fields ready to be populated - * with results. - * - * @param {string} query - * @param {object} options - * @returns {object} - */ - Sifter.prototype.prepareSearch = function(query, options) { - if (typeof query === 'object') return query; - - options = extend({}, options); - - var option_fields = options.fields; - var option_sort = options.sort; - var option_sort_empty = options.sort_empty; - - if (option_fields && !is_array(option_fields)) options.fields = [option_fields]; - if (option_sort && !is_array(option_sort)) options.sort = [option_sort]; - if (option_sort_empty && !is_array(option_sort_empty)) options.sort_empty = [option_sort_empty]; - - return { - options : options, - query : String(query || '').toLowerCase(), - tokens : this.tokenize(query), - total : 0, - items : [] - }; - }; - - /** - * Searches through all items and returns a sorted array of matches. - * - * The `options` parameter can contain: - * - * - fields {string|array} - * - sort {array} - * - score {function} - * - filter {bool} - * - limit {integer} - * - * Returns an object containing: - * - * - options {object} - * - query {string} - * - tokens {array} - * - total {int} - * - items {array} - * - * @param {string} query - * @param {object} options - * @returns {object} - */ - Sifter.prototype.search = function(query, options) { - var self = this, value, score, search, calculateScore; - var fn_sort; - var fn_score; - - search = this.prepareSearch(query, options); - options = search.options; - query = search.query; - - // generate result scoring function - fn_score = options.score || self.getScoreFunction(search); - - // perform search and sort - if (query.length) { - self.iterator(self.items, function(item, id) { - score = fn_score(item); - if (options.filter === false || score > 0) { - search.items.push({'score': score, 'id': id}); - } - }); - } else { - self.iterator(self.items, function(item, id) { - search.items.push({'score': 1, 'id': id}); - }); - } - - fn_sort = self.getSortFunction(search, options); - if (fn_sort) search.items.sort(fn_sort); - - // apply limits - search.total = search.items.length; - if (typeof options.limit === 'number') { - search.items = search.items.slice(0, options.limit); - } - - return search; - }; - - // utilities - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - var cmp = function(a, b) { - if (typeof a === 'number' && typeof b === 'number') { - return a > b ? 1 : (a < b ? -1 : 0); - } - a = asciifold(String(a || '')); - b = asciifold(String(b || '')); - if (a > b) return 1; - if (b > a) return -1; - return 0; - }; - - var extend = function(a, b) { - var i, n, k, object; - for (i = 1, n = arguments.length; i < n; i++) { - object = arguments[i]; - if (!object) continue; - for (k in object) { - if (object.hasOwnProperty(k)) { - a[k] = object[k]; - } - } - } - return a; - }; - - /** - * A property getter resolving dot-notation - * @param {Object} obj The root object to fetch property on - * @param {String} name The optionally dotted property name to fetch - * @param {Boolean} nesting Handle nesting or not - * @return {Object} The resolved property value - */ - var getattr = function(obj, name, nesting) { - if (!obj || !name) return; - if (!nesting) return obj[name]; - var names = name.split("."); - while(names.length && (obj = obj[names.shift()])); - return obj; - }; - - var trim = function(str) { - return (str + '').replace(/^\s+|\s+$|/g, ''); - }; - - var escape_regex = function(str) { - return (str + '').replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1'); - }; - - var is_array = Array.isArray || (typeof $ !== 'undefined' && $.isArray) || function(object) { - return Object.prototype.toString.call(object) === '[object Array]'; - }; - - var DIACRITICS = { - 'a': '[aḀḁĂăÂâǍǎȺⱥȦȧẠạÄäÀàÁáĀāÃãÅåąĄÃąĄ]', - 'b': '[b␢βΒB฿𐌁ᛒ]', - 'c': '[cĆćĈĉČčĊċC̄c̄ÇçḈḉȻȼƇƈɕᴄCc]', - 'd': '[dĎďḊḋḐḑḌḍḒḓḎḏĐđD̦d̦ƉɖƊɗƋƌᵭᶁᶑȡᴅDdð]', - 'e': '[eÉéÈèÊêḘḙĚěĔĕẼẽḚḛẺẻĖėËëĒēȨȩĘęᶒɆɇȄȅẾếỀềỄễỂểḜḝḖḗḔḕȆȇẸẹỆệⱸᴇEeɘǝƏƐε]', - 'f': '[fƑƒḞḟ]', - 'g': '[gɢ₲ǤǥĜĝĞğĢģƓɠĠġ]', - 'h': '[hĤĥĦħḨḩẖẖḤḥḢḣɦʰǶƕ]', - 'i': '[iÍíÌìĬĭÎîǏǐÏïḮḯĨĩĮįĪīỈỉȈȉȊȋỊịḬḭƗɨɨ̆ᵻᶖİiIıɪIi]', - 'j': '[jȷĴĵɈɉʝɟʲ]', - 'k': '[kƘƙꝀꝁḰḱǨǩḲḳḴḵκϰ₭]', - 'l': '[lŁłĽľĻļĹĺḶḷḸḹḼḽḺḻĿŀȽƚⱠⱡⱢɫɬᶅɭȴʟLl]', - 'n': '[nŃńǸǹŇňÑñṄṅŅņṆṇṊṋṈṉN̈n̈ƝɲȠƞᵰᶇɳȵɴNnŊŋ]', - 'o': '[oØøÖöÓóÒòÔôǑǒŐőŎŏȮȯỌọƟɵƠơỎỏŌōÕõǪǫȌȍՕօ]', - 'p': '[pṔṕṖṗⱣᵽƤƥᵱ]', - 'q': '[qꝖꝗʠɊɋꝘꝙq̃]', - 'r': '[rŔŕɌɍŘřŖŗṘṙȐȑȒȓṚṛⱤɽ]', - 's': '[sŚśṠṡṢṣꞨꞩŜŝŠšŞşȘșS̈s̈]', - 't': '[tŤťṪṫŢţṬṭƮʈȚțṰṱṮṯƬƭ]', - 'u': '[uŬŭɄʉỤụÜüÚúÙùÛûǓǔŰűŬŭƯưỦủŪūŨũŲųȔȕ∪]', - 'v': '[vṼṽṾṿƲʋꝞꝟⱱʋ]', - 'w': '[wẂẃẀẁŴŵẄẅẆẇẈẉ]', - 'x': '[xẌẍẊẋχ]', - 'y': '[yÝýỲỳŶŷŸÿỸỹẎẏỴỵɎɏƳƴ]', - 'z': '[zŹźẐẑŽžŻżẒẓẔẕƵƶ]' - }; - - var asciifold = (function() { - var i, n, k, chunk; - var foreignletters = ''; - var lookup = {}; - for (k in DIACRITICS) { - if (DIACRITICS.hasOwnProperty(k)) { - chunk = DIACRITICS[k].substring(2, DIACRITICS[k].length - 1); - foreignletters += chunk; - for (i = 0, n = chunk.length; i < n; i++) { - lookup[chunk.charAt(i)] = k; - } - } - } - var regexp = new RegExp('[' + foreignletters + ']', 'g'); - return function(str) { - return str.replace(regexp, function(foreignletter) { - return lookup[foreignletter]; - }).toLowerCase(); - }; - })(); - - - // export - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - return Sifter; -})); - - - -/** - * microplugin.js - * Copyright (c) 2013 Brian Reavis & contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this - * file except in compliance with the License. You may obtain a copy of the License at: - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under - * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF - * ANY KIND, either express or implied. See the License for the specific language - * governing permissions and limitations under the License. - * - * @author Brian Reavis - */ - -(function(root, factory) { - if (typeof define === 'function' && define.amd) { - define('microplugin', factory); - } else if (typeof exports === 'object') { - module.exports = factory(); - } else { - root.MicroPlugin = factory(); - } -}(this, function() { - var MicroPlugin = {}; - - MicroPlugin.mixin = function(Interface) { - Interface.plugins = {}; - - /** - * Initializes the listed plugins (with options). - * Acceptable formats: - * - * List (without options): - * ['a', 'b', 'c'] - * - * List (with options): - * [{'name': 'a', options: {}}, {'name': 'b', options: {}}] - * - * Hash (with options): - * {'a': { ... }, 'b': { ... }, 'c': { ... }} - * - * @param {mixed} plugins - */ - Interface.prototype.initializePlugins = function(plugins) { - var i, n, key; - var self = this; - var queue = []; - - self.plugins = { - names : [], - settings : {}, - requested : {}, - loaded : {} - }; - - if (utils.isArray(plugins)) { - for (i = 0, n = plugins.length; i < n; i++) { - if (typeof plugins[i] === 'string') { - queue.push(plugins[i]); - } else { - self.plugins.settings[plugins[i].name] = plugins[i].options; - queue.push(plugins[i].name); - } - } - } else if (plugins) { - for (key in plugins) { - if (plugins.hasOwnProperty(key)) { - self.plugins.settings[key] = plugins[key]; - queue.push(key); - } - } - } - - while (queue.length) { - self.require(queue.shift()); - } - }; - - Interface.prototype.loadPlugin = function(name) { - var self = this; - var plugins = self.plugins; - var plugin = Interface.plugins[name]; - - if (!Interface.plugins.hasOwnProperty(name)) { - throw new Error('Unable to find "' + name + '" plugin'); - } - - plugins.requested[name] = true; - plugins.loaded[name] = plugin.fn.apply(self, [self.plugins.settings[name] || {}]); - plugins.names.push(name); - }; - - /** - * Initializes a plugin. - * - * @param {string} name - */ - Interface.prototype.require = function(name) { - var self = this; - var plugins = self.plugins; - - if (!self.plugins.loaded.hasOwnProperty(name)) { - if (plugins.requested[name]) { - throw new Error('Plugin has circular dependency ("' + name + '")'); - } - self.loadPlugin(name); - } - - return plugins.loaded[name]; - }; - - /** - * Registers a plugin. - * - * @param {string} name - * @param {function} fn - */ - Interface.define = function(name, fn) { - Interface.plugins[name] = { - 'name' : name, - 'fn' : fn - }; - }; - }; - - var utils = { - isArray: Array.isArray || function(vArg) { - return Object.prototype.toString.call(vArg) === '[object Array]'; - } - }; - - return MicroPlugin; -})); - -/** - * selectize.js (v0.12.6) - * Copyright (c) 2013–2015 Brian Reavis & contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this - * file except in compliance with the License. You may obtain a copy of the License at: - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under - * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF - * ANY KIND, either express or implied. See the License for the specific language - * governing permissions and limitations under the License. - * - * @author Brian Reavis - */ - -/*jshint curly:false */ -/*jshint browser:true */ - -(function(root, factory) { - if (typeof define === 'function' && define.amd) { - define('selectize', ['jquery','sifter','microplugin'], factory); - } else if (typeof exports === 'object') { - module.exports = factory(require('jquery'), require('sifter'), require('microplugin')); - } else { - root.Selectize = factory(root.jQuery, root.Sifter, root.MicroPlugin); - } -}(this, function($, Sifter, MicroPlugin) { - 'use strict'; - - var highlight = function($element, pattern) { - if (typeof pattern === 'string' && !pattern.length) return; - var regex = (typeof pattern === 'string') ? new RegExp(pattern, 'i') : pattern; - - var highlight = function(node) { - var skip = 0; - // Wrap matching part of text node with highlighting , e.g. - // Soccer -> Soccer for regex = /soc/i - if (node.nodeType === 3) { - var pos = node.data.search(regex); - if (pos >= 0 && node.data.length > 0) { - var match = node.data.match(regex); - var spannode = document.createElement('span'); - spannode.className = 'highlight'; - var middlebit = node.splitText(pos); - var endbit = middlebit.splitText(match[0].length); - var middleclone = middlebit.cloneNode(true); - spannode.appendChild(middleclone); - middlebit.parentNode.replaceChild(spannode, middlebit); - skip = 1; - } - } - // Recurse element node, looking for child text nodes to highlight, unless element - // is childless, "; - - $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class); - $pageRenderer->addHeaderData($googleJobs); - } - // Pagetitle Templating $title = $this->settings["pageTitle"]; if ($title !== "") @@ -371,6 +280,8 @@ public function showAction(Posting $posting = null): ResponseInterface $titleProvider->setTitle($title); + $this->addGoogleJobsDataToPage($posting); + // SignalSlotDispatcher BeforePostingShowAssign $changedPosting = $this->signalSlotDispatcher->dispatch(__CLASS__, "BeforePostingShowAssign", ["posting" => $posting]); if ($changedPosting["posting"] instanceof Posting) @@ -383,6 +294,114 @@ public function showAction(Posting $posting = null): ResponseInterface return $this->htmlResponse(); } + /** + * This function generates the Google Jobs structured on page data. + * This can be overriden if any field customizations are done. + */ + protected function addGoogleJobsDataToPage(Posting $posting): void + { + /** @var ExtensionConfiguration $extconf */ + $extconf = GeneralUtility::makeInstance(ExtensionConfiguration::class); + + $companyName = $extconf->get('jobapplications', 'companyName'); + + if (empty($companyName) || $this->settings['enableGoogleJobs'] !== "1") + { + return; + } + + $hiringOrganization = [ + "@type" => "Organization", + "name" => $companyName + ]; + + $logo = $extconf->get('jobapplications', 'logo'); + if (!empty($logo)) + { + $hiringOrganization["logo"] = $logo; + } + + $employmentTypes = []; + + foreach ($posting->getDeserializedEmploymentTypes() as $employmentType) + { + switch ($employmentType) + { + case "fulltime": + $employmentTypes[] = "FULL_TIME"; + break; + case "parttime": + $employmentTypes[] = "PART_TIME"; + break; + case "contractor": + $employmentTypes[] = "CONTRACTOR"; + break; + case "temporary": + $employmentTypes[] = "TEMPORARY"; + break; + case "intern": + $employmentTypes[] = "INTERN"; + break; + case "volunteer": + $employmentTypes[] = "VOLUNTEER"; + break; + case "perdiem": + $employmentTypes[] = "PER_DIEM"; + break; + case "other": + $employmentTypes[] = "OTHER"; + break; + default: + $employmentTypes = []; + } + } + + $googleJobsJSON = [ + "@context" => "http://schema.org", + "@type" => "JobPosting", + "datePosted" => $posting->getDatePosted()->format("c"), + "description" => $posting->getCompanyDescription()."
".$posting->getJobDescription()."
" + .$posting->getRoleDescription()."
".$posting->getSkillRequirements() + ."
".$posting->getBenefits(), + "jobLocation" => [ + "@type" => "Place", + "address" => [ + "streetAddress" => $posting->getLocation()->getAddressStreetAndNumber(), + "addressLocality" => $posting->getLocation()->getAddressCity(), + "postalCode" => $posting->getLocation()->getAddressPostCode(), + "addressCountry" => $posting->getLocation()->getAddressCountry() + ] + ], + "title" => $posting->getTitle(), + "employmentType" => $employmentTypes + ]; + + $googleJobsJSON["hiringOrganization"] = $hiringOrganization; + + if (!empty($posting->getBaseSalary())) + { + $currency = $logo = $extconf->get('jobapplications', 'currency') ?: "EUR"; + $googleJobsJSON["baseSalary"] = [ + "@type" => "MonetaryAmount", + "currency" => $currency, + "value" => [ + "@type" => "QuantitativeValue", + "value" => preg_replace('/\D/', '', $posting->getBaseSalary()), + "unitText" => "YEAR" + ] + ]; + } + + if ($posting->getEndtime() instanceof \DateTime) + { + $googleJobsJSON["validThrough"] = $posting->getEndtime()->format("c"); + } + + $googleJobs = ""; + + $this->pageRenderer->addHeaderData($googleJobs); + } + public function injectPostingRepository(PostingRepository $postingRepository): void { $this->postingRepository = $postingRepository; From d5c977ad2c3dc587dc470ff57ce81080f499150f Mon Sep 17 00:00:00 2001 From: Benjamin Jasper Date: Thu, 10 Mar 2022 16:08:30 +0100 Subject: [PATCH 42/61] feat: replaced signal slots in favor of events --- Classes/Controller/ApplicationController.php | 34 +++-------- Classes/Controller/PostingController.php | 64 ++++---------------- Classes/Event/BeforeApplicationPersisted.php | 35 +++++++++++ Classes/Event/DisplayPostingEvent.php | 33 ++++++++++ Documentation/Developer/Index.rst | 8 +-- 5 files changed, 91 insertions(+), 83 deletions(-) create mode 100644 Classes/Event/BeforeApplicationPersisted.php create mode 100644 Classes/Event/DisplayPostingEvent.php diff --git a/Classes/Controller/ApplicationController.php b/Classes/Controller/ApplicationController.php index 44781ac..490ba66 100644 --- a/Classes/Controller/ApplicationController.php +++ b/Classes/Controller/ApplicationController.php @@ -32,6 +32,7 @@ use ITX\Jobapplications\Domain\Repository\ApplicationRepository; use ITX\Jobapplications\Domain\Repository\PostingRepository; use ITX\Jobapplications\Domain\Repository\StatusRepository; + use ITX\Jobapplications\Event\BeforeApplicationPersisted; use ITX\Jobapplications\PageTitle\JobsPageTitleProvider; use ITX\Jobapplications\Service\ApplicationFileService; use ITX\Jobapplications\Utility\Mail\MailInterface; @@ -42,7 +43,6 @@ use Symfony\Component\Mime\Address; use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; use TYPO3\CMS\Core\Database\ConnectionPool; - use TYPO3\CMS\Core\Localization\Exception\FileNotFoundException; use TYPO3\CMS\Core\Log\LogManager; use TYPO3\CMS\Core\Mail\FluidEmail; use TYPO3\CMS\Core\Mail\Mailer; @@ -55,7 +55,6 @@ use TYPO3\CMS\Core\Resource\Exception\InvalidFileNameException; use TYPO3\CMS\Core\Resource\File; use TYPO3\CMS\Core\Resource\FileInterface; - use TYPO3\CMS\Core\Resource\ResourceStorage; use TYPO3\CMS\Core\Resource\ResourceStorageInterface; use TYPO3\CMS\Core\Resource\StorageRepository; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -66,9 +65,6 @@ use TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException; use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager; use TYPO3\CMS\Extbase\Property\TypeConverter\DateTimeConverter; - use TYPO3\CMS\Extbase\SignalSlot\Dispatcher; - use TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotException; - use TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotReturnException; use TYPO3\CMS\Extbase\Utility\LocalizationUtility; /** @@ -100,12 +96,7 @@ class ApplicationController extends ActionController * @var \ITX\Jobapplications\Service\ApplicationFileService */ protected $applicationFileService; - /** - * signalSlotDispatcher - * - * @var \TYPO3\CMS\Extbase\SignalSlot\Dispatcher - */ - protected $signalSlotDispatcher; + /** * @var \TYPO3\CMS\Core\Log\Logger */ @@ -323,8 +314,6 @@ private function isStringArray(?array $array): bool * @throws InvalidFileNameException * @throws StopActionException * @throws IllegalObjectTypeException - * @throws InvalidSlotException - * @throws InvalidSlotReturnException */ public function createAction(Application $newApplication, Posting $posting = null): void { @@ -389,7 +378,7 @@ public function createAction(Application $newApplication, Posting $posting = nul $newApplication->setPosting($posting); } - /* @var \ITX\Jobapplications\Domain\Model\Status $firstStatus */ + /* @var Status $firstStatus */ $firstStatus = $this->statusRepository->findNewStatus(); if ($firstStatus instanceof Status) @@ -397,14 +386,10 @@ public function createAction(Application $newApplication, Posting $posting = nul $newApplication->setStatus($firstStatus); } - // SignalSlotDispatcher BeforePostingAssign - $signalArguments = ["application" => $newApplication]; - $signalArguments = $this->signalSlotDispatcher->dispatch(__CLASS__, "BeforeApplicationAdd", $signalArguments); - - if ($signalArguments["application"] instanceof Application) - { - $newApplication = $signalArguments['application']; - } + // Event BeforeApplicationPersisted + /** @var BeforeApplicationPersisted $event */ + $event = $this->eventDispatcher->dispatch(new BeforeApplicationPersisted($newApplication)); + $newApplication = $event->getApplication(); $this->applicationRepository->add($newApplication); $this->persistenceManager->persistAll(); @@ -721,11 +706,6 @@ public function injectApplicationFileService(ApplicationFileService $application $this->applicationFileService = $applicationFileService; } - public function injectSignalSlotDispatcher(Dispatcher $signalSlotDispatcher): void - { - $this->signalSlotDispatcher = $signalSlotDispatcher; - } - public function injectPostingRepository(PostingRepository $postingRepository): void { $this->postingRepository = $postingRepository; diff --git a/Classes/Controller/PostingController.php b/Classes/Controller/PostingController.php index 00dd00e..6b16fe1 100644 --- a/Classes/Controller/PostingController.php +++ b/Classes/Controller/PostingController.php @@ -6,11 +6,13 @@ use ITX\Jobapplications\Domain\Model\Posting; use ITX\Jobapplications\Domain\Repository\LocationRepository; use ITX\Jobapplications\Domain\Repository\PostingRepository; + use ITX\Jobapplications\Event\DisplayPostingEvent; use ITX\Jobapplications\PageTitle\JobsPageTitleProvider; use Psr\Http\Message\ResponseInterface; use TYPO3\CMS\Core\Cache\CacheManager; use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface; use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; + use TYPO3\CMS\Core\Error\Http\PageNotFoundException; use TYPO3\CMS\Core\Http\ImmediateResponseException; use TYPO3\CMS\Core\Page\PageRenderer; use TYPO3\CMS\Core\Pagination\SimplePagination; @@ -23,9 +25,6 @@ use TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException; use TYPO3\CMS\Extbase\Persistence\QueryInterface; use TYPO3\CMS\Extbase\Reflection\Exception\UnknownClassException; - use TYPO3\CMS\Extbase\SignalSlot\Dispatcher; - use TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotException; - use TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotReturnException; use TYPO3\CMS\Frontend\Controller\ErrorController; /*************************************************************** @@ -56,28 +55,8 @@ */ class PostingController extends ActionController { - - /** - * postingRepository - * - * @var \ITX\Jobapplications\Domain\Repository\PostingRepository - */ - protected $postingRepository = null; - - /** - * locationRepository - * - * @var \ITX\Jobapplications\Domain\Repository\LocationRepository - */ - protected $locationRepository = null; - - /** - * signalSlotDispatcher - * - * @var \TYPO3\CMS\Extbase\SignalSlot\Dispatcher - */ - protected $signalSlotDispatcher; - + protected PostingRepository $postingRepository; + protected LocationRepository $locationRepository; protected PageRenderer $pageRenderer; public function __construct(PageRenderer $pageRenderer) @@ -118,8 +97,6 @@ public function initializeView(ViewInterface $view) /** * @throws InvalidQueryException - * @throws InvalidSlotException - * @throws InvalidSlotReturnException * @throws UnknownClassException * @throws NoSuchArgumentException */ @@ -159,13 +136,6 @@ public function listAction(Constraint $constraint = null): ResponseInterface // Make the actual repository call $postings = $this->postingRepository->findByFilter($categories, $repositoryConfiguration, $constraint, $orderBy, $order); - // SignalSlotDispatcher BeforePostingAssign - $changedPostings = $this->signalSlotDispatcher->dispatch(__CLASS__, "BeforePostingAssign", ["postings" => $postings]); - if (count($changedPostings["postings"]) > 0) - { - $postings = $changedPostings['postings']; - } - // Determines whether user tried to filter $isFiltering = false; @@ -245,17 +215,14 @@ public function getFilterOptions(array $categories): array } /** - * @param \ITX\Jobapplications\Domain\Model\Posting|null $posting + * @param Posting|null $posting * + * @return ResponseInterface * @throws ImmediateResponseException + * @throws PageNotFoundException * @throws \JsonException - * @throws \TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationExtensionNotConfiguredException - * @throws \TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationPathDoesNotExistException - * @throws \TYPO3\CMS\Core\Error\Http\PageNotFoundException - * @throws InvalidSlotException - * @throws InvalidSlotReturnException */ - public function showAction(Posting $posting = null): ResponseInterface + public function showAction(?Posting $posting = null): ResponseInterface { if ($posting === null) { @@ -282,12 +249,10 @@ public function showAction(Posting $posting = null): ResponseInterface $this->addGoogleJobsDataToPage($posting); - // SignalSlotDispatcher BeforePostingShowAssign - $changedPosting = $this->signalSlotDispatcher->dispatch(__CLASS__, "BeforePostingShowAssign", ["posting" => $posting]); - if ($changedPosting["posting"] instanceof Posting) - { - $posting = $changedPosting['posting']; - } + // Event DisplayPostingEvent + /** @var DisplayPostingEvent $event */ + $event = $this->eventDispatcher->dispatch(new DisplayPostingEvent($posting)); + $posting = $event->getPosting(); $this->view->assign('posting', $posting); @@ -411,9 +376,4 @@ public function injectLocationRepository(LocationRepository $locationRepository) { $this->locationRepository = $locationRepository; } - - public function injectSignalSlotDispatcher(Dispatcher $signalSlotDispatcher): void - { - $this->signalSlotDispatcher = $signalSlotDispatcher; - } } diff --git a/Classes/Event/BeforeApplicationPersisted.php b/Classes/Event/BeforeApplicationPersisted.php new file mode 100644 index 0000000..687e707 --- /dev/null +++ b/Classes/Event/BeforeApplicationPersisted.php @@ -0,0 +1,35 @@ +application = $application; + } + + /** + * @return Application + */ + public function getApplication(): Application + { + return $this->application; + } + + /** + * @param Application $application + */ + public function setApplication(Application $application): void + { + $this->application = $application; + } + } \ No newline at end of file diff --git a/Classes/Event/DisplayPostingEvent.php b/Classes/Event/DisplayPostingEvent.php new file mode 100644 index 0000000..0778188 --- /dev/null +++ b/Classes/Event/DisplayPostingEvent.php @@ -0,0 +1,33 @@ +posting = $posting; + } + + /** + * @return Posting + */ + public function getPosting(): Posting + { + return $this->posting; + } + + /** + * @param Posting $posting + */ + public function setPosting(Posting $posting): void + { + $this->posting = $posting; + } + } \ No newline at end of file diff --git a/Documentation/Developer/Index.rst b/Documentation/Developer/Index.rst index 9cbbbe7..43b7466 100644 --- a/Documentation/Developer/Index.rst +++ b/Documentation/Developer/Index.rst @@ -9,11 +9,11 @@ For Developers .. _developer-signal-slots: -Signal Slots -============ -There are Signal Slots implemented which mainly happen before postings or applications are being assigned to the view. +Events +====== +There are a few events provided which mainly happen before postings or applications are being assigned to the view. -You can simply find them by looking through the code. If you think you need more slots than are already provided feel free to +You can simply find them by taking a look into ITX\Jobapplications\Event. If you think you need more events than are already provided feel free to contact us via GitHub or :ref:`E-Mail `. Custom Filters From a0be1d6279340b19787c2751ad92236bbb466663 Mon Sep 17 00:00:00 2001 From: Benjamin Jasper Date: Fri, 11 Mar 2022 08:33:20 +0100 Subject: [PATCH 43/61] fix: removed unneeded compatibility --- .../Page/Header/MetaViewHelper.php | 38 ++++++++----------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/Classes/ViewHelpers/Page/Header/MetaViewHelper.php b/Classes/ViewHelpers/Page/Header/MetaViewHelper.php index fa7aaab..0c37437 100644 --- a/Classes/ViewHelpers/Page/Header/MetaViewHelper.php +++ b/Classes/ViewHelpers/Page/Header/MetaViewHelper.php @@ -58,34 +58,28 @@ public function render() if (!empty($content)) { $pageRenderer = static::getPageRenderer(); - if (!method_exists($pageRenderer, 'setMetaTag')) + + $properties = []; + $type = 'name'; + $name = $this->tag->getAttribute('name'); + if (!empty($this->tag->getAttribute('property'))) { - $pageRenderer->addMetaTag($this->renderTag($this->tagName, null, ['content' => $content])); + $type = 'property'; + $name = $this->tag->getAttribute('property'); } - else + elseif (!empty($this->tag->getAttribute('http-equiv'))) { - $properties = []; - $type = 'name'; - $name = $this->tag->getAttribute('name'); - if (!empty($this->tag->getAttribute('property'))) - { - $type = 'property'; - $name = $this->tag->getAttribute('property'); - } - elseif (!empty($this->tag->getAttribute('http-equiv'))) - { - $type = 'http-equiv'; - $name = $this->tag->getAttribute('http-equiv'); - } - foreach (['http-equiv', 'property', 'scheme', 'lang', 'dir'] as $propertyName) + $type = 'http-equiv'; + $name = $this->tag->getAttribute('http-equiv'); + } + foreach (['http-equiv', 'property', 'scheme', 'lang', 'dir'] as $propertyName) + { + if (!empty($this->tag->getAttribute($propertyName))) { - if (!empty($this->tag->getAttribute($propertyName))) - { - $properties[$propertyName] = $this->tag->getAttribute($propertyName); - } + $properties[$propertyName] = $this->tag->getAttribute($propertyName); } - $pageRenderer->setMetaTag($type, $name, $content, $properties); } + $pageRenderer->setMetaTag($type, $name, $content, $properties); } } } From 332bf38d5dc5df0b6dd963b564dd31466e8fb587 Mon Sep 17 00:00:00 2001 From: Benjamin Jasper Date: Fri, 11 Mar 2022 08:33:39 +0100 Subject: [PATCH 44/61] fix: deleted tests --- .../Controller/ApplicationControllerTest.php | 53 -- .../Unit/Controller/ContactControllerTest.php | 143 ----- .../Controller/LocationControllerTest.php | 143 ----- .../Unit/Controller/PostingControllerTest.php | 75 --- Tests/Unit/Domain/Model/ApplicationTest.php | 488 ------------------ Tests/Unit/Domain/Model/ContactTest.php | 130 ----- Tests/Unit/Domain/Model/LocationTest.php | 130 ----- Tests/Unit/Domain/Model/PostingTest.php | 488 ------------------ 8 files changed, 1650 deletions(-) delete mode 100644 Tests/Unit/Controller/ApplicationControllerTest.php delete mode 100644 Tests/Unit/Controller/ContactControllerTest.php delete mode 100644 Tests/Unit/Controller/LocationControllerTest.php delete mode 100644 Tests/Unit/Controller/PostingControllerTest.php delete mode 100644 Tests/Unit/Domain/Model/ApplicationTest.php delete mode 100644 Tests/Unit/Domain/Model/ContactTest.php delete mode 100644 Tests/Unit/Domain/Model/LocationTest.php delete mode 100644 Tests/Unit/Domain/Model/PostingTest.php diff --git a/Tests/Unit/Controller/ApplicationControllerTest.php b/Tests/Unit/Controller/ApplicationControllerTest.php deleted file mode 100644 index c4edbe5..0000000 --- a/Tests/Unit/Controller/ApplicationControllerTest.php +++ /dev/null @@ -1,53 +0,0 @@ -getMockBuilder(ApplicationRepository::class) - ->setMethods(['add']) - ->disableOriginalConstructor() - ->getMock(); - - $applicationRepository->expects(self::once())->method('add')->with($application); - $this->inject($this->subject, 'applicationRepository', $applicationRepository); - - $this->subject->createAction($application); - } - - protected function setUp() - { - parent::setUp(); - $this->subject = $this->getMockBuilder(ApplicationController::class) - ->setMethods(['redirect', 'forward', 'addFlashMessage']) - ->disableOriginalConstructor() - ->getMock(); - } - - protected function tearDown() - { - parent::tearDown(); - } - } diff --git a/Tests/Unit/Controller/ContactControllerTest.php b/Tests/Unit/Controller/ContactControllerTest.php deleted file mode 100644 index 22d1d30..0000000 --- a/Tests/Unit/Controller/ContactControllerTest.php +++ /dev/null @@ -1,143 +0,0 @@ -getMockBuilder(ObjectStorage::class) - ->disableOriginalConstructor() - ->getMock(); - - $contactRepository = $this->getMockBuilder(ContactRepository::class) - ->setMethods(['findAll']) - ->disableOriginalConstructor() - ->getMock(); - $contactRepository->expects(self::once())->method('findAll')->will(self::returnValue($allContacts)); - $this->inject($this->subject, 'contactRepository', $contactRepository); - - $view = $this->getMockBuilder(ViewInterface::class)->getMock(); - $view->expects(self::once())->method('assign')->with('contacts', $allContacts); - $this->inject($this->subject, 'view', $view); - - $this->subject->listAction(); - } - - /** - * @test - */ - public function showActionAssignsTheGivenContactToView() - { - $contact = new Contact(); - - $view = $this->getMockBuilder(ViewInterface::class)->getMock(); - $this->inject($this->subject, 'view', $view); - $view->expects(self::once())->method('assign')->with('contact', $contact); - - $this->subject->showAction($contact); - } - - /** - * @test - */ - public function createActionAddsTheGivenContactToContactRepository() - { - $contact = new Contact(); - - $contactRepository = $this->getMockBuilder(ContactRepository::class) - ->setMethods(['add']) - ->disableOriginalConstructor() - ->getMock(); - - $contactRepository->expects(self::once())->method('add')->with($contact); - $this->inject($this->subject, 'contactRepository', $contactRepository); - - $this->subject->createAction($contact); - } - - /** - * @test - */ - public function editActionAssignsTheGivenContactToView() - { - $contact = new Contact(); - - $view = $this->getMockBuilder(ViewInterface::class)->getMock(); - $this->inject($this->subject, 'view', $view); - $view->expects(self::once())->method('assign')->with('contact', $contact); - - $this->subject->editAction($contact); - } - - /** - * @test - */ - public function updateActionUpdatesTheGivenContactInContactRepository() - { - $contact = new Contact(); - - $contactRepository = $this->getMockBuilder(ContactRepository::class) - ->setMethods(['update']) - ->disableOriginalConstructor() - ->getMock(); - - $contactRepository->expects(self::once())->method('update')->with($contact); - $this->inject($this->subject, 'contactRepository', $contactRepository); - - $this->subject->updateAction($contact); - } - - /** - * @test - */ - public function deleteActionRemovesTheGivenContactFromContactRepository() - { - $contact = new Contact(); - - $contactRepository = $this->getMockBuilder(ContactRepository::class) - ->setMethods(['remove']) - ->disableOriginalConstructor() - ->getMock(); - - $contactRepository->expects(self::once())->method('remove')->with($contact); - $this->inject($this->subject, 'contactRepository', $contactRepository); - - $this->subject->deleteAction($contact); - } - - protected function setUp() - { - parent::setUp(); - $this->subject = $this->getMockBuilder(ContactController::class) - ->setMethods(['redirect', 'forward', 'addFlashMessage']) - ->disableOriginalConstructor() - ->getMock(); - } - - protected function tearDown() - { - parent::tearDown(); - } - } diff --git a/Tests/Unit/Controller/LocationControllerTest.php b/Tests/Unit/Controller/LocationControllerTest.php deleted file mode 100644 index 34edf37..0000000 --- a/Tests/Unit/Controller/LocationControllerTest.php +++ /dev/null @@ -1,143 +0,0 @@ -getMockBuilder(ObjectStorage::class) - ->disableOriginalConstructor() - ->getMock(); - - $locationRepository = $this->getMockBuilder(LocationRepository::class) - ->setMethods(['findAll']) - ->disableOriginalConstructor() - ->getMock(); - $locationRepository->expects(self::once())->method('findAll')->will(self::returnValue($allLocations)); - $this->inject($this->subject, 'locationRepository', $locationRepository); - - $view = $this->getMockBuilder(ViewInterface::class)->getMock(); - $view->expects(self::once())->method('assign')->with('locations', $allLocations); - $this->inject($this->subject, 'view', $view); - - $this->subject->listAction(); - } - - /** - * @test - */ - public function showActionAssignsTheGivenLocationToView() - { - $location = new Location(); - - $view = $this->getMockBuilder(ViewInterface::class)->getMock(); - $this->inject($this->subject, 'view', $view); - $view->expects(self::once())->method('assign')->with('location', $location); - - $this->subject->showAction($location); - } - - /** - * @test - */ - public function createActionAddsTheGivenLocationToLocationRepository() - { - $location = new Location(); - - $locationRepository = $this->getMockBuilder(LocationRepository::class) - ->setMethods(['add']) - ->disableOriginalConstructor() - ->getMock(); - - $locationRepository->expects(self::once())->method('add')->with($location); - $this->inject($this->subject, 'locationRepository', $locationRepository); - - $this->subject->createAction($location); - } - - /** - * @test - */ - public function editActionAssignsTheGivenLocationToView() - { - $location = new Location(); - - $view = $this->getMockBuilder(ViewInterface::class)->getMock(); - $this->inject($this->subject, 'view', $view); - $view->expects(self::once())->method('assign')->with('location', $location); - - $this->subject->editAction($location); - } - - /** - * @test - */ - public function updateActionUpdatesTheGivenLocationInLocationRepository() - { - $location = new Location(); - - $locationRepository = $this->getMockBuilder(LocationRepository::class) - ->setMethods(['update']) - ->disableOriginalConstructor() - ->getMock(); - - $locationRepository->expects(self::once())->method('update')->with($location); - $this->inject($this->subject, 'locationRepository', $locationRepository); - - $this->subject->updateAction($location); - } - - /** - * @test - */ - public function deleteActionRemovesTheGivenLocationFromLocationRepository() - { - $location = new Location(); - - $locationRepository = $this->getMockBuilder(LocationRepository::class) - ->setMethods(['remove']) - ->disableOriginalConstructor() - ->getMock(); - - $locationRepository->expects(self::once())->method('remove')->with($location); - $this->inject($this->subject, 'locationRepository', $locationRepository); - - $this->subject->deleteAction($location); - } - - protected function setUp() - { - parent::setUp(); - $this->subject = $this->getMockBuilder(LocationController::class) - ->setMethods(['redirect', 'forward', 'addFlashMessage']) - ->disableOriginalConstructor() - ->getMock(); - } - - protected function tearDown() - { - parent::tearDown(); - } - } diff --git a/Tests/Unit/Controller/PostingControllerTest.php b/Tests/Unit/Controller/PostingControllerTest.php deleted file mode 100644 index 9f3f4d2..0000000 --- a/Tests/Unit/Controller/PostingControllerTest.php +++ /dev/null @@ -1,75 +0,0 @@ -getMockBuilder(ObjectStorage::class) - ->disableOriginalConstructor() - ->getMock(); - - $postingRepository = $this->getMockBuilder(PostingRepository::class) - ->setMethods(['findAll']) - ->disableOriginalConstructor() - ->getMock(); - $postingRepository->expects(self::once())->method('findAll')->will(self::returnValue($allPostings)); - $this->inject($this->subject, 'postingRepository', $postingRepository); - - $view = $this->getMockBuilder(ViewInterface::class)->getMock(); - $view->expects(self::once())->method('assign')->with('postings', $allPostings); - $this->inject($this->subject, 'view', $view); - - $this->subject->listAction(); - } - - /** - * @test - */ - public function showActionAssignsTheGivenPostingToView() - { - $posting = new Posting(); - - $view = $this->getMockBuilder(ViewInterface::class)->getMock(); - $this->inject($this->subject, 'view', $view); - $view->expects(self::once())->method('assign')->with('posting', $posting); - - $this->subject->showAction($posting); - } - - protected function setUp() - { - parent::setUp(); - $this->subject = $this->getMockBuilder(PostingController::class) - ->setMethods(['redirect', 'forward', 'addFlashMessage']) - ->disableOriginalConstructor() - ->getMock(); - } - - protected function tearDown() - { - parent::tearDown(); - } - } diff --git a/Tests/Unit/Domain/Model/ApplicationTest.php b/Tests/Unit/Domain/Model/ApplicationTest.php deleted file mode 100644 index a5f6012..0000000 --- a/Tests/Unit/Domain/Model/ApplicationTest.php +++ /dev/null @@ -1,488 +0,0 @@ -subject->getSalutation() - ); - } - - /** - * @test - */ - public function setSalutationForIntSetsSalutation() - { - $this->subject->setSalutation(12); - - self::assertAttributeEquals( - 12, - 'salutation', - $this->subject - ); - } - - /** - * @test - */ - public function getFirstNameReturnsInitialValueForString() - { - self::assertSame( - '', - $this->subject->getFirstName() - ); - } - - /** - * @test - */ - public function setFirstNameForStringSetsFirstName() - { - $this->subject->setFirstName('Conceived at T3CON10'); - - self::assertAttributeEquals( - 'Conceived at T3CON10', - 'firstName', - $this->subject - ); - } - - /** - * @test - */ - public function getLastNameReturnsInitialValueForString() - { - self::assertSame( - '', - $this->subject->getLastName() - ); - } - - /** - * @test - */ - public function setLastNameForStringSetsLastName() - { - $this->subject->setLastName('Conceived at T3CON10'); - - self::assertAttributeEquals( - 'Conceived at T3CON10', - 'lastName', - $this->subject - ); - } - - /** - * @test - */ - public function getEmailReturnsInitialValueForString() - { - self::assertSame( - '', - $this->subject->getEmail() - ); - } - - /** - * @test - */ - public function setEmailForStringSetsEmail() - { - $this->subject->setEmail('Conceived at T3CON10'); - - self::assertAttributeEquals( - 'Conceived at T3CON10', - 'email', - $this->subject - ); - } - - /** - * @test - */ - public function getPhoneReturnsInitialValueForString() - { - self::assertSame( - '', - $this->subject->getPhone() - ); - } - - /** - * @test - */ - public function setPhoneForStringSetsPhone() - { - $this->subject->setPhone('Conceived at T3CON10'); - - self::assertAttributeEquals( - 'Conceived at T3CON10', - 'phone', - $this->subject - ); - } - - /** - * @test - */ - public function getAddressStreetAndNumberReturnsInitialValueForString() - { - self::assertSame( - '', - $this->subject->getAddressStreetAndNumber() - ); - } - - /** - * @test - */ - public function setAddressStreetAndNumberForStringSetsAddressStreetAndNumber() - { - $this->subject->setAddressStreetAndNumber('Conceived at T3CON10'); - - self::assertAttributeEquals( - 'Conceived at T3CON10', - 'addressStreetAndNumber', - $this->subject - ); - } - - /** - * @test - */ - public function getAddressAdditionReturnsInitialValueForString() - { - self::assertSame( - '', - $this->subject->getAddressAddition() - ); - } - - /** - * @test - */ - public function setAddressAdditionForStringSetsAddressAddition() - { - $this->subject->setAddressAddition('Conceived at T3CON10'); - - self::assertAttributeEquals( - 'Conceived at T3CON10', - 'addressAddition', - $this->subject - ); - } - - /** - * @test - */ - public function getAddressPostCodeReturnsInitialValueForInt() - { - self::assertSame( - 0, - $this->subject->getAddressPostCode() - ); - } - - /** - * @test - */ - public function setAddressPostCodeForIntSetsAddressPostCode() - { - $this->subject->setAddressPostCode(12); - - self::assertAttributeEquals( - 12, - 'addressPostCode', - $this->subject - ); - } - - /** - * @test - */ - public function getAddressCityReturnsInitialValueForString() - { - self::assertSame( - '', - $this->subject->getAddressCity() - ); - } - - /** - * @test - */ - public function setAddressCityForStringSetsAddressCity() - { - $this->subject->setAddressCity('Conceived at T3CON10'); - - self::assertAttributeEquals( - 'Conceived at T3CON10', - 'addressCity', - $this->subject - ); - } - - /** - * @test - */ - public function getAddressCountryReturnsInitialValueForString() - { - self::assertSame( - '', - $this->subject->getAddressCountry() - ); - } - - /** - * @test - */ - public function setAddressCountryForStringSetsAddressCountry() - { - $this->subject->setAddressCountry('Conceived at T3CON10'); - - self::assertAttributeEquals( - 'Conceived at T3CON10', - 'addressCountry', - $this->subject - ); - } - - /** - * @test - */ - public function getSalaryExpectationReturnsInitialValueForString() - { - self::assertSame( - '', - $this->subject->getSalaryExpectation() - ); - } - - /** - * @test - */ - public function setSalaryExpectationForStringSetsSalaryExpectation() - { - $this->subject->setSalaryExpectation('Conceived at T3CON10'); - - self::assertAttributeEquals( - 'Conceived at T3CON10', - 'salaryExpectation', - $this->subject - ); - } - - /** - * @test - */ - public function getEarliestDateOfJoiningReturnsInitialValueForDateTime() - { - self::assertEquals( - null, - $this->subject->getEarliestDateOfJoining() - ); - } - - /** - * @test - */ - public function setEarliestDateOfJoiningForDateTimeSetsEarliestDateOfJoining() - { - $dateTimeFixture = new \DateTime(); - $this->subject->setEarliestDateOfJoining($dateTimeFixture); - - self::assertAttributeEquals( - $dateTimeFixture, - 'earliestDateOfJoining', - $this->subject - ); - } - - /** - * @test - */ - public function getCvReturnsInitialValueForFileReference() - { - self::assertEquals( - null, - $this->subject->getCv() - ); - } - - /** - * @test - */ - public function setCvForFileReferenceSetsCv() - { - $fileReferenceFixture = new FileReference(); - $this->subject->setCv($fileReferenceFixture); - - self::assertAttributeEquals( - $fileReferenceFixture, - 'cv', - $this->subject - ); - } - - /** - * @test - */ - public function getCoverLetterReturnsInitialValueForFileReference() - { - self::assertEquals( - null, - $this->subject->getCoverLetter() - ); - } - - /** - * @test - */ - public function setCoverLetterForFileReferenceSetsCoverLetter() - { - $fileReferenceFixture = new FileReference(); - $this->subject->setCoverLetter($fileReferenceFixture); - - self::assertAttributeEquals( - $fileReferenceFixture, - 'coverLetter', - $this->subject - ); - } - - /** - * @test - */ - public function getTestimonialsReturnsInitialValueForFileReference() - { - self::assertEquals( - null, - $this->subject->getTestimonials() - ); - } - - /** - * @test - */ - public function setTestimonialsForFileReferenceSetsTestimonials() - { - $fileReferenceFixture = new FileReference(); - $this->subject->setTestimonials($fileReferenceFixture); - - self::assertAttributeEquals( - $fileReferenceFixture, - 'testimonials', - $this->subject - ); - } - - /** - * @test - */ - public function getOtherFilesReturnsInitialValueForFileReference() - { - self::assertEquals( - null, - $this->subject->getOtherFiles() - ); - } - - /** - * @test - */ - public function setOtherFilesForFileReferenceSetsOtherFiles() - { - $fileReferenceFixture = new FileReference(); - $this->subject->setOtherFiles($fileReferenceFixture); - - self::assertAttributeEquals( - $fileReferenceFixture, - 'otherFiles', - $this->subject - ); - } - - /** - * @test - */ - public function getPrivacyAgreementReturnsInitialValueForBool() - { - self::assertSame( - false, - $this->subject->getPrivacyAgreement() - ); - } - - /** - * @test - */ - public function setPrivacyAgreementForBoolSetsPrivacyAgreement() - { - $this->subject->setPrivacyAgreement(true); - - self::assertAttributeEquals( - true, - 'privacyAgreement', - $this->subject - ); - } - - /** - * @test - */ - public function getPostingReturnsInitialValueForPosting() - { - self::assertEquals( - null, - $this->subject->getPosting() - ); - } - - /** - * @test - */ - public function setPostingForPostingSetsPosting() - { - $postingFixture = new Posting(); - $this->subject->setPosting($postingFixture); - - self::assertAttributeEquals( - $postingFixture, - 'posting', - $this->subject - ); - } - - protected function setUp() - { - parent::setUp(); - $this->subject = new Application(); - } - - protected function tearDown() - { - parent::tearDown(); - } - } diff --git a/Tests/Unit/Domain/Model/ContactTest.php b/Tests/Unit/Domain/Model/ContactTest.php deleted file mode 100644 index 71c029a..0000000 --- a/Tests/Unit/Domain/Model/ContactTest.php +++ /dev/null @@ -1,130 +0,0 @@ -subject->getName() - ); - } - - /** - * @test - */ - public function setNameForStringSetsName() - { - $this->subject->setName('Conceived at T3CON10'); - - self::assertAttributeEquals( - 'Conceived at T3CON10', - 'name', - $this->subject - ); - } - - /** - * @test - */ - public function getEmailReturnsInitialValueForString() - { - self::assertSame( - '', - $this->subject->getEmail() - ); - } - - /** - * @test - */ - public function setEmailForStringSetsEmail() - { - $this->subject->setEmail('Conceived at T3CON10'); - - self::assertAttributeEquals( - 'Conceived at T3CON10', - 'email', - $this->subject - ); - } - - /** - * @test - */ - public function getPhoneReturnsInitialValueForString() - { - self::assertSame( - '', - $this->subject->getPhone() - ); - } - - /** - * @test - */ - public function setPhoneForStringSetsPhone() - { - $this->subject->setPhone('Conceived at T3CON10'); - - self::assertAttributeEquals( - 'Conceived at T3CON10', - 'phone', - $this->subject - ); - } - - /** - * @test - */ - public function getDivisionReturnsInitialValueForString() - { - self::assertSame( - '', - $this->subject->getDivision() - ); - } - - /** - * @test - */ - public function setDivisionForStringSetsDivision() - { - $this->subject->setDivision('Conceived at T3CON10'); - - self::assertAttributeEquals( - 'Conceived at T3CON10', - 'division', - $this->subject - ); - } - - protected function setUp() - { - parent::setUp(); - $this->subject = new Contact(); - } - - protected function tearDown() - { - parent::tearDown(); - } - } diff --git a/Tests/Unit/Domain/Model/LocationTest.php b/Tests/Unit/Domain/Model/LocationTest.php deleted file mode 100644 index 0690386..0000000 --- a/Tests/Unit/Domain/Model/LocationTest.php +++ /dev/null @@ -1,130 +0,0 @@ -subject->getName() - ); - } - - /** - * @test - */ - public function setNameForStringSetsName() - { - $this->subject->setName('Conceived at T3CON10'); - - self::assertAttributeEquals( - 'Conceived at T3CON10', - 'name', - $this->subject - ); - } - - /** - * @test - */ - public function getAddressReturnsInitialValueForString() - { - self::assertSame( - '', - $this->subject->getAddress() - ); - } - - /** - * @test - */ - public function setAddressForStringSetsAddress() - { - $this->subject->setAddress('Conceived at T3CON10'); - - self::assertAttributeEquals( - 'Conceived at T3CON10', - 'address', - $this->subject - ); - } - - /** - * @test - */ - public function getLatitudeReturnsInitialValueForString() - { - self::assertSame( - '', - $this->subject->getLatitude() - ); - } - - /** - * @test - */ - public function setLatitudeForStringSetsLatitude() - { - $this->subject->setLatitude('Conceived at T3CON10'); - - self::assertAttributeEquals( - 'Conceived at T3CON10', - 'latitude', - $this->subject - ); - } - - /** - * @test - */ - public function getLonditudeReturnsInitialValueForString() - { - self::assertSame( - '', - $this->subject->getLonditude() - ); - } - - /** - * @test - */ - public function setLonditudeForStringSetsLonditude() - { - $this->subject->setLonditude('Conceived at T3CON10'); - - self::assertAttributeEquals( - 'Conceived at T3CON10', - 'londitude', - $this->subject - ); - } - - protected function setUp() - { - parent::setUp(); - $this->subject = new Location(); - } - - protected function tearDown() - { - parent::tearDown(); - } - } diff --git a/Tests/Unit/Domain/Model/PostingTest.php b/Tests/Unit/Domain/Model/PostingTest.php deleted file mode 100644 index df590a9..0000000 --- a/Tests/Unit/Domain/Model/PostingTest.php +++ /dev/null @@ -1,488 +0,0 @@ -subject->getTitle() - ); - } - - /** - * @test - */ - public function setTitleForStringSetsTitle() - { - $this->subject->setTitle('Conceived at T3CON10'); - - self::assertAttributeEquals( - 'Conceived at T3CON10', - 'title', - $this->subject - ); - } - - /** - * @test - */ - public function getDatePostedReturnsInitialValueForDateTime() - { - self::assertEquals( - null, - $this->subject->getDatePosted() - ); - } - - /** - * @test - */ - public function setDatePostedForDateTimeSetsDatePosted() - { - $dateTimeFixture = new \DateTime(); - $this->subject->setDatePosted($dateTimeFixture); - - self::assertAttributeEquals( - $dateTimeFixture, - 'datePosted', - $this->subject - ); - } - - /** - * @test - */ - public function getCareerLevelReturnsInitialValueForString() - { - self::assertSame( - '', - $this->subject->getCareerLevel() - ); - } - - /** - * @test - */ - public function setCareerLevelForStringSetsCareerLevel() - { - $this->subject->setCareerLevel('Conceived at T3CON10'); - - self::assertAttributeEquals( - 'Conceived at T3CON10', - 'careerLevel', - $this->subject - ); - } - - /** - * @test - */ - public function getDivisionReturnsInitialValueForString() - { - self::assertSame( - '', - $this->subject->getDivision() - ); - } - - /** - * @test - */ - public function setDivisionForStringSetsDivision() - { - $this->subject->setDivision('Conceived at T3CON10'); - - self::assertAttributeEquals( - 'Conceived at T3CON10', - 'division', - $this->subject - ); - } - - /** - * @test - */ - public function getEmploymentTypeReturnsInitialValueForString() - { - self::assertSame( - '', - $this->subject->getEmploymentType() - ); - } - - /** - * @test - */ - public function setEmploymentTypeForStringSetsEmploymentType() - { - $this->subject->setEmploymentType('Conceived at T3CON10'); - - self::assertAttributeEquals( - 'Conceived at T3CON10', - 'employmentType', - $this->subject - ); - } - - /** - * @test - */ - public function getTermsOfEmploymentReturnsInitialValueForString() - { - self::assertSame( - '', - $this->subject->getTermsOfEmployment() - ); - } - - /** - * @test - */ - public function setTermsOfEmploymentForStringSetsTermsOfEmployment() - { - $this->subject->setTermsOfEmployment('Conceived at T3CON10'); - - self::assertAttributeEquals( - 'Conceived at T3CON10', - 'termsOfEmployment', - $this->subject - ); - } - - /** - * @test - */ - public function getCompanyDescriptionReturnsInitialValueForString() - { - self::assertSame( - '', - $this->subject->getCompanyDescription() - ); - } - - /** - * @test - */ - public function setCompanyDescriptionForStringSetsCompanyDescription() - { - $this->subject->setCompanyDescription('Conceived at T3CON10'); - - self::assertAttributeEquals( - 'Conceived at T3CON10', - 'companyDescription', - $this->subject - ); - } - - /** - * @test - */ - public function getJobDescriptionReturnsInitialValueForString() - { - self::assertSame( - '', - $this->subject->getJobDescription() - ); - } - - /** - * @test - */ - public function setJobDescriptionForStringSetsJobDescription() - { - $this->subject->setJobDescription('Conceived at T3CON10'); - - self::assertAttributeEquals( - 'Conceived at T3CON10', - 'jobDescription', - $this->subject - ); - } - - /** - * @test - */ - public function getRoleDescriptionReturnsInitialValueForString() - { - self::assertSame( - '', - $this->subject->getRoleDescription() - ); - } - - /** - * @test - */ - public function setRoleDescriptionForStringSetsRoleDescription() - { - $this->subject->setRoleDescription('Conceived at T3CON10'); - - self::assertAttributeEquals( - 'Conceived at T3CON10', - 'roleDescription', - $this->subject - ); - } - - /** - * @test - */ - public function getSkillRequirementsReturnsInitialValueForString() - { - self::assertSame( - '', - $this->subject->getSkillRequirements() - ); - } - - /** - * @test - */ - public function setSkillRequirementsForStringSetsSkillRequirements() - { - $this->subject->setSkillRequirements('Conceived at T3CON10'); - - self::assertAttributeEquals( - 'Conceived at T3CON10', - 'skillRequirements', - $this->subject - ); - } - - /** - * @test - */ - public function getBenefitsReturnsInitialValueForString() - { - self::assertSame( - '', - $this->subject->getBenefits() - ); - } - - /** - * @test - */ - public function setBenefitsForStringSetsBenefits() - { - $this->subject->setBenefits('Conceived at T3CON10'); - - self::assertAttributeEquals( - 'Conceived at T3CON10', - 'benefits', - $this->subject - ); - } - - /** - * @test - */ - public function getBaseSalaryReturnsInitialValueForString() - { - self::assertSame( - '', - $this->subject->getBaseSalary() - ); - } - - /** - * @test - */ - public function setBaseSalaryForStringSetsBaseSalary() - { - $this->subject->setBaseSalary('Conceived at T3CON10'); - - self::assertAttributeEquals( - 'Conceived at T3CON10', - 'baseSalary', - $this->subject - ); - } - - /** - * @test - */ - public function getRequiredDocumentsReturnsInitialValueForString() - { - self::assertSame( - '', - $this->subject->getRequiredDocuments() - ); - } - - /** - * @test - */ - public function setRequiredDocumentsForStringSetsRequiredDocuments() - { - $this->subject->setRequiredDocuments('Conceived at T3CON10'); - - self::assertAttributeEquals( - 'Conceived at T3CON10', - 'requiredDocuments', - $this->subject - ); - } - - /** - * @test - */ - public function getCompanyInformationReturnsInitialValueForString() - { - self::assertSame( - '', - $this->subject->getCompanyInformation() - ); - } - - /** - * @test - */ - public function setCompanyInformationForStringSetsCompanyInformation() - { - $this->subject->setCompanyInformation('Conceived at T3CON10'); - - self::assertAttributeEquals( - 'Conceived at T3CON10', - 'companyInformation', - $this->subject - ); - } - - /** - * @test - */ - public function getDetailViewImageReturnsInitialValueForFileReference() - { - self::assertEquals( - null, - $this->subject->getDetailViewImage() - ); - } - - /** - * @test - */ - public function setDetailViewImageForFileReferenceSetsDetailViewImage() - { - $fileReferenceFixture = new FileReference(); - $this->subject->setDetailViewImage($fileReferenceFixture); - - self::assertAttributeEquals( - $fileReferenceFixture, - 'detailViewImage', - $this->subject - ); - } - - /** - * @test - */ - public function getListViewImageReturnsInitialValueForFileReference() - { - self::assertEquals( - null, - $this->subject->getListViewImage() - ); - } - - /** - * @test - */ - public function setListViewImageForFileReferenceSetsListViewImage() - { - $fileReferenceFixture = new FileReference(); - $this->subject->setListViewImage($fileReferenceFixture); - - self::assertAttributeEquals( - $fileReferenceFixture, - 'listViewImage', - $this->subject - ); - } - - /** - * @test - */ - public function getLocationReturnsInitialValueForLocation() - { - self::assertEquals( - null, - $this->subject->getLocation() - ); - } - - /** - * @test - */ - public function setLocationForLocationSetsLocation() - { - $locationFixture = new Location(); - $this->subject->setLocation($locationFixture); - - self::assertAttributeEquals( - $locationFixture, - 'location', - $this->subject - ); - } - - /** - * @test - */ - public function getContactReturnsInitialValueForContact() - { - self::assertEquals( - null, - $this->subject->getContact() - ); - } - - /** - * @test - */ - public function setContactForContactSetsContact() - { - $contactFixture = new Contact(); - $this->subject->setContact($contactFixture); - - self::assertAttributeEquals( - $contactFixture, - 'contact', - $this->subject - ); - } - - protected function setUp() - { - parent::setUp(); - $this->subject = new Posting(); - } - - protected function tearDown() - { - parent::tearDown(); - } - } From 647398a00508e9779e5b6b543977f7ec49ac159b Mon Sep 17 00:00:00 2001 From: Benjamin Jasper Date: Fri, 11 Mar 2022 08:51:19 +0100 Subject: [PATCH 45/61] fix: removed unneeded base uri --- Classes/Controller/BackendController.php | 5 +---- .../Backend/Templates/Backend/ShowApplication.html | 10 +++++----- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/Classes/Controller/BackendController.php b/Classes/Controller/BackendController.php index 3e7c0b4..127ceff 100644 --- a/Classes/Controller/BackendController.php +++ b/Classes/Controller/BackendController.php @@ -25,6 +25,7 @@ namespace ITX\Jobapplications\Controller; + use Psr\Http\Message\ServerRequestInterface; use TYPO3\CMS\Core\Pagination\SimplePagination; use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; use ITX\Jobapplications\Domain\Model\Application; @@ -274,11 +275,7 @@ public function showApplicationAction(Application $application) $this->persistenceManager->persistAll(); } - // Fetch baseuri for f:uri to access Public folder - $baseUri = str_replace('typo3/', '', $this->request->getBaseUri()); - $this->view->assign('application', $application); - $this->view->assign('baseUri', $baseUri); } /** diff --git a/Resources/Private/Backend/Templates/Backend/ShowApplication.html b/Resources/Private/Backend/Templates/Backend/ShowApplication.html index 85739de..10ba6ba 100644 --- a/Resources/Private/Backend/Templates/Backend/ShowApplication.html +++ b/Resources/Private/Backend/Templates/Backend/ShowApplication.html @@ -123,7 +123,7 @@
- + pdf download @@ -131,7 +131,7 @@
- + pdf download @@ -139,7 +139,7 @@
- + pdf download @@ -147,7 +147,7 @@
- + pdf download @@ -155,7 +155,7 @@
- + pdf {file.originalResource.name} download From 7445bb762cf67566fa15a65804ac8908ec586dec Mon Sep 17 00:00:00 2001 From: Benjamin Jasper Date: Thu, 31 Mar 2022 16:05:08 +0200 Subject: [PATCH 46/61] build: removed replace on itself --- composer.json | 1 - 1 file changed, 1 deletion(-) diff --git a/composer.json b/composer.json index 0d30d49..22fa307 100644 --- a/composer.json +++ b/composer.json @@ -48,7 +48,6 @@ } }, "replace": { - "itx/jobapplications": "self.version", "typo3-ter/jobapplications": "self.version" } } \ No newline at end of file From 7272dec614bf5d149d47b709d334f50710b149e5 Mon Sep 17 00:00:00 2001 From: sdl Date: Tue, 5 Apr 2022 21:05:53 +0200 Subject: [PATCH 47/61] fix: language management of filter options * core depends on having the language column in the db result * new tca type "language" * cache respects language id now --- Classes/Controller/PostingController.php | 24 ++++++---- .../Domain/Repository/PostingRepository.php | 46 ++++++++++++------- ...bapplications_domain_model_application.php | 12 +---- ...x_jobapplications_domain_model_contact.php | 12 +---- ..._jobapplications_domain_model_location.php | 12 +---- ...x_jobapplications_domain_model_posting.php | 12 +---- ...tx_jobapplications_domain_model_status.php | 12 +---- Documentation/Installation/Index.rst | 1 + 8 files changed, 50 insertions(+), 81 deletions(-) diff --git a/Classes/Controller/PostingController.php b/Classes/Controller/PostingController.php index 6b16fe1..d1f6d7a 100644 --- a/Classes/Controller/PostingController.php +++ b/Classes/Controller/PostingController.php @@ -12,6 +12,7 @@ use TYPO3\CMS\Core\Cache\CacheManager; use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface; use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; + use TYPO3\CMS\Core\Context\Context; use TYPO3\CMS\Core\Error\Http\PageNotFoundException; use TYPO3\CMS\Core\Http\ImmediateResponseException; use TYPO3\CMS\Core\Page\PageRenderer; @@ -182,16 +183,18 @@ private function getCachedFilterOptions(array $categories): array /** @var FrontendInterface $cache */ $cache = GeneralUtility::makeInstance(CacheManager::class)->getCache('jobapplications_cache'); + $languageAspect = GeneralUtility::makeInstance(Context::class)->getAspect('language'); + $languageId = $languageAspect->getId(); - // If $entry is false, it hasn't been cached. Calculate the value and store it in the cache: - if (($entry = $cache->get($cacheKey)) === false) + // If $entry is false, or language key does not exist it hasn't been cached. Calculate the value and store it in the cache: + if (($entry = $cache->get($cacheKey)) === false || !key_exists($languageId, $entry)) { - $entry = $this->getFilterOptions($categories); + $entry = $this->getFilterOptions($categories, $languageId); $cache->set($cacheKey, $entry, [], null); } - return $entry; + return $entry[$languageId]; } /** @@ -200,17 +203,20 @@ private function getCachedFilterOptions(array $categories): array * Override for customization. * * @param $categories array categories + * @param $languageId int * * @return array * @throws InvalidQueryException */ - public function getFilterOptions(array $categories): array + public function getFilterOptions(array $categories, $languageId): array { return [ - 'division' => $this->postingRepository->findAllDivisions($categories), - 'careerLevel' => $this->postingRepository->findAllCareerLevels($categories), - 'employmentType' => $this->postingRepository->findAllEmploymentTypes($categories), - 'location' => $this->locationRepository->findAll($categories)->toArray(), + $languageId => [ + 'division' => $this->postingRepository->findAllDivisions($categories, $languageId), + 'careerLevel' => $this->postingRepository->findAllCareerLevels($categories, $languageId), + 'employmentType' => $this->postingRepository->findAllEmploymentTypes($categories, $languageId), + 'location' => $this->locationRepository->findAll($categories)->toArray() + ] ]; } diff --git a/Classes/Domain/Repository/PostingRepository.php b/Classes/Domain/Repository/PostingRepository.php index f24fa1c..cfbb6ad 100644 --- a/Classes/Domain/Repository/PostingRepository.php +++ b/Classes/Domain/Repository/PostingRepository.php @@ -4,6 +4,7 @@ use ITX\Jobapplications\Domain\Model\Constraint; use ITX\Jobapplications\Domain\Repository\RepoHelpers; + use TYPO3\CMS\Core\Context\Context; use TYPO3\CMS\Core\Utility\DebugUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Persistence\QueryInterface; @@ -68,10 +69,11 @@ public function findByCategory(array $categories) * Gets all divisions * * @param array|null $categories + * @param int $languageUid * * @return array */ - public function findAllDivisions(array $categories = null): array + public function findAllDivisions(array $categories = null, int $languageUid): array { $qb = $this->getQueryBuilder("tx_jobapplications_domain_model_posting"); $query = $this->createQuery(); @@ -80,18 +82,20 @@ public function findAllDivisions(array $categories = null): array if (count($categories) === 0) { $qb - ->select("division") - ->groupBy("division") + ->select("division", "sys_language_uid") + ->groupBy("division", "sys_language_uid") ->from("tx_jobapplications_domain_model_posting") - ->andWhere($qb->expr()->in("pid", $query->getQuerySettings()->getStoragePageIds())); + ->andWhere($qb->expr()->in("pid", $query->getQuerySettings()->getStoragePageIds())) + ->andWhere($qb->expr()->eq("sys_language_uid", $languageUid)); } else { $qb - ->select("division") - ->groupBy("division") + ->select("division", "sys_language_uid") + ->groupBy("division", "sys_language_uid") ->from("tx_jobapplications_domain_model_posting") ->andWhere($qb->expr()->in("pid", $query->getQuerySettings()->getStoragePageIds())) + ->andWhere($qb->expr()->eq("sys_language_uid", $languageUid)) ->join("tx_jobapplications_domain_model_posting", "sys_category_record_mm", "sys_category_record_mm", $qb->expr()->eq("tx_jobapplications_domain_model_posting.uid", "sys_category_record_mm.uid_foreign")) @@ -108,10 +112,11 @@ public function findAllDivisions(array $categories = null): array /** * @param array|null $categories + * @param int $languageUid * * @return array */ - public function findAllCareerLevels(array $categories = null): array + public function findAllCareerLevels(array $categories = null, int $languageUid): array { $qb = $this->getQueryBuilder("tx_jobapplications_domain_model_posting"); @@ -121,18 +126,20 @@ public function findAllCareerLevels(array $categories = null): array if (count($categories) === 0) { $qb - ->select("career_level AS careerLevel") - ->groupBy("careerLevel") + ->select("career_level AS careerLevel", "sys_language_uid") + ->groupBy("careerLevel", "sys_language_uid") ->from("tx_jobapplications_domain_model_posting") - ->where($qb->expr()->in("pid", $query->getQuerySettings()->getStoragePageIds())); + ->where($qb->expr()->in("pid", $query->getQuerySettings()->getStoragePageIds())) + ->andWhere($qb->expr()->eq("sys_language_uid", $languageUid)); } else { $qb - ->select("career_level AS careerLevel") - ->groupBy("careerLevel") + ->select("career_level AS careerLevel", "sys_language_uid") + ->groupBy("careerLevel", "sys_language_uid") ->from("tx_jobapplications_domain_model_posting") ->where($qb->expr()->in("pid", $query->getQuerySettings()->getStoragePageIds())) + ->andWhere($qb->expr()->eq("sys_language_uid", $languageUid)) ->join("tx_jobapplications_domain_model_posting", "sys_category_record_mm", "sys_category_record_mm", $qb->expr()->eq("tx_jobapplications_domain_model_posting.uid", "sys_category_record_mm.uid_foreign")) @@ -148,9 +155,12 @@ public function findAllCareerLevels(array $categories = null): array } /** + * @param array|null $categories + * @param int $languageUid + * * @return array */ - public function findAllEmploymentTypes(array $categories = null) + public function findAllEmploymentTypes(array $categories = null, int $languageUid) { $qb = $this->getQueryBuilder("tx_jobapplications_domain_model_posting"); @@ -160,19 +170,21 @@ public function findAllEmploymentTypes(array $categories = null) if (count($categories) === 0) { $qb - ->select("employment_type AS employmentType") - ->groupBy("employmentType") + ->select("employment_type AS employmentType", "sys_language_uid") + ->groupBy("employmentType", "sys_language_uid") ->from("tx_jobapplications_domain_model_posting") ->andWhere($qb->expr()->in('pid', $query->getQuerySettings()->getStoragePageIds())) + ->andWhere($qb->expr()->eq("sys_language_uid", $languageUid)) ->orderBy('employmentType', QueryInterface::ORDER_ASCENDING); } else { $qb - ->select("employment_type AS employmentType") - ->groupBy("employmentType") + ->select("employment_type AS employmentType", "sys_language_uid") + ->groupBy("employmentType", "sys_language_uid") ->from("tx_jobapplications_domain_model_posting") ->where($qb->expr()->in("pid", $query->getQuerySettings()->getStoragePageIds())) + ->andWhere($qb->expr()->eq("sys_language_uid", $languageUid)) ->join("tx_jobapplications_domain_model_posting", "sys_category_record_mm", "sys_category_record_mm", $qb->expr()->eq("tx_jobapplications_domain_model_posting.uid", "sys_category_record_mm.uid_foreign")) diff --git a/Configuration/TCA/tx_jobapplications_domain_model_application.php b/Configuration/TCA/tx_jobapplications_domain_model_application.php index 1c40f65..793199a 100644 --- a/Configuration/TCA/tx_jobapplications_domain_model_application.php +++ b/Configuration/TCA/tx_jobapplications_domain_model_application.php @@ -37,17 +37,7 @@ 'exclude' => true, 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language', 'config' => [ - 'type' => 'select', - 'renderType' => 'selectSingle', - 'special' => 'languages', - 'items' => [ - [ - 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.allLanguages', - -1, - 'flags-multiple' - ] - ], - 'default' => 0, + 'type' => 'language' ], ], 'l10n_parent' => [ diff --git a/Configuration/TCA/tx_jobapplications_domain_model_contact.php b/Configuration/TCA/tx_jobapplications_domain_model_contact.php index 9ded31a..fefd4e3 100644 --- a/Configuration/TCA/tx_jobapplications_domain_model_contact.php +++ b/Configuration/TCA/tx_jobapplications_domain_model_contact.php @@ -27,17 +27,7 @@ 'exclude' => true, 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language', 'config' => [ - 'type' => 'select', - 'renderType' => 'selectSingle', - 'special' => 'languages', - 'items' => [ - [ - 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.allLanguages', - -1, - 'flags-multiple' - ] - ], - 'default' => 0, + 'type' => 'language' ], ], 'l10n_parent' => [ diff --git a/Configuration/TCA/tx_jobapplications_domain_model_location.php b/Configuration/TCA/tx_jobapplications_domain_model_location.php index 115a065..52352a2 100644 --- a/Configuration/TCA/tx_jobapplications_domain_model_location.php +++ b/Configuration/TCA/tx_jobapplications_domain_model_location.php @@ -27,17 +27,7 @@ 'exclude' => true, 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language', 'config' => [ - 'type' => 'select', - 'renderType' => 'selectSingle', - 'special' => 'languages', - 'items' => [ - [ - 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.allLanguages', - -1, - 'flags-multiple' - ] - ], - 'default' => 0, + 'type' => 'language' ], ], 'l10n_parent' => [ diff --git a/Configuration/TCA/tx_jobapplications_domain_model_posting.php b/Configuration/TCA/tx_jobapplications_domain_model_posting.php index 3f3fc61..ff4f2f0 100644 --- a/Configuration/TCA/tx_jobapplications_domain_model_posting.php +++ b/Configuration/TCA/tx_jobapplications_domain_model_posting.php @@ -27,17 +27,7 @@ 'exclude' => true, 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language', 'config' => [ - 'type' => 'select', - 'renderType' => 'selectSingle', - 'special' => 'languages', - 'items' => [ - [ - 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.allLanguages', - -1, - 'flags-multiple' - ] - ], - 'default' => 0, + 'type' => 'language' ], ], 'l10n_parent' => [ diff --git a/Configuration/TCA/tx_jobapplications_domain_model_status.php b/Configuration/TCA/tx_jobapplications_domain_model_status.php index d32c81f..3997836 100644 --- a/Configuration/TCA/tx_jobapplications_domain_model_status.php +++ b/Configuration/TCA/tx_jobapplications_domain_model_status.php @@ -38,17 +38,7 @@ 'exclude' => true, 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language', 'config' => [ - 'type' => 'select', - 'renderType' => 'selectSingle', - 'special' => 'languages', - 'items' => [ - [ - 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.allLanguages', - -1, - 'flags-multiple' - ] - ], - 'default' => 0, + 'type' => 'lanuage' ], ], 'l10n_parent' => [ diff --git a/Documentation/Installation/Index.rst b/Documentation/Installation/Index.rst index aa50408..70887cf 100644 --- a/Documentation/Installation/Index.rst +++ b/Documentation/Installation/Index.rst @@ -18,6 +18,7 @@ You can install it via composer by typing composer require itx/jobapplications or the Extension Manager in the Backend or install it locally for example directly from `Github <|project_repository|>`__. +Please make sure to switch to the Maintainance tool and push the buttons *analyse database structure* and *flush cache*. Include Static Typoscript ------------------------- From 67f9036d558703cfda8e9eeaa3c4615de6c233ae Mon Sep 17 00:00:00 2001 From: sdl Date: Tue, 5 Apr 2022 22:28:51 +0200 Subject: [PATCH 48/61] master merged --- .github/workflows/publish.yaml | 3 ++- Documentation/ChangeLog/Index.rst | 9 ++++++++- Documentation/Settings.cfg | 2 +- ext_emconf.php | 2 ++ 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 5519e5d..27cf4f6 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -1,5 +1,6 @@ name: publish on: + workflow_dispatch: push: tags: - '*' @@ -29,7 +30,7 @@ jobs: - name: Get comment id: get-comment run: | - readonly local comment=$(git tag -n10 -l ${{ steps.get-version.outputs.version }} | sed "s/^[0-9.]*[ ]*//g") + readonly local comment=$(git tag -n1 -l ${{ steps.get-version.outputs.version }} | sed "s/^[0-9.]*[ ]*//g") if [[ -z "${comment// }" ]]; then echo ::set-output name=comment::Released version ${{ steps.get-version.outputs.version }} of ${{ env.TYPO3_EXTENSION_KEY }} diff --git a/Documentation/ChangeLog/Index.rst b/Documentation/ChangeLog/Index.rst index 54181cd..a78ba9f 100644 --- a/Documentation/ChangeLog/Index.rst +++ b/Documentation/ChangeLog/Index.rst @@ -11,7 +11,11 @@ Changelog ========= -1.0.4 - Bugfixes +1.0.6 - Build fix +----------------- +* this update contains no actual content, and only fixes a build issue + +1.0.5 - Bugfixes ---------------- * [BUGFIX] fixed error "Unsupported or non-existing property name "categories" used in relation matching" when using categories with filters #51 * [BUGFIX] fixed error when removing filters from fluid template #44 @@ -20,6 +24,9 @@ Changelog * [FEATURE] removed postingApp parameter from links where a detail view and an application form are on the same page, it now works automatically #41 * [FEATURE] added configurable file storage #38 +1.0.4 - Skipped because of reason +--------------------------------- + 1.0.3 - Bugfixes ---------------- * [BUGFIX] fixed record deletion hook not checking if indexing is enabled diff --git a/Documentation/Settings.cfg b/Documentation/Settings.cfg index ee7b8d1..ec7ce07 100644 --- a/Documentation/Settings.cfg +++ b/Documentation/Settings.cfg @@ -27,7 +27,7 @@ project = Jobapplications Extension # ... (recommended) version, displayed next to title (desktop) and in 'it.x informationssysteme gmbh', 'author_email' => 'typo-itx@itx.de', 'state' => 'stable', + 'uploadfolder' => 1, + 'createDirs' => '', 'clearCacheOnLoad' => true, 'version' => '2.0.0', 'constraints' => [ From 8208dbd21381016988541f9dbe62c9ccfa043567 Mon Sep 17 00:00:00 2001 From: sdl Date: Tue, 5 Apr 2022 22:29:52 +0200 Subject: [PATCH 49/61] [wip]: make the location field a multi select field --- .../TCA/tx_jobapplications_domain_model_posting.php | 7 +++++-- ext_tables.sql | 12 +++++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Configuration/TCA/tx_jobapplications_domain_model_posting.php b/Configuration/TCA/tx_jobapplications_domain_model_posting.php index ff4f2f0..b276fb3 100644 --- a/Configuration/TCA/tx_jobapplications_domain_model_posting.php +++ b/Configuration/TCA/tx_jobapplications_domain_model_posting.php @@ -409,9 +409,12 @@ 'label' => 'LLL:EXT:jobapplications/Resources/Private/Language/locallang_db.xlf:tx_jobapplications_domain_model_posting.location', 'config' => [ 'type' => 'select', - 'renderType' => 'selectSingle', + 'renderType' => 'selectMultipleSideBySide', 'foreign_table' => 'tx_jobapplications_domain_model_location', - 'maxitems' => 1 + 'foreign_table_where' => 'tx_jobapplications_domain_model_location.sys_language_uid IN (0,-1) ORDER BY tx_jobapplications_domain_model_location.name ASC', + 'MM' => 'tx_jobapplications_postings_locations_mm', + 'size' => 3, + 'autoSizeMax' => 5, ], ], 'contact' => [ diff --git a/ext_tables.sql b/ext_tables.sql index fbe9764..10e68a6 100644 --- a/ext_tables.sql +++ b/ext_tables.sql @@ -22,7 +22,7 @@ CREATE TABLE tx_jobapplications_domain_model_posting company_information text, detail_view_image int(11) unsigned NOT NULL default '0', list_view_image int(11) unsigned NOT NULL default '0', - location int(11) unsigned DEFAULT '0', + location int(11) unsigned DEFAULT '0' NOT NULL, contact int(11) unsigned DEFAULT '0', slug varchar(255) DEFAULT '' NOT NULL @@ -62,6 +62,16 @@ CREATE TABLE tx_jobapplications_domain_model_location ); +CREATE TABLE tx_jobapplications_postings_locations_mm ( + uid_local int(11) unsigned DEFAULT '0' NOT NULL, + uid_foreign int(11) unsigned DEFAULT '0' NOT NULL, + sorting int(11) unsigned DEFAULT '0' NOT NULL, + sorting_foreign int(11) unsigned DEFAULT '0' NOT NULL, + + KEY uid_local (uid_local), + KEY uid_foreign (uid_foreign) +); + # # Table structure for table 'tx_jobapplications_domain_model_application' # From 6bc263b5c940bac2163fff763ba7700a51f62e27 Mon Sep 17 00:00:00 2001 From: sdl Date: Wed, 6 Apr 2022 13:32:20 +0200 Subject: [PATCH 50/61] feat: renamed location field to locations and changed the output in the templates --- Classes/Controller/PostingController.php | 10 +++---- Classes/Domain/Model/Constraint.php | 12 ++++---- Classes/Domain/Model/Posting.php | 22 +++++++-------- ...x_jobapplications_domain_model_posting.php | 6 ++-- Configuration/TypoScript/setup.typoscript | 4 +-- Resources/Private/Language/de.locallang.xlf | 6 ++-- .../Private/Language/de.locallang_db.xlf | 6 ++-- Resources/Private/Language/locallang.xlf | 4 +-- Resources/Private/Language/locallang_db.xlf | 4 +-- .../Private/Partials/Posting/ListItem.html | 7 +++-- .../Private/Partials/Posting/Properties.html | 28 ++++++++++--------- Resources/Private/Templates/Posting/List.html | 10 +++---- ext_tables.sql | 2 +- 13 files changed, 63 insertions(+), 58 deletions(-) diff --git a/Classes/Controller/PostingController.php b/Classes/Controller/PostingController.php index d1f6d7a..0ecf7fe 100644 --- a/Classes/Controller/PostingController.php +++ b/Classes/Controller/PostingController.php @@ -215,7 +215,7 @@ public function getFilterOptions(array $categories, $languageId): array 'division' => $this->postingRepository->findAllDivisions($categories, $languageId), 'careerLevel' => $this->postingRepository->findAllCareerLevels($categories, $languageId), 'employmentType' => $this->postingRepository->findAllEmploymentTypes($categories, $languageId), - 'location' => $this->locationRepository->findAll($categories)->toArray() + 'locations' => $this->locationRepository->findAll($categories)->toArray() ] ]; } @@ -337,10 +337,10 @@ protected function addGoogleJobsDataToPage(Posting $posting): void "jobLocation" => [ "@type" => "Place", "address" => [ - "streetAddress" => $posting->getLocation()->getAddressStreetAndNumber(), - "addressLocality" => $posting->getLocation()->getAddressCity(), - "postalCode" => $posting->getLocation()->getAddressPostCode(), - "addressCountry" => $posting->getLocation()->getAddressCountry() + "streetAddress" => $posting->getLocations()->getAddressStreetAndNumber(), + "addressLocality" => $posting->getLocations()->getAddressCity(), + "postalCode" => $posting->getLocations()->getAddressPostCode(), + "addressCountry" => $posting->getLocations()->getAddressCountry() ] ], "title" => $posting->getTitle(), diff --git a/Classes/Domain/Model/Constraint.php b/Classes/Domain/Model/Constraint.php index fb69aec..14accae 100644 --- a/Classes/Domain/Model/Constraint.php +++ b/Classes/Domain/Model/Constraint.php @@ -23,7 +23,7 @@ class Constraint /** @var array */ - protected $location = []; + protected $locations = []; /** * @return array @@ -76,16 +76,16 @@ public function setEmploymentType(array $employmentType): void /** * @return array */ - public function getLocation(): array + public function getLocations(): array { - return $this->location; + return $this->locations; } /** - * @param array $location + * @param array $locations */ - public function setLocation(array $location): void + public function setLocations(array $locations): void { - $this->location = $location; + $this->locations = $locations; } } \ No newline at end of file diff --git a/Classes/Domain/Model/Posting.php b/Classes/Domain/Model/Posting.php index 8029666..aaa71df 100644 --- a/Classes/Domain/Model/Posting.php +++ b/Classes/Domain/Model/Posting.php @@ -1,7 +1,7 @@ */ - protected $location = null; + protected $locations = null; /** * contact @@ -520,25 +520,25 @@ public function setCompanyInformation($companyInformation) } /** - * Returns the location + * Returns the locations * - * @return \ITX\Jobapplications\Domain\Model\Location location + * @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\ITX\Jobapplications\Domain\Model\Location> $locations */ - public function getLocation() + public function getLocations() { - return $this->location; + return $this->locations; } /** * Sets the location * - * @param \ITX\Jobapplications\Domain\Model\Location $location + * @param \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\ITX\Jobapplications\Domain\Model\Location> $locations * * @return void */ - public function setLocation(Location $location) + public function setLocations(\TYPO3\CMS\Extbase\Persistence\ObjectStorage $locations) { - $this->location = $location; + $this->locations = $locations; } /** diff --git a/Configuration/TCA/tx_jobapplications_domain_model_posting.php b/Configuration/TCA/tx_jobapplications_domain_model_posting.php index b276fb3..3c09446 100644 --- a/Configuration/TCA/tx_jobapplications_domain_model_posting.php +++ b/Configuration/TCA/tx_jobapplications_domain_model_posting.php @@ -404,9 +404,9 @@ $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'] ), ], - 'location' => [ + 'locations' => [ 'exclude' => true, - 'label' => 'LLL:EXT:jobapplications/Resources/Private/Language/locallang_db.xlf:tx_jobapplications_domain_model_posting.location', + 'label' => 'LLL:EXT:jobapplications/Resources/Private/Language/locallang_db.xlf:tx_jobapplications_domain_model_posting.locations', 'config' => [ 'type' => 'select', 'renderType' => 'selectMultipleSideBySide', @@ -465,7 +465,7 @@ 'showitem' => 'date_posted, starttime ,endtime' ], 'relations' => [ - 'showitem' => 'location, contact' + 'showitem' => 'locations, contact' ], 'images' => [ 'showitem' => 'detail_view_image, list_view_image' diff --git a/Configuration/TypoScript/setup.typoscript b/Configuration/TypoScript/setup.typoscript index b9ad1ef..7c871e3 100644 --- a/Configuration/TypoScript/setup.typoscript +++ b/Configuration/TypoScript/setup.typoscript @@ -60,8 +60,8 @@ plugin.tx_jobapplications { relationType = contains } - location { - relation = location + locations { + relation = locations relationType = equals } } diff --git a/Resources/Private/Language/de.locallang.xlf b/Resources/Private/Language/de.locallang.xlf index 6e7c2c8..da82cda 100644 --- a/Resources/Private/Language/de.locallang.xlf +++ b/Resources/Private/Language/de.locallang.xlf @@ -79,9 +79,9 @@ List View Image Bild Listenansicht - - Location - Standort + + Locations + Standorte Contact diff --git a/Resources/Private/Language/de.locallang_db.xlf b/Resources/Private/Language/de.locallang_db.xlf index e3794fb..3605bf6 100644 --- a/Resources/Private/Language/de.locallang_db.xlf +++ b/Resources/Private/Language/de.locallang_db.xlf @@ -75,9 +75,9 @@ List View Image Bild Listenansicht - - Location - Standort + + Locations + Standorte Contact diff --git a/Resources/Private/Language/locallang.xlf b/Resources/Private/Language/locallang.xlf index 3aea9ff..6dd15d5 100644 --- a/Resources/Private/Language/locallang.xlf +++ b/Resources/Private/Language/locallang.xlf @@ -60,8 +60,8 @@ List View Image - - Location + + Locations Contact diff --git a/Resources/Private/Language/locallang_db.xlf b/Resources/Private/Language/locallang_db.xlf index ffcd058..a4e9e98 100644 --- a/Resources/Private/Language/locallang_db.xlf +++ b/Resources/Private/Language/locallang_db.xlf @@ -57,8 +57,8 @@ List View Image - - Location + + Locations Contact diff --git a/Resources/Private/Partials/Posting/ListItem.html b/Resources/Private/Partials/Posting/ListItem.html index 2bb7646..fbe6c1d 100644 --- a/Resources/Private/Partials/Posting/ListItem.html +++ b/Resources/Private/Partials/Posting/ListItem.html @@ -20,11 +20,14 @@
- + :
- {posting.location.name} + + {location.name}{f:if(condition: '!{iterator.isLast}', then: ', ')} + +
diff --git a/Resources/Private/Partials/Posting/Properties.html b/Resources/Private/Partials/Posting/Properties.html index dafe3b5..a3626be 100644 --- a/Resources/Private/Partials/Posting/Properties.html +++ b/Resources/Private/Partials/Posting/Properties.html @@ -159,25 +159,27 @@
- +
- +
-

- - {posting.location.name}
-
- {posting.location.addressStreetAndNumber}
- - {posting.location.addressAddition}
-
- {posting.location.addressPostCode} {posting.location.addressCity}
- {posting.location.addressCountry} -

+ +

+ + {location.name}
+
+ {location.addressStreetAndNumber}
+ + {location.addressAddition}
+
+ {location.addressPostCode} {location.addressCity}
+ {location.addressCountry} +

+
diff --git a/Resources/Private/Templates/Posting/List.html b/Resources/Private/Templates/Posting/List.html index 125ea97..90f9670 100644 --- a/Resources/Private/Templates/Posting/List.html +++ b/Resources/Private/Templates/Posting/List.html @@ -56,13 +56,13 @@

-
-