From c21af664e76fb0161c9e7d13191782bc61058021 Mon Sep 17 00:00:00 2001 From: Alex Kellner Date: Fri, 4 Jun 2021 10:50:35 +0200 Subject: [PATCH 01/14] [FEATURE] Add a new record to store sender information via list view In addition there is also a model and repository and a small check in newsletter list module if there are records. I also added some exceptions to ConfigurationUtility for the old methods that should be rewritten in the upcoming commits. --- Classes/Controller/NewsletterController.php | 65 ++++--- Classes/Domain/Model/Settings.php | 167 ++++++++++++++++++ .../Domain/Repository/AbstractRepository.php | 1 - .../Domain/Repository/SettingsRepository.php | 10 ++ Classes/Tca/SiteSelection.php | 34 ++++ Classes/Utility/ConfigurationUtility.php | 16 ++ .../tx_luxletter_domain_model_settings.php | 100 +++++++++++ .../Private/Language/de.locallang_db.xlf | 29 +++ Resources/Private/Language/locallang_db.xlf | 22 +++ .../Private/Templates/Newsletter/List.html | 21 +++ .../tx_luxletter_domain_model_settings.svg | 3 + ext_localconf.php | 4 +- ext_tables.sql | 25 +++ 13 files changed, 465 insertions(+), 32 deletions(-) create mode 100644 Classes/Domain/Model/Settings.php create mode 100644 Classes/Domain/Repository/SettingsRepository.php create mode 100644 Classes/Tca/SiteSelection.php create mode 100644 Configuration/TCA/tx_luxletter_domain_model_settings.php create mode 100644 Resources/Public/Icons/tx_luxletter_domain_model_settings.svg diff --git a/Classes/Controller/NewsletterController.php b/Classes/Controller/NewsletterController.php index beea7c95..f50102fd 100644 --- a/Classes/Controller/NewsletterController.php +++ b/Classes/Controller/NewsletterController.php @@ -10,6 +10,7 @@ use In2code\Luxletter\Domain\Model\User; use In2code\Luxletter\Domain\Repository\LogRepository; use In2code\Luxletter\Domain\Repository\NewsletterRepository; +use In2code\Luxletter\Domain\Repository\SettingsRepository; use In2code\Luxletter\Domain\Repository\UserRepository; use In2code\Luxletter\Domain\Service\ParseNewsletterService; use In2code\Luxletter\Domain\Service\ParseNewsletterUrlService; @@ -75,6 +76,37 @@ class NewsletterController extends ActionController */ protected $logRepository = null; + /** + * @var SettingsRepository + */ + protected $settingsRepository = null; + + /** + * NewsletterController constructor. + * @param NewsletterRepository|null $newsletterRepository + * @param UserRepository|null $userRepository + * @param LogRepository|null $logRepository + * @param SettingsRepository|null $settingsRepository + * @throws Exception + */ + public function __construct( + NewsletterRepository $newsletterRepository = null, + UserRepository $userRepository = null, + LogRepository $logRepository = null, + SettingsRepository $settingsRepository = null + ) { + $this->newsletterRepository = $newsletterRepository ?: ObjectUtility::getObjectManager()->get( + NewsletterRepository::class + ); + $this->userRepository = $userRepository ?: ObjectUtility::getObjectManager()->get( + UserRepository::class + ); + $this->logRepository = $logRepository ?: ObjectUtility::getObjectManager()->get(LogRepository::class); + $this->settingsRepository = $settingsRepository ?: ObjectUtility::getObjectManager()->get( + SettingsRepository::class + ); + } + /** * @return void * @throws DBALException @@ -104,8 +136,10 @@ public function dashboardAction(): void */ public function listAction(): void { - $newsletters = $this->newsletterRepository->findAll(); - $this->view->assign('newsletters', $newsletters); + $this->view->assignMultiple([ + 'newsletters' => $this->newsletterRepository->findAll(), + 'luxlettersettings' => $this->settingsRepository->findAll() + ]); } /** @@ -375,31 +409,4 @@ protected function parseNewsletterToBodytext(): void $newsletter['bodytext'] = $parseService->getParsedContent(); $this->request->setArgument('newsletter', $newsletter); } - - /** - * @param NewsletterRepository $newsletterRepository - * @return void - */ - public function injectNewsletterRepository(NewsletterRepository $newsletterRepository): void - { - $this->newsletterRepository = $newsletterRepository; - } - - /** - * @param UserRepository $userRepository - * @return void - */ - public function injectUserRepository(UserRepository $userRepository): void - { - $this->userRepository = $userRepository; - } - - /** - * @param LogRepository $logRepository - * @return void - */ - public function injectLogRepository(LogRepository $logRepository): void - { - $this->logRepository = $logRepository; - } } diff --git a/Classes/Domain/Model/Settings.php b/Classes/Domain/Model/Settings.php new file mode 100644 index 00000000..b095d196 --- /dev/null +++ b/Classes/Domain/Model/Settings.php @@ -0,0 +1,167 @@ +title; + } + + /** + * @param string $title + * @return Settings + */ + public function setTitle(string $title): self + { + $this->title = $title; + return $this; + } + + /** + * @return string + */ + public function getFromEmail(): string + { + return $this->fromEmail; + } + + /** + * @param string $fromEmail + * @return Settings + */ + public function setFromEmail(string $fromEmail): self + { + $this->fromEmail = $fromEmail; + return $this; + } + + /** + * @return string + */ + public function getFromName(): string + { + return $this->fromName; + } + + /** + * @param string $fromName + * @return Settings + */ + public function setFromName(string $fromName): self + { + $this->fromName = $fromName; + return $this; + } + + /** + * @return string + */ + public function getReplyEmail(): string + { + return $this->replyEmail; + } + + /** + * @param string $replyEmail + * @return Settings + */ + public function setReplyEmail(string $replyEmail): self + { + $this->replyEmail = $replyEmail; + return $this; + } + + /** + * @return string + */ + public function getReplyName(): string + { + return $this->replyName; + } + + /** + * @param string $replyName + * @return Settings + */ + public function setReplyName(string $replyName): self + { + $this->replyName = $replyName; + return $this; + } + + /** + * @return string + */ + public function getSite(): string + { + return $this->site; + } + + /** + * @return Site + * @throws SiteNotFoundException + */ + public function getSiteConfiguration(): Site + { + $identifier = $this->getSite(); + /** @var SiteFinder $siteFinder */ + $siteFinder = GeneralUtility::makeInstance(SiteFinder::class); + return $siteFinder->getSiteByIdentifier($identifier); + } + + /** + * @param string $site + * @return Settings + */ + public function setSite(string $site): self + { + $this->site = $site; + return $this; + } +} diff --git a/Classes/Domain/Repository/AbstractRepository.php b/Classes/Domain/Repository/AbstractRepository.php index 4c5e8096..dd7c69d8 100644 --- a/Classes/Domain/Repository/AbstractRepository.php +++ b/Classes/Domain/Repository/AbstractRepository.php @@ -14,7 +14,6 @@ */ abstract class AbstractRepository extends Repository { - /** * @var array */ diff --git a/Classes/Domain/Repository/SettingsRepository.php b/Classes/Domain/Repository/SettingsRepository.php new file mode 100644 index 00000000..79b91227 --- /dev/null +++ b/Classes/Domain/Repository/SettingsRepository.php @@ -0,0 +1,10 @@ +getAllSites() as $site) { + $configuration['items'][] = [$site->getIdentifier(), $site->getIdentifier()]; + } + } + + /** + * @return Site[] + */ + protected function getAllSites(): array + { + /** @var SiteFinder $siteFinder */ + $siteFinder = GeneralUtility::makeInstance(SiteFinder::class); + return $siteFinder->getAllSites(); + } +} diff --git a/Classes/Utility/ConfigurationUtility.php b/Classes/Utility/ConfigurationUtility.php index 4df887ee..c7a005ec 100644 --- a/Classes/Utility/ConfigurationUtility.php +++ b/Classes/Utility/ConfigurationUtility.php @@ -35,15 +35,27 @@ public static function getExtensionSettings(): array */ public static function getDomain(): string { + throw new \LogicException('This function must be replaced by site configuration'); $domain = (string)GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('luxletter', 'domain'); return rtrim($domain, '/'); } + /** + * @return string like "https://www.domain.org/" + */ + public static function getCurrentDomain(): string + { + $uri = parse_url(GeneralUtility::getIndpEnv('TYPO3_REQUEST_URL'), PHP_URL_SCHEME); + $uri .= '://' . GeneralUtility::getIndpEnv('HTTP_HOST') . '/'; + return $uri; + } + /** * @return int */ public static function getPidUnsubscribe(): int { + throw new \LogicException('This function must be replaced by site configuration'); return (int)GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('luxletter', 'pidUnsubscribe'); } @@ -80,6 +92,7 @@ public static function isReceiverActionActivated(): bool */ public static function getFromEmail(): string { + throw new \LogicException('This function must be replaced by settings domain model'); return (string)GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('luxletter', 'fromEmail'); } @@ -88,6 +101,7 @@ public static function getFromEmail(): string */ public static function getFromName(): string { + throw new \LogicException('This function must be replaced by settings domain model'); return (string)GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('luxletter', 'fromName'); } @@ -96,6 +110,7 @@ public static function getFromName(): string */ public static function getReplyEmail(): string { + throw new \LogicException('This function must be replaced by settings domain model'); return (string)GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('luxletter', 'replyEmail'); } @@ -104,6 +119,7 @@ public static function getReplyEmail(): string */ public static function getReplyName(): string { + throw new \LogicException('This function must be replaced by settings domain model'); return (string)GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('luxletter', 'replyName'); } diff --git a/Configuration/TCA/tx_luxletter_domain_model_settings.php b/Configuration/TCA/tx_luxletter_domain_model_settings.php new file mode 100644 index 00000000..04e8998a --- /dev/null +++ b/Configuration/TCA/tx_luxletter_domain_model_settings.php @@ -0,0 +1,100 @@ + [ + 'title' => 'LLL:EXT:luxletter/Resources/Private/Language/locallang_db.xlf:' . Settings::TABLE_NAME, + 'label' => 'title', + 'tstamp' => 'tstamp', + 'crdate' => 'crdate', + 'cruser_id' => 'cruser_id', + 'languageField' => 'sys_language_uid', + 'transOrigPointerField' => 'l10n_parent', + 'transOrigDiffSourceField' => 'l10n_diffsource', + 'default_sortby' => 'ORDER BY title ASC', + 'delete' => 'deleted', + 'enablecolumns' => [ + 'disabled' => 'hidden', + 'starttime' => 'starttime', + 'endtime' => 'endtime', + ], + 'iconfile' => 'EXT:luxletter/Resources/Public/Icons/' . Settings::TABLE_NAME . '.svg', + 'rootLevel' => -1 + ], + 'interface' => [ + 'showRecordFieldList' => 'title,from_email,from_name,reply_email,reply_name,site', + ], + 'types' => [ + '1' => ['showitem' => 'title,from_email,from_name,reply_email,reply_name,site'], + ], + 'columns' => [ + 'title' => [ + 'exclude' => true, + 'label' => 'LLL:EXT:luxletter/Resources/Private/Language/locallang_db.xlf:' + . Settings::TABLE_NAME . '.title', + 'config' => [ + 'type' => 'input', + 'size' => 30, + 'placeholder' => 'Marketing yourdomain.org', + 'eval' => 'required' + ] + ], + 'from_email' => [ + 'exclude' => true, + 'label' => 'LLL:EXT:luxletter/Resources/Private/Language/locallang_db.xlf:' + . Settings::TABLE_NAME . '.from_email', + 'config' => [ + 'type' => 'input', + 'size' => 30, + 'placeholder' => 'marketing@yourdomain.org', + 'eval' => 'required,email' + ] + ], + 'from_name' => [ + 'exclude' => true, + 'label' => 'LLL:EXT:luxletter/Resources/Private/Language/locallang_db.xlf:' + . Settings::TABLE_NAME . '.from_name', + 'config' => [ + 'type' => 'input', + 'size' => 30, + 'placeholder' => 'Marketing', + 'eval' => 'required' + ] + ], + 'reply_email' => [ + 'exclude' => true, + 'label' => 'LLL:EXT:luxletter/Resources/Private/Language/locallang_db.xlf:' + . Settings::TABLE_NAME . '.reply_email', + 'config' => [ + 'type' => 'input', + 'size' => 30, + 'placeholder' => 'sales@yourdomain.org', + 'eval' => 'required,email' + ] + ], + 'reply_name' => [ + 'exclude' => true, + 'label' => 'LLL:EXT:luxletter/Resources/Private/Language/locallang_db.xlf:' + . Settings::TABLE_NAME . '.reply_name', + 'config' => [ + 'type' => 'input', + 'size' => 30, + 'placeholder' => 'Sales', + 'eval' => 'required' + ] + ], + 'site' => [ + 'exclude' => true, + 'label' => 'LLL:EXT:luxletter/Resources/Private/Language/locallang_db.xlf:' + . Settings::TABLE_NAME . '.site', + 'config' => [ + 'type' => 'select', + 'renderType' => 'selectSingle', + 'itemsProcFunc' => \In2code\Luxletter\Tca\SiteSelection::class . '->getAll', + 'itemsProcConfig' => [ + 'table' => 'tt_content' + ], + ] + ] + ] +]; diff --git a/Resources/Private/Language/de.locallang_db.xlf b/Resources/Private/Language/de.locallang_db.xlf index 19217a4a..d4dc06cf 100644 --- a/Resources/Private/Language/de.locallang_db.xlf +++ b/Resources/Private/Language/de.locallang_db.xlf @@ -141,6 +141,35 @@ Ziel + + Settings + Einstellungen + + + Title + Bezeichnung + + + Sender email + Absender E-Mail-Adresse + + + Sender name + Absender Name + + + Reply to email + Antworten E-Mail-Adresse + + + Reply name + Antworten Name + + + Site + Seitenbaum + + Select usergroup which should be removed on unsubscribe Benutzergruppe auswählen, die bei einem Austragen aus dem Newsletter entfernt werden soll diff --git a/Resources/Private/Language/locallang_db.xlf b/Resources/Private/Language/locallang_db.xlf index 11be09f4..563da294 100644 --- a/Resources/Private/Language/locallang_db.xlf +++ b/Resources/Private/Language/locallang_db.xlf @@ -108,6 +108,28 @@ Target + + Settings + + + Title + + + Sender email + + + Sender name + + + Reply to email + + + Reply name + + + Site + + Select usergroup which should be removed on unsubscribe diff --git a/Resources/Private/Templates/Newsletter/List.html b/Resources/Private/Templates/Newsletter/List.html index de18b9c8..743e980d 100644 --- a/Resources/Private/Templates/Newsletter/List.html +++ b/Resources/Private/Templates/Newsletter/List.html @@ -1,6 +1,27 @@ + + + + + + + + + + + + + + + + + +
diff --git a/Resources/Public/Icons/tx_luxletter_domain_model_settings.svg b/Resources/Public/Icons/tx_luxletter_domain_model_settings.svg new file mode 100644 index 00000000..8e2f63dc --- /dev/null +++ b/Resources/Public/Icons/tx_luxletter_domain_model_settings.svg @@ -0,0 +1,3 @@ + + + diff --git a/ext_localconf.php b/ext_localconf.php index 4b434349..334fdf28 100644 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -26,13 +26,13 @@ function () { $GLOBALS['TYPO3_CONF_VARS']['SYS']['fluid']['namespaces']['luxletter'][] = 'In2code\Luxletter\ViewHelpers'; /** - * Add an absRefPrefix for FluidStyledMailContent (but absRefPrefix will be overruled by site configuration) + * Add an absRefPrefix for FluidStyledMailContent (could be overruled by site configuration) */ \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTypoScript( 'luxletterFluidStyledMailContent', 'setup', 'fluidStyledMailContent.config.absRefPrefix = ' - . \In2code\Luxletter\Utility\ConfigurationUtility::getDomain() . '/' + . \In2code\Luxletter\Utility\ConfigurationUtility::getCurrentDomain() ); } ); diff --git a/ext_tables.sql b/ext_tables.sql index 0e3433c5..86f72c4e 100644 --- a/ext_tables.sql +++ b/ext_tables.sql @@ -106,3 +106,28 @@ CREATE TABLE tx_luxletter_domain_model_link ( KEY parent (pid), KEY language (l10n_parent,sys_language_uid) ); + +CREATE TABLE tx_luxletter_domain_model_settings ( + uid int(11) NOT NULL auto_increment, + pid int(11) DEFAULT '0' NOT NULL, + + title varchar(255) DEFAULT '' NOT NULL, + from_email varchar(255) DEFAULT '' NOT NULL, + from_name varchar(255) DEFAULT '' NOT NULL, + reply_email varchar(255) DEFAULT '' NOT NULL, + reply_name varchar(255) DEFAULT '' NOT NULL, + site varchar(255) DEFAULT '' NOT NULL, + + tstamp int(11) unsigned DEFAULT '0' NOT NULL, + crdate int(11) unsigned DEFAULT '0' NOT NULL, + cruser_id int(11) unsigned DEFAULT '0' NOT NULL, + deleted tinyint(4) unsigned DEFAULT '0' NOT NULL, + + sys_language_uid int(11) DEFAULT '0' NOT NULL, + l10n_parent int(11) DEFAULT '0' NOT NULL, + l10n_diffsource mediumblob, + + PRIMARY KEY (uid), + KEY parent (pid), + KEY language (l10n_parent,sys_language_uid) +); From 5b912fe68a97ae9448625319c9061e0ebd543684 Mon Sep 17 00:00:00 2001 From: Alex Kellner Date: Fri, 4 Jun 2021 20:38:27 +0200 Subject: [PATCH 02/14] [FEATURE] Support new configuration in testmails, preview and when saving newsletters In addition I improve UX in newsletter form. Now multiple test mails are possible to send. --- Classes/Command/ClearCommand.php | 4 +- Classes/Controller/FrontendController.php | 7 +- Classes/Controller/NewsletterController.php | 68 +++--- .../Model/{Settings.php => Configuration.php} | 16 +- Classes/Domain/Model/Link.php | 1 + Classes/Domain/Model/Newsletter.php | 23 ++ .../Repository/ConfigurationRepository.php | 18 ++ .../Domain/Repository/SettingsRepository.php | 10 - Classes/Domain/Service/FrontendUrlService.php | 25 +- .../Service/ParseNewsletterUrlService.php | 14 +- Classes/Domain/Service/SiteService.php | 31 +++ Classes/Mail/SendMail.php | 21 +- Classes/Utility/ConfigurationUtility.php | 22 +- Classes/Utility/FrontendUtility.php | 21 ++ Classes/Utility/ObjectUtility.php | 10 + .../Configuration/GetDomainViewHelper.php | 2 +- .../Mail/GetTrackingPixelUrlViewHelper.php | 2 +- .../Mail/GetUnsubscribeUrlViewHelper.php | 31 ++- .../SiteConfiguration/Overrides/sites.php | 11 + ..._luxletter_domain_model_configuration.php} | 18 +- .../tx_luxletter_domain_model_newsletter.php | 20 +- Resources/Private/Build/.nvmrc | 1 + Resources/Private/Build/Toolchain.md | 7 + Resources/Private/JavaScript/Module.js | 31 ++- Resources/Private/Language/de.locallang.xlf | 34 ++- .../Private/Language/de.locallang_db.xlf | 18 +- Resources/Private/Language/locallang.xlf | 21 +- Resources/Private/Language/locallang_db.xlf | 16 +- .../Partials/Newsletter/FormFields.html | 229 +++++++++++------- .../Templates/Mail/NewsletterContainer.html | 2 +- .../Private/Templates/Newsletter/List.html | 20 +- ..._luxletter_domain_model_configuration.svg} | 0 .../Public/JavaScript/Luxletter/Module.min.js | 2 +- ext_localconf.php | 14 +- ext_tables.sql | 3 +- readme.md | 10 + 36 files changed, 528 insertions(+), 255 deletions(-) rename Classes/Domain/Model/{Settings.php => Configuration.php} (90%) create mode 100644 Classes/Domain/Repository/ConfigurationRepository.php delete mode 100644 Classes/Domain/Repository/SettingsRepository.php create mode 100644 Classes/Domain/Service/SiteService.php create mode 100644 Configuration/SiteConfiguration/Overrides/sites.php rename Configuration/TCA/{tx_luxletter_domain_model_settings.php => tx_luxletter_domain_model_configuration.php} (86%) create mode 100644 Resources/Private/Build/.nvmrc create mode 100644 Resources/Private/Build/Toolchain.md rename Resources/Public/Icons/{tx_luxletter_domain_model_settings.svg => tx_luxletter_domain_model_configuration.svg} (100%) diff --git a/Classes/Command/ClearCommand.php b/Classes/Command/ClearCommand.php index bdb6f5f8..d2b5561d 100644 --- a/Classes/Command/ClearCommand.php +++ b/Classes/Command/ClearCommand.php @@ -12,8 +12,8 @@ /** * Class ClearCommand */ -class ClearCommand extends Command { - +class ClearCommand extends Command +{ /** * Configure the command by defining the name, options and arguments */ diff --git a/Classes/Controller/FrontendController.php b/Classes/Controller/FrontendController.php index 05565ce9..b0be29d6 100644 --- a/Classes/Controller/FrontendController.php +++ b/Classes/Controller/FrontendController.php @@ -9,6 +9,7 @@ use In2code\Luxletter\Domain\Repository\UserRepository; use In2code\Luxletter\Domain\Service\LogService; use In2code\Luxletter\Domain\Service\ParseNewsletterUrlService; +use In2code\Luxletter\Domain\Service\SiteService; use In2code\Luxletter\Exception\ArgumentMissingException; use In2code\Luxletter\Exception\AuthenticationFailedException; use In2code\Luxletter\Exception\MissingRelationException; @@ -16,6 +17,7 @@ use In2code\Luxletter\Utility\BackendUserUtility; use In2code\Luxletter\Utility\LocalizationUtility; use In2code\Luxletter\Utility\ObjectUtility; +use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; use TYPO3\CMS\Extbase\Object\Exception; use TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException; @@ -58,8 +60,11 @@ public function initializePreviewAction(): void public function previewAction(string $origin): string { try { + /** @var SiteService $siteService */ + $siteService = GeneralUtility::makeInstance(SiteService::class); + /** @var ParseNewsletterUrlService $urlService */ $urlService = ObjectUtility::getObjectManager()->get(ParseNewsletterUrlService::class, $origin); - return $urlService->getParsedContent(); + return $urlService->getParsedContent($siteService->getSite()); } catch (\Exception $exception) { return 'Origin ' . htmlspecialchars($origin) . ' could not be converted into a valid url!
' . 'Message: ' . $exception->getMessage(); diff --git a/Classes/Controller/NewsletterController.php b/Classes/Controller/NewsletterController.php index f50102fd..1b2ecf89 100644 --- a/Classes/Controller/NewsletterController.php +++ b/Classes/Controller/NewsletterController.php @@ -7,15 +7,17 @@ use In2code\Luxletter\Domain\Factory\UserFactory; use In2code\Luxletter\Domain\Model\Dto\Filter; use In2code\Luxletter\Domain\Model\Newsletter; +use In2code\Luxletter\Domain\Model\Configuration; use In2code\Luxletter\Domain\Model\User; use In2code\Luxletter\Domain\Repository\LogRepository; use In2code\Luxletter\Domain\Repository\NewsletterRepository; -use In2code\Luxletter\Domain\Repository\SettingsRepository; +use In2code\Luxletter\Domain\Repository\ConfigurationRepository; use In2code\Luxletter\Domain\Repository\UserRepository; use In2code\Luxletter\Domain\Service\ParseNewsletterService; use In2code\Luxletter\Domain\Service\ParseNewsletterUrlService; use In2code\Luxletter\Domain\Service\QueueService; use In2code\Luxletter\Domain\Service\ReceiverAnalysisService; +use In2code\Luxletter\Domain\Service\SiteService; use In2code\Luxletter\Exception\AuthenticationFailedException; use In2code\Luxletter\Exception\InvalidUrlException; use In2code\Luxletter\Exception\MisconfigurationException; @@ -77,23 +79,23 @@ class NewsletterController extends ActionController protected $logRepository = null; /** - * @var SettingsRepository + * @var ConfigurationRepository */ - protected $settingsRepository = null; + protected $configurationRepository = null; /** * NewsletterController constructor. * @param NewsletterRepository|null $newsletterRepository * @param UserRepository|null $userRepository * @param LogRepository|null $logRepository - * @param SettingsRepository|null $settingsRepository + * @param ConfigurationRepository|null $configurationRepository * @throws Exception */ public function __construct( NewsletterRepository $newsletterRepository = null, UserRepository $userRepository = null, LogRepository $logRepository = null, - SettingsRepository $settingsRepository = null + ConfigurationRepository $configurationRepository = null ) { $this->newsletterRepository = $newsletterRepository ?: ObjectUtility::getObjectManager()->get( NewsletterRepository::class @@ -102,8 +104,8 @@ public function __construct( UserRepository::class ); $this->logRepository = $logRepository ?: ObjectUtility::getObjectManager()->get(LogRepository::class); - $this->settingsRepository = $settingsRepository ?: ObjectUtility::getObjectManager()->get( - SettingsRepository::class + $this->configurationRepository = $configurationRepository ?: ObjectUtility::getObjectManager()->get( + ConfigurationRepository::class ); } @@ -138,7 +140,7 @@ public function listAction(): void { $this->view->assignMultiple([ 'newsletters' => $this->newsletterRepository->findAll(), - 'luxlettersettings' => $this->settingsRepository->findAll() + 'configurations' => $this->configurationRepository->findAll() ]); } @@ -147,6 +149,9 @@ public function listAction(): void */ public function newAction(): void { + $this->view->assignMultiple([ + 'configurations' => $this->configurationRepository->findAll() + ]); } /** @@ -270,19 +275,12 @@ public function receiverAction(Filter $filter): void /** * @param ServerRequestInterface $request - * @param ResponseInterface $response Todo: Second parameter is removed in TYPO3 10 * @return ResponseInterface * @throws DBALException * @throws Exception */ - public function wizardUserPreviewAjax( - ServerRequestInterface $request, - ResponseInterface $response = null - ): ResponseInterface + public function wizardUserPreviewAjax(ServerRequestInterface $request): ResponseInterface { - if ($response === null) { - $response = ObjectUtility::getObjectManager()->get(JsonResponse::class); - } $userRepository = ObjectUtility::getObjectManager()->get(UserRepository::class); $standaloneView = ObjectUtility::getObjectManager()->get(StandaloneView::class); $standaloneView->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($this->wizardUserPreviewFile)); @@ -290,6 +288,7 @@ public function wizardUserPreviewAjax( 'userPreview' => $userRepository->getUsersFromGroup((int)$request->getQueryParams()['usergroup'], 3), 'userAmount' => $userRepository->getUserAmountFromGroup((int)$request->getQueryParams()['usergroup']) ]); + $response = ObjectUtility::getJsonResponse(); $response->getBody()->write(json_encode( ['html' => $standaloneView->render()] )); @@ -298,7 +297,6 @@ public function wizardUserPreviewAjax( /** * @param ServerRequestInterface $request - * @param ResponseInterface $response Todo: Second parameter is removed in TYPO3 10 * @return ResponseInterface * @throws AuthenticationFailedException * @throws Exception @@ -311,21 +309,23 @@ public function wizardUserPreviewAjax( * @throws MisconfigurationException * @throws TransportExceptionInterface */ - public function testMailAjax( - ServerRequestInterface $request, - ResponseInterface $response = null - ): ResponseInterface { + public function testMailAjax(ServerRequestInterface $request): ResponseInterface + { if (BackendUserUtility::isBackendUserAuthenticated() === false) { throw new AuthenticationFailedException('You are not authenticated to send mails', 1560872725); } - if ($response === null) { - $response = ObjectUtility::getObjectManager()->get(JsonResponse::class); - } + /** @var ParseNewsletterUrlService $parseUrlService */ $parseUrlService = ObjectUtility::getObjectManager()->get( ParseNewsletterUrlService::class, $request->getQueryParams()['origin'] ); + /** @var ParseNewsletterService $parseService */ $parseService = ObjectUtility::getObjectManager()->get(ParseNewsletterService::class); + /** @var ConfigurationRepository $configurationRepository */ + $configurationRepository = ObjectUtility::getObjectManager()->get(ConfigurationRepository::class); + /** @var Configuration $configuration */ + $configuration = $configurationRepository->findByUid($request->getQueryParams()['configuration']); + /** @var UserFactory $userFactory */ $userFactory = ObjectUtility::getObjectManager()->get(UserFactory::class); $user = $userFactory->getDummyUser(); $mailService = ObjectUtility::getObjectManager()->get( @@ -334,26 +334,22 @@ public function testMailAjax( $request->getQueryParams()['subject'], ['user' => $user] ), - $parseUrlService->getParsedContent() + $parseUrlService->getParsedContent($configuration->getSiteConfiguration()), + $configuration ); $status = $mailService->sendNewsletter([$request->getQueryParams()['email'] => $user->getReadableName()]); + $response = ObjectUtility::getJsonResponse(); $response->getBody()->write(json_encode(['status' => $status])); return $response; } /** * @param ServerRequestInterface $request - * @param ResponseInterface $response Todo: Second parameter is removed in TYPO3 10 * @return ResponseInterface * @throws Exception */ - public function receiverDetailAjax( - ServerRequestInterface $request, - ResponseInterface $response = null - ): ResponseInterface { - if ($response === null) { - $response = ObjectUtility::getObjectManager()->get(JsonResponse::class); - } + public function receiverDetailAjax(ServerRequestInterface $request): ResponseInterface + { $userRepository = ObjectUtility::getObjectManager()->get(UserRepository::class); $visitorRepository = ObjectUtility::getObjectManager()->get(VisitorRepository::class); $logRepository = ObjectUtility::getObjectManager()->get(LogRepository::class); @@ -366,6 +362,7 @@ public function receiverDetailAjax( 'visitor' => $visitorRepository->findOneByFrontenduser($user), 'logs' => $logRepository->findByUser($user) ]); + $response = ObjectUtility::getJsonResponse(); $response->getBody()->write(json_encode( ['html' => $standaloneView->render()] )); @@ -404,9 +401,12 @@ protected function setDatetimeObjectInNewsletterRequest(): void protected function parseNewsletterToBodytext(): void { $newsletter = (array)$this->request->getArgument('newsletter'); + /** @var ParseNewsletterUrlService $parseService */ $parseService = ObjectUtility::getObjectManager()->get(ParseNewsletterUrlService::class, $newsletter['origin']); $parseService->setParseVariables(false); - $newsletter['bodytext'] = $parseService->getParsedContent(); + /** @var Configuration $configuration */ + $configuration = $this->configurationRepository->findByUid((int)$newsletter['configuration']); + $newsletter['bodytext'] = $parseService->getParsedContent($configuration->getSiteConfiguration()); $this->request->setArgument('newsletter', $newsletter); } } diff --git a/Classes/Domain/Model/Settings.php b/Classes/Domain/Model/Configuration.php similarity index 90% rename from Classes/Domain/Model/Settings.php rename to Classes/Domain/Model/Configuration.php index b095d196..7fb20dae 100644 --- a/Classes/Domain/Model/Settings.php +++ b/Classes/Domain/Model/Configuration.php @@ -11,9 +11,9 @@ /** * Class Settings */ -class Settings extends AbstractEntity +class Configuration extends AbstractEntity { - const TABLE_NAME = 'tx_luxletter_domain_model_settings'; + const TABLE_NAME = 'tx_luxletter_domain_model_configuration'; /** * @var string @@ -55,7 +55,7 @@ public function getTitle(): string /** * @param string $title - * @return Settings + * @return Configuration */ public function setTitle(string $title): self { @@ -73,7 +73,7 @@ public function getFromEmail(): string /** * @param string $fromEmail - * @return Settings + * @return Configuration */ public function setFromEmail(string $fromEmail): self { @@ -91,7 +91,7 @@ public function getFromName(): string /** * @param string $fromName - * @return Settings + * @return Configuration */ public function setFromName(string $fromName): self { @@ -109,7 +109,7 @@ public function getReplyEmail(): string /** * @param string $replyEmail - * @return Settings + * @return Configuration */ public function setReplyEmail(string $replyEmail): self { @@ -127,7 +127,7 @@ public function getReplyName(): string /** * @param string $replyName - * @return Settings + * @return Configuration */ public function setReplyName(string $replyName): self { @@ -157,7 +157,7 @@ public function getSiteConfiguration(): Site /** * @param string $site - * @return Settings + * @return Configuration */ public function setSite(string $site): self { diff --git a/Classes/Domain/Model/Link.php b/Classes/Domain/Model/Link.php index 779b152e..93615a7f 100644 --- a/Classes/Domain/Model/Link.php +++ b/Classes/Domain/Model/Link.php @@ -103,6 +103,7 @@ public function setHash(string $hash): self */ public function getUriFromHash(): string { + /** @var FrontendUrlService $urlService */ $urlService = ObjectUtility::getObjectManager()->get(FrontendUrlService::class); return $urlService->getFrontendUrlFromParameter(['luxletterlink' => $this->getHash()]); } diff --git a/Classes/Domain/Model/Newsletter.php b/Classes/Domain/Model/Newsletter.php index 2cea880a..11615c7f 100644 --- a/Classes/Domain/Model/Newsletter.php +++ b/Classes/Domain/Model/Newsletter.php @@ -46,6 +46,11 @@ class Newsletter extends AbstractEntity */ protected $receiver = null; + /** + * @var \In2code\Luxletter\Domain\Model\Configuration + */ + protected $configuration = null; + /** * @var string */ @@ -197,6 +202,24 @@ public function setReceiver(Usergroup $receiver): self return $this; } + /** + * @return Configuration + */ + public function getConfiguration(): Configuration + { + return $this->configuration; + } + + /** + * @param Configuration $configuration + * @return Newsletter + */ + public function setConfiguration(Configuration $configuration): self + { + $this->configuration = $configuration; + return $this; + } + /** * @return string */ diff --git a/Classes/Domain/Repository/ConfigurationRepository.php b/Classes/Domain/Repository/ConfigurationRepository.php new file mode 100644 index 00000000..42fa360b --- /dev/null +++ b/Classes/Domain/Repository/ConfigurationRepository.php @@ -0,0 +1,18 @@ + QueryInterface::ORDER_ASCENDING + ]; +} diff --git a/Classes/Domain/Repository/SettingsRepository.php b/Classes/Domain/Repository/SettingsRepository.php deleted file mode 100644 index 79b91227..00000000 --- a/Classes/Domain/Repository/SettingsRepository.php +++ /dev/null @@ -1,10 +0,0 @@ -getUri($pageIdentifier, $arguments)->getPath(); - if ($arguments !== []) { - $url .= '?' . $this->getUri($pageIdentifier, $arguments)->getQuery(); - } + /** @var Site $site */ + $site = GeneralUtility::makeInstance(SiteFinder::class)->getSiteByPageId($pageIdentifier); + $uri = $site->getRouter()->generateUri($pageIdentifier, $arguments); + $url = $uri->__tostring(); return $url; } @@ -50,19 +50,4 @@ public function getFrontendUrlFromParameter(array $arguments): string $url .= '/?' . http_build_query($arguments); return $url; } - - /** - * Generates an absolute URL for a page (based on Site Handling) - * - * @param int $pageId - * @param array $arguments - * @return UriInterface - * @throws SiteNotFoundException - * @throws InvalidRouteArgumentsException - */ - protected function getUri(int $pageId, array $arguments = []): UriInterface - { - $site = GeneralUtility::makeInstance(SiteFinder::class)->getSiteByPageId($pageId); - return $site->getRouter()->generateUri($pageId, $arguments); - } } diff --git a/Classes/Domain/Service/ParseNewsletterUrlService.php b/Classes/Domain/Service/ParseNewsletterUrlService.php index 8b35b292..00c253a0 100644 --- a/Classes/Domain/Service/ParseNewsletterUrlService.php +++ b/Classes/Domain/Service/ParseNewsletterUrlService.php @@ -11,6 +11,7 @@ use In2code\Luxletter\Utility\ObjectUtility; use In2code\Luxletter\Utility\StringUtility; use In2code\Luxletter\Utility\TemplateUtility; +use TYPO3\CMS\Core\Site\Entity\Site; use TYPO3\CMS\Core\TypoScript\TypoScriptService; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\MathUtility; @@ -76,6 +77,7 @@ public function __construct(string $origin) } /** + * @param Site $site * @param User|null $user * @return string * @throws Exception @@ -85,28 +87,29 @@ public function __construct(string $origin) * @throws InvalidUrlException * @throws MisconfigurationException */ - public function getParsedContent(User $user = null): string + public function getParsedContent(Site $site, User $user = null): string { if ($user === null) { $userFactory = ObjectUtility::getObjectManager()->get(UserFactory::class); $user = $userFactory->getDummyUser(); } $this->signalDispatch(__CLASS__, __FUNCTION__ . 'BeforeParsing', [$user, $this]); - $content = $this->getNewsletterContainerAndContent($this->getContentFromOrigin($user), $user); + $content = $this->getNewsletterContainerAndContent($this->getContentFromOrigin($user), $site, $user); $this->signalDispatch(__CLASS__, __FUNCTION__ . 'AfterParsing', [$content, $this]); return $content; } /** * @param string $content + * @param Site $site * @param User $user * @return string + * @throws Exception + * @throws InvalidConfigurationTypeException * @throws InvalidSlotException * @throws InvalidSlotReturnException - * @throws InvalidConfigurationTypeException - * @throws Exception */ - protected function getNewsletterContainerAndContent(string $content, User $user): string + protected function getNewsletterContainerAndContent(string $content, Site $site, User $user): string { $templateName = 'Mail/NewsletterContainer.html'; if ($this->isParsingActive()) { @@ -121,6 +124,7 @@ protected function getNewsletterContainerAndContent(string $content, User $user) [ 'content' => $content, 'user' => $user, + 'site' => $site, 'settings' => $configuration['settings'] ?? [] ] ); diff --git a/Classes/Domain/Service/SiteService.php b/Classes/Domain/Service/SiteService.php new file mode 100644 index 00000000..d33a94fd --- /dev/null +++ b/Classes/Domain/Service/SiteService.php @@ -0,0 +1,31 @@ + 0) { + /** @var SiteFinder $siteFinder */ + $siteFinder = GeneralUtility::makeInstance(SiteFinder::class); + return $siteFinder->getSiteByPageId($pageIdentifier); + } else { + throw new \LogicException('Not in frontend context? No page identifier given.', 1622813408); + } + } +} diff --git a/Classes/Mail/SendMail.php b/Classes/Mail/SendMail.php index 653bc7ae..450f5701 100644 --- a/Classes/Mail/SendMail.php +++ b/Classes/Mail/SendMail.php @@ -2,12 +2,14 @@ declare(strict_types=1); namespace In2code\Luxletter\Mail; +use In2code\Luxletter\Domain\Model\Configuration; use In2code\Luxletter\Signal\SignalTrait; use In2code\Luxletter\Utility\ConfigurationUtility; use In2code\Luxletter\Utility\ObjectUtility; use Symfony\Component\Mailer\Exception\TransportExceptionInterface; use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationExtensionNotConfiguredException; use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationPathDoesNotExistException; +use TYPO3\CMS\Core\Site\Entity\Site; use TYPO3\CMS\Extbase\Object\Exception; use TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotException; use TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotReturnException; @@ -30,14 +32,21 @@ class SendMail protected $bodytext = ''; /** - * MailService constructor. + * @var Configuration|null + */ + protected $configuration = null; + + /** + * SendMail constructor. * @param string $subject * @param string $bodytext + * @param Configuration $configuration */ - public function __construct(string $subject, string $bodytext) + public function __construct(string $subject, string $bodytext, Configuration $configuration) { $this->subject = $subject; $this->bodytext = $bodytext; + $this->configuration = $configuration; } /** @@ -80,8 +89,8 @@ protected function send(array $receiver): bool $mailMessage = ObjectUtility::getObjectManager()->get(MailMessage::class); $mailMessage ->setTo($receiver) - ->setFrom([ConfigurationUtility::getFromEmail() => ConfigurationUtility::getFromName()]) - ->setReplyTo([ConfigurationUtility::getReplyEmail() => ConfigurationUtility::getReplyName()]) + ->setFrom([$this->configuration->getFromEmail() => $this->configuration->getFromName()]) + ->setReplyTo([$this->configuration->getReplyEmail() => $this->configuration->getReplyName()]) ->setSubject($this->subject) ->html($this->bodytext); $this->signalDispatch(__CLASS__, __FUNCTION__ . 'mailMessage', [$mailMessage, &$send, $receiver, $this]); @@ -112,8 +121,8 @@ protected function sendLegacy(array $receiver): bool $mailMessage = ObjectUtility::getObjectManager()->get(MailMessageLegacy::class); $mailMessage ->setTo($receiver) - ->setFrom([ConfigurationUtility::getFromEmail() => ConfigurationUtility::getFromName()]) - ->setReplyTo([ConfigurationUtility::getReplyEmail() => ConfigurationUtility::getReplyName()]) + ->setFrom([$this->configuration->getFromEmail() => $this->configuration->getFromName()]) + ->setReplyTo([$this->configuration->getReplyEmail() => $this->configuration->getReplyName()]) ->setSubject($this->subject) ->setBody($this->bodytext, 'text/html'); $this->signalDispatch(__CLASS__, __FUNCTION__ . 'mailMessageLegacy', [$mailMessage, &$send, $receiver, $this]); diff --git a/Classes/Utility/ConfigurationUtility.php b/Classes/Utility/ConfigurationUtility.php index c7a005ec..bd5d91d8 100644 --- a/Classes/Utility/ConfigurationUtility.php +++ b/Classes/Utility/ConfigurationUtility.php @@ -35,7 +35,7 @@ public static function getExtensionSettings(): array */ public static function getDomain(): string { - throw new \LogicException('This function must be replaced by site configuration'); + throw new \LogicException('This function must be replaced by site configuration: ' . __FUNCTION__); $domain = (string)GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('luxletter', 'domain'); return rtrim($domain, '/'); } @@ -45,20 +45,14 @@ public static function getDomain(): string */ public static function getCurrentDomain(): string { + if (GeneralUtility::getIndpEnv('HTTP_HOST') === 'null') { + throw new \LogicException(__FUNCTION__ . ' must not be called from CLI context', 1622812071); + } $uri = parse_url(GeneralUtility::getIndpEnv('TYPO3_REQUEST_URL'), PHP_URL_SCHEME); $uri .= '://' . GeneralUtility::getIndpEnv('HTTP_HOST') . '/'; return $uri; } - /** - * @return int - */ - public static function getPidUnsubscribe(): int - { - throw new \LogicException('This function must be replaced by site configuration'); - return (int)GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('luxletter', 'pidUnsubscribe'); - } - /** * @return bool */ @@ -92,7 +86,7 @@ public static function isReceiverActionActivated(): bool */ public static function getFromEmail(): string { - throw new \LogicException('This function must be replaced by settings domain model'); + throw new \LogicException('This function must be replaced by settings domain model: ' . __FUNCTION__); return (string)GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('luxletter', 'fromEmail'); } @@ -101,7 +95,7 @@ public static function getFromEmail(): string */ public static function getFromName(): string { - throw new \LogicException('This function must be replaced by settings domain model'); + throw new \LogicException('This function must be replaced by settings domain model: ' . __FUNCTION__); return (string)GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('luxletter', 'fromName'); } @@ -110,7 +104,7 @@ public static function getFromName(): string */ public static function getReplyEmail(): string { - throw new \LogicException('This function must be replaced by settings domain model'); + throw new \LogicException('This function must be replaced by settings domain model: ' . __FUNCTION__); return (string)GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('luxletter', 'replyEmail'); } @@ -119,7 +113,7 @@ public static function getReplyEmail(): string */ public static function getReplyName(): string { - throw new \LogicException('This function must be replaced by settings domain model'); + throw new \LogicException('This function must be replaced by settings domain model: ' . __FUNCTION__); return (string)GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('luxletter', 'replyName'); } diff --git a/Classes/Utility/FrontendUtility.php b/Classes/Utility/FrontendUtility.php index 83b0d5e4..d9730b5e 100644 --- a/Classes/Utility/FrontendUtility.php +++ b/Classes/Utility/FrontendUtility.php @@ -3,6 +3,7 @@ namespace In2code\Luxletter\Utility; use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController; /** * Class FrontendUtility @@ -23,6 +24,17 @@ public static function getCurrentUri(): string $uri .= rtrim(GeneralUtility::getIndpEnv('TYPO3_SITE_PATH'), '/'); return $uri; } + /** + * @return int + */ + public static function getCurrentPageIdentifier(): int + { + $tsfe = self::getTyposcriptFrontendController(); + if ($tsfe !== null) { + return (int)$tsfe->id; + } + return 0; + } /** * @return string @@ -58,4 +70,13 @@ public static function getPluginName(): string { return 'tx_luxletter_lux_luxletterluxletter'; } + + /** + * @return TypoScriptFrontendController + * @SuppressWarnings(PHPMD.Superglobals) + */ + protected static function getTyposcriptFrontendController(): ?TypoScriptFrontendController + { + return $GLOBALS['TSFE'] ?: null; + } } diff --git a/Classes/Utility/ObjectUtility.php b/Classes/Utility/ObjectUtility.php index 9e950b06..2e100efe 100644 --- a/Classes/Utility/ObjectUtility.php +++ b/Classes/Utility/ObjectUtility.php @@ -2,6 +2,7 @@ declare(strict_types=1); namespace In2code\Luxletter\Utility; +use TYPO3\CMS\Core\Http\JsonResponse; use TYPO3\CMS\Core\Utility\GeneralUtility; use \TYPO3\CMS\Core\Configuration\ConfigurationManager as ConfigurationManagerCore; use TYPO3\CMS\Extbase\Configuration\ConfigurationManager; @@ -53,4 +54,13 @@ public static function getContentObject(): ContentObjectRenderer { return self::getObjectManager()->get(ContentObjectRenderer::class); } + + /** + * @return JsonResponse + * @throws Exception + */ + public static function getJsonResponse(): JsonResponse + { + return self::getObjectManager()->get(JsonResponse::class); + } } diff --git a/Classes/ViewHelpers/Configuration/GetDomainViewHelper.php b/Classes/ViewHelpers/Configuration/GetDomainViewHelper.php index 9d346870..8b0b5d28 100644 --- a/Classes/ViewHelpers/Configuration/GetDomainViewHelper.php +++ b/Classes/ViewHelpers/Configuration/GetDomainViewHelper.php @@ -22,6 +22,6 @@ class GetDomainViewHelper extends AbstractViewHelper */ public function render(): string { - return ConfigurationUtility::getDomain(); + return ConfigurationUtility::getCurrentDomain(); } } diff --git a/Classes/ViewHelpers/Mail/GetTrackingPixelUrlViewHelper.php b/Classes/ViewHelpers/Mail/GetTrackingPixelUrlViewHelper.php index 3912c99b..85136fbb 100644 --- a/Classes/ViewHelpers/Mail/GetTrackingPixelUrlViewHelper.php +++ b/Classes/ViewHelpers/Mail/GetTrackingPixelUrlViewHelper.php @@ -34,7 +34,7 @@ public function initializeArguments(): void */ public function render(): string { - $url = ConfigurationUtility::getDomain(); + $url = ConfigurationUtility::getCurrentDomain(); $url .= '/?type=1561894816'; $url .= '&tx_luxletter_fe[user]=' . $this->getUserIdentifier(); $url .= '&tx_luxletter_fe[newsletter]=' . $this->getNewsletterIdentifier(); diff --git a/Classes/ViewHelpers/Mail/GetUnsubscribeUrlViewHelper.php b/Classes/ViewHelpers/Mail/GetUnsubscribeUrlViewHelper.php index 0420bb4a..93178bb1 100644 --- a/Classes/ViewHelpers/Mail/GetUnsubscribeUrlViewHelper.php +++ b/Classes/ViewHelpers/Mail/GetUnsubscribeUrlViewHelper.php @@ -7,12 +7,15 @@ use In2code\Luxletter\Domain\Service\FrontendUrlService; use In2code\Luxletter\Exception\MisconfigurationException; use In2code\Luxletter\Exception\UserValuesAreMissingException; -use In2code\Luxletter\Utility\ConfigurationUtility; +use In2code\Luxletter\Utility\FrontendUtility; use In2code\Luxletter\Utility\ObjectUtility; use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationExtensionNotConfiguredException; use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationPathDoesNotExistException; use TYPO3\CMS\Core\Exception\SiteNotFoundException; use TYPO3\CMS\Core\Routing\InvalidRouteArgumentsException; +use TYPO3\CMS\Core\Site\Entity\Site; +use TYPO3\CMS\Core\Site\SiteFinder; +use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Object\Exception; use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper; @@ -28,8 +31,9 @@ class GetUnsubscribeUrlViewHelper extends AbstractViewHelper public function initializeArguments(): void { parent::initializeArguments(); - $this->registerArgument('newsletter', Newsletter::class, 'Newsletter', false, null); - $this->registerArgument('user', User::class, 'User', false, null); + $this->registerArgument('newsletter', Newsletter::class, 'Newsletter object', false, null); + $this->registerArgument('user', User::class, 'User object', false, null); + $this->registerArgument('site', Site::class, 'Site object', true); } /** @@ -44,9 +48,10 @@ public function initializeArguments(): void */ public function render(): string { + /** @var FrontendUrlService $frontendUrlService */ $frontendUrlService = ObjectUtility::getObjectManager()->get(FrontendUrlService::class); $url = $frontendUrlService->getTypolinkUrlFromParameter( - ConfigurationUtility::getPidUnsubscribe(), + $this->getPidUnsubscribe(), [ 'tx_luxletter_fe' => [ 'user' => $this->getUserIdentifier(), @@ -58,6 +63,24 @@ public function render(): string return $url; } + /** + * @return int + * @throws MisconfigurationException + * @throws SiteNotFoundException + */ + protected function getPidUnsubscribe(): int + { + $site = $this->arguments['site']; + $unsubscribePid = (int)$site->getConfiguration()['luxletterUnsubscribePid']; + if ($unsubscribePid === 0) { + throw new MisconfigurationException( + 'No unsubscribe page identifier found in site configuration', + 1622811392 + ); + } + return $unsubscribePid; + } + /** * @return int */ diff --git a/Configuration/SiteConfiguration/Overrides/sites.php b/Configuration/SiteConfiguration/Overrides/sites.php new file mode 100644 index 00000000..2f0d6d53 --- /dev/null +++ b/Configuration/SiteConfiguration/Overrides/sites.php @@ -0,0 +1,11 @@ + 'Unsubscribe PID', + 'description' => 'IMPORTANT: "Entry Point" in tab "General" must not contain a simple "/" but a full domain name like "https://domain.org/" to allow Luxletter to create url from CLI context!', + 'config' => [ + 'type' => 'input', + 'eval' => 'required', + ], +]; + +$GLOBALS['SiteConfiguration']['site']['types']['0']['showitem'] .= ', --div--;Luxletter, luxletterUnsubscribePid'; diff --git a/Configuration/TCA/tx_luxletter_domain_model_settings.php b/Configuration/TCA/tx_luxletter_domain_model_configuration.php similarity index 86% rename from Configuration/TCA/tx_luxletter_domain_model_settings.php rename to Configuration/TCA/tx_luxletter_domain_model_configuration.php index 04e8998a..c400fd75 100644 --- a/Configuration/TCA/tx_luxletter_domain_model_settings.php +++ b/Configuration/TCA/tx_luxletter_domain_model_configuration.php @@ -1,9 +1,9 @@ [ - 'title' => 'LLL:EXT:luxletter/Resources/Private/Language/locallang_db.xlf:' . Settings::TABLE_NAME, + 'title' => 'LLL:EXT:luxletter/Resources/Private/Language/locallang_db.xlf:' . Configuration::TABLE_NAME, 'label' => 'title', 'tstamp' => 'tstamp', 'crdate' => 'crdate', @@ -18,7 +18,7 @@ 'starttime' => 'starttime', 'endtime' => 'endtime', ], - 'iconfile' => 'EXT:luxletter/Resources/Public/Icons/' . Settings::TABLE_NAME . '.svg', + 'iconfile' => 'EXT:luxletter/Resources/Public/Icons/' . Configuration::TABLE_NAME . '.svg', 'rootLevel' => -1 ], 'interface' => [ @@ -31,7 +31,7 @@ 'title' => [ 'exclude' => true, 'label' => 'LLL:EXT:luxletter/Resources/Private/Language/locallang_db.xlf:' - . Settings::TABLE_NAME . '.title', + . Configuration::TABLE_NAME . '.title', 'config' => [ 'type' => 'input', 'size' => 30, @@ -42,7 +42,7 @@ 'from_email' => [ 'exclude' => true, 'label' => 'LLL:EXT:luxletter/Resources/Private/Language/locallang_db.xlf:' - . Settings::TABLE_NAME . '.from_email', + . Configuration::TABLE_NAME . '.from_email', 'config' => [ 'type' => 'input', 'size' => 30, @@ -53,7 +53,7 @@ 'from_name' => [ 'exclude' => true, 'label' => 'LLL:EXT:luxletter/Resources/Private/Language/locallang_db.xlf:' - . Settings::TABLE_NAME . '.from_name', + . Configuration::TABLE_NAME . '.from_name', 'config' => [ 'type' => 'input', 'size' => 30, @@ -64,7 +64,7 @@ 'reply_email' => [ 'exclude' => true, 'label' => 'LLL:EXT:luxletter/Resources/Private/Language/locallang_db.xlf:' - . Settings::TABLE_NAME . '.reply_email', + . Configuration::TABLE_NAME . '.reply_email', 'config' => [ 'type' => 'input', 'size' => 30, @@ -75,7 +75,7 @@ 'reply_name' => [ 'exclude' => true, 'label' => 'LLL:EXT:luxletter/Resources/Private/Language/locallang_db.xlf:' - . Settings::TABLE_NAME . '.reply_name', + . Configuration::TABLE_NAME . '.reply_name', 'config' => [ 'type' => 'input', 'size' => 30, @@ -86,7 +86,7 @@ 'site' => [ 'exclude' => true, 'label' => 'LLL:EXT:luxletter/Resources/Private/Language/locallang_db.xlf:' - . Settings::TABLE_NAME . '.site', + . Configuration::TABLE_NAME . '.site', 'config' => [ 'type' => 'select', 'renderType' => 'selectSingle', diff --git a/Configuration/TCA/tx_luxletter_domain_model_newsletter.php b/Configuration/TCA/tx_luxletter_domain_model_newsletter.php index 34335bb0..aa3f5661 100644 --- a/Configuration/TCA/tx_luxletter_domain_model_newsletter.php +++ b/Configuration/TCA/tx_luxletter_domain_model_newsletter.php @@ -23,10 +23,10 @@ 'rootLevel' => -1 ], 'interface' => [ - 'showRecordFieldList' => 'disabled,title,description,datetime,subject,receiver,origin,bodytext', + 'showRecordFieldList' => 'disabled,title,description,datetime,subject,receiver,configuration,origin,bodytext', ], 'types' => [ - '1' => ['showitem' => 'disabled,title,description,datetime,subject,receiver,origin,bodytext'], + '1' => ['showitem' => 'disabled,title,description,datetime,subject,receiver,configuration,origin,bodytext'], ], 'columns' => [ 'disabled' => [ @@ -98,6 +98,22 @@ 'readOnly' => true ] ], + 'configuration' => [ + 'exclude' => true, + 'label' => 'LLL:EXT:luxletter/Resources/Private/Language/locallang_db.xlf:' + . Newsletter::TABLE_NAME . '.configuration', + 'config' => [ + 'type' => 'select', + 'renderType' => 'selectSingle', + 'items' => [ + ['', 0], + ], + 'foreign_table' => \In2code\Luxletter\Domain\Model\Configuration::TABLE_NAME, + 'foreign_table_where' => 'AND 1', + 'default' => 0, + 'readOnly' => true + ] + ], 'origin' => [ 'exclude' => true, 'label' => 'LLL:EXT:luxletter/Resources/Private/Language/locallang_db.xlf:' diff --git a/Resources/Private/Build/.nvmrc b/Resources/Private/Build/.nvmrc new file mode 100644 index 00000000..b4de3947 --- /dev/null +++ b/Resources/Private/Build/.nvmrc @@ -0,0 +1 @@ +11 diff --git a/Resources/Private/Build/Toolchain.md b/Resources/Private/Build/Toolchain.md new file mode 100644 index 00000000..17d79c64 --- /dev/null +++ b/Resources/Private/Build/Toolchain.md @@ -0,0 +1,7 @@ +# Frontend toolchain + +To compress JS and CSS files, goto EXT:luxletter/Resources/Private/Build and fire this comands: + +* `nvm use` +* `npm i` +* `./node_modules/gulp/bin/gulp.js default` diff --git a/Resources/Private/JavaScript/Module.js b/Resources/Private/JavaScript/Module.js index b58a423a..36bb31ce 100644 --- a/Resources/Private/JavaScript/Module.js +++ b/Resources/Private/JavaScript/Module.js @@ -62,6 +62,8 @@ define(['jquery'], function($) { hideElement(fieldsets[k]); } showElement(fieldsets[step-1]); + + showIfNewsletterIsReady(); }); } }; @@ -138,11 +140,13 @@ define(['jquery'], function($) { var origin = document.querySelector('[data-luxletter-wizardpreviewevent="newsletter"]').value; var email = document.querySelector('[data-luxletter-testmail="email"]').value; var subject = document.querySelector('[data-luxletter-testmail="subject"]').value; + var configuration = document.querySelector('[data-luxletter-testmail="configuration"]').value; if (origin && email && subject) { ajaxConnection(TYPO3.settings.ajaxUrls['/luxletter/testMail'], { origin: origin, email: email, subject: subject, + configuration: configuration }, 'testMailListenerCallback'); } }); @@ -202,10 +206,6 @@ define(['jquery'], function($) { if (messageElement !== null) { showElement(messageElement); } - var fieldElements = document.querySelector('[data-luxletter-testmail="fields"]'); - if (fieldElements !== null) { - hideElement(fieldElements); - } }; /** @@ -246,10 +246,14 @@ define(['jquery'], function($) { * @returns {void} */ var showIfNewsletterIsReady = function() { - if (isNewsletterReady()) { - var statusElements = document.querySelectorAll('[data-luxletter-wizardstatus="ready"]'); + if (isNewsletterReady() && areAllMandatoryFieldsFilled()) { + var statusElements = document.querySelectorAll('[data-luxletter-wizardstatus]'); for (var i = 0; i < statusElements.length; i++) { - showElement(statusElements[i]); + if (statusElements[i].getAttribute('data-luxletter-wizardstatus') === 'ready') { + showElement(statusElements[i]); + } else if (statusElements[i].getAttribute('data-luxletter-wizardstatus') === 'pending') { + hideElement(statusElements[i]); + } } } }; @@ -261,6 +265,19 @@ define(['jquery'], function($) { return newsletterPreview && userPreview; }; + /** + * @returns {boolean} + */ + var areAllMandatoryFieldsFilled = function() { + var fields = document.querySelectorAll('[data-luxletter-mandatory]'); + for (var i = 0; i < fields.length; i++) { + if (fields[i].value === 0 || fields[i].value === '') { + return false; + } + } + return true; + }; + /** * Build an uri string for an ajax call together with params from an object * { diff --git a/Resources/Private/Language/de.locallang.xlf b/Resources/Private/Language/de.locallang.xlf index e71af36a..ff201da5 100644 --- a/Resources/Private/Language/de.locallang.xlf +++ b/Resources/Private/Language/de.locallang.xlf @@ -115,6 +115,14 @@ Just create a new one Neuen Newsletter erzeugen + + No configuration yet + Noch keine Konfiguration vorhanden + + + Please create a sender configuration in a sysfolder first + Bitte erstelle zuerst eine Senderkonfiguration in einem Sysfolder + Title Bezeichnung @@ -193,8 +201,8 @@ Du kannst eine kleine Beschreibung für interne Nutzung hinzufügen - Newsletter start - Startdatum + Newsletter start (optional) + Startdatum (optional) Don't send newsletter before this date (empty for sending as soon as possible) @@ -209,20 +217,28 @@ Bitte Betreff für Newsletter eintragen. - Choose a receiver group - Empfänger-Gruppe auswählen + Receiver + Empfänger Please choose a frontend user group. Every user in this group will receive this newsletter. Bitte eine Frontend-Benutzergruppe auswählen. Jeder Benutzer dieser Gruppe wird den Newsletter erhalten. + + Sender + Absender + + + Please choose between your predefined sender settings + Bitte wähle einen von dir zuvor angelegten Senderdatensatz aus + Where is the newsletter located? Wo befindet sich der Newsletter? - Please add the absolute URL (https://domain.org/newsletter/) or a page UID where your former created newsletter is located. Afterwards the newsletter will be parsed and prepared for sending. - Bitte tragen Sie die absolute URL (https://domain.org/newsletter/) oder eine Seiten UID ein zum von Ihnen zuvor erstellten Newsletter ein. Anschließend wird dieser von Luxletter gelesen und für den Versand vorbereitet. + Please add an absolute URL (https://domain.org/newsletter/) or a page UID where your former created newsletter is located. Afterwards the newsletter will be parsed and prepared for sending. + Bitte trage eine absolute URL (https://domain.org/newsletter/) oder eine Seiten-UID zu einem von dir zuvor erstellten Newsletter ein. Anschließend wird diese URL Luxletter gelesen und für den Versand vorbereitet. Send a test mail to yourself @@ -246,7 +262,7 @@ Your test newsletter was sent successfully - Newsletter erfolgreich abgesendet + Test-Newsletter erfolgreich abgesendet Newsletter is not ready yet @@ -260,6 +276,10 @@ Please select an origin for your newsletter Bitte wähle zuerst einen Ursprung für deinen Newsletter + + Please fill all mandatory fields + Bitte zuerst alle Pflichtfelder ausfüllen + Receivers preview Vorschau der Empfängerliste diff --git a/Resources/Private/Language/de.locallang_db.xlf b/Resources/Private/Language/de.locallang_db.xlf index d4dc06cf..00a2ae4c 100644 --- a/Resources/Private/Language/de.locallang_db.xlf +++ b/Resources/Private/Language/de.locallang_db.xlf @@ -141,31 +141,31 @@ Ziel - - Settings - Einstellungen + + Sender configuration + Sender Einstellungen - + Title Bezeichnung - + Sender email Absender E-Mail-Adresse - + Sender name Absender Name - + Reply to email Antworten E-Mail-Adresse - + Reply name Antworten Name - + Site Seitenbaum diff --git a/Resources/Private/Language/locallang.xlf b/Resources/Private/Language/locallang.xlf index 723d2858..eb59ee63 100644 --- a/Resources/Private/Language/locallang.xlf +++ b/Resources/Private/Language/locallang.xlf @@ -87,6 +87,12 @@ Just create a new one + + No configuration yet + + + Please create a sender configuration in a sysfolder first + Title @@ -146,7 +152,7 @@ You can add a small description for internal useage - Newsletter start + Newsletter start (optional) Don't send newsletter before this date (empty for sending as soon as possible) @@ -158,16 +164,22 @@ Choose an email subject for this newsletter. - Choose a receiver group + Receiver Please choose a frontend user group. Every user in this group will receive this newsletter. + + Sender + + + Please choose between your predefined sender settings + Where is the newsletter located? - Please add the absolute URL (https://domain.org/newsletter/) or a page UID where your former created newsletter is located. Afterwards the newsletter will be parsed and prepared for sending. + Please add an absolute URL (https://domain.org/newsletter/) or a page UID where your former created newsletter is located. Afterwards the newsletter will be parsed and prepared for sending. Send a test mail to yourself @@ -196,6 +208,9 @@ Please select an origin for your newsletter + + Please fill all mandatory fields + Receivers preview diff --git a/Resources/Private/Language/locallang_db.xlf b/Resources/Private/Language/locallang_db.xlf index 563da294..d8c94850 100644 --- a/Resources/Private/Language/locallang_db.xlf +++ b/Resources/Private/Language/locallang_db.xlf @@ -108,25 +108,25 @@ Target - - Settings + + Sender configuration - + Title - + Sender email - + Sender name - + Reply to email - + Reply name - + Site diff --git a/Resources/Private/Partials/Newsletter/FormFields.html b/Resources/Private/Partials/Newsletter/FormFields.html index f2aa8d03..ec770144 100644 --- a/Resources/Private/Partials/Newsletter/FormFields.html +++ b/Resources/Private/Partials/Newsletter/FormFields.html @@ -1,47 +1,58 @@
-
- - - - Useful title - -
+
+
+
+ + + + Useful title + +
+
-
- - - - Example description - -
+
+
+ + + + Datetime description + +
+
-
- - - - Datetime description - + +
+
+ + + + Example description + +
+
-
@@ -53,54 +64,87 @@
-
- - - - Email subject - +
+
+
+ + + + Sender description + +
+
+
+
+ + + + Receiver group description + +
+
-
- - - - Receiver group description - -
-
- - - - PID or absolute URL - + +
+
+
+ + + + Email subject + +
+
+
+
+ + + + PID or absolute URL + +
+
+
- + +
@@ -178,6 +232,8 @@

+ +

@@ -196,9 +252,12 @@

+ + - + +
diff --git a/Resources/Private/Templates/Mail/NewsletterContainer.html b/Resources/Private/Templates/Mail/NewsletterContainer.html index 6154b33e..94cfe251 100644 --- a/Resources/Private/Templates/Mail/NewsletterContainer.html +++ b/Resources/Private/Templates/Mail/NewsletterContainer.html @@ -170,7 +170,7 @@

Company newsletter

© Copyright now
needhelp@in2code.de | - Unsubscribe now + Unsubscribe now

diff --git a/Resources/Private/Templates/Newsletter/List.html b/Resources/Private/Templates/Newsletter/List.html index 743e980d..69ceff6f 100644 --- a/Resources/Private/Templates/Newsletter/List.html +++ b/Resources/Private/Templates/Newsletter/List.html @@ -2,25 +2,17 @@ - + - + - - - - -
@@ -117,3 +109,11 @@

+ + + + + diff --git a/Resources/Public/Icons/tx_luxletter_domain_model_settings.svg b/Resources/Public/Icons/tx_luxletter_domain_model_configuration.svg similarity index 100% rename from Resources/Public/Icons/tx_luxletter_domain_model_settings.svg rename to Resources/Public/Icons/tx_luxletter_domain_model_configuration.svg diff --git a/Resources/Public/JavaScript/Luxletter/Module.min.js b/Resources/Public/JavaScript/Luxletter/Module.min.js index 5c5bce96..ff6a8a11 100644 --- a/Resources/Public/JavaScript/Luxletter/Module.min.js +++ b/Resources/Public/JavaScript/Luxletter/Module.min.js @@ -1 +1 @@ -define(["jquery"],function(e){"use strict";function t(e){var t=this,r=!1,n=!1;this.initialize=function(){i(),l(),u(),o(),c(),s(),d()};var l=function(){for(var e=document.querySelectorAll(".wizardform > fieldset"),t=document.querySelectorAll("[data-wizardform-gotostep]"),r=document.querySelectorAll(".wizard > a"),n=1;n fieldset"),t=document.querySelectorAll("[data-wizardform-gotostep]"),r=document.querySelectorAll(".wizard > a"),n=1;n Date: Fri, 4 Jun 2021 21:07:27 +0200 Subject: [PATCH 03/14] [FEATURE] Replace any getDomain() functionality now with a site-based variant That allows us to remove the domain-settings in the ext_conf_template file. --- Classes/Command/QueueCommand.php | 1 - Classes/Domain/Model/Link.php | 8 ++-- Classes/Domain/Service/FrontendUrlService.php | 12 ++--- Classes/Domain/Service/LinkHashingService.php | 13 ++++-- Classes/Domain/Service/SiteService.php | 20 ++++++++ Classes/Mail/ProgressQueue.php | 7 ++- Classes/Utility/ConfigurationUtility.php | 46 ------------------- Classes/Utility/StringUtility.php | 12 +++++ Resources/Private/Language/de.locallang.xlf | 4 +- Resources/Private/Language/locallang.xlf | 2 +- ext_conf_template.txt | 20 -------- 11 files changed, 58 insertions(+), 87 deletions(-) diff --git a/Classes/Command/QueueCommand.php b/Classes/Command/QueueCommand.php index 77adf6c8..c598da96 100644 --- a/Classes/Command/QueueCommand.php +++ b/Classes/Command/QueueCommand.php @@ -7,7 +7,6 @@ use In2code\Luxletter\Mail\ProgressQueue; use In2code\Luxletter\Utility\ObjectUtility; use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; diff --git a/Classes/Domain/Model/Link.php b/Classes/Domain/Model/Link.php index 93615a7f..822da301 100644 --- a/Classes/Domain/Model/Link.php +++ b/Classes/Domain/Model/Link.php @@ -4,10 +4,10 @@ use In2code\Luxletter\Domain\Service\FrontendUrlService; use In2code\Luxletter\Exception\MisconfigurationException; -use In2code\Luxletter\Utility\ObjectUtility; use In2code\Luxletter\Utility\StringUtility; use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationExtensionNotConfiguredException; use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationPathDoesNotExistException; +use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; use TYPO3\CMS\Extbase\Object\Exception; @@ -98,14 +98,14 @@ public function setHash(string $hash): self * @return string * @throws ExtensionConfigurationExtensionNotConfiguredException * @throws ExtensionConfigurationPathDoesNotExistException - * @throws Exception * @throws MisconfigurationException */ public function getUriFromHash(): string { + $site = $this->getNewsletter()->getConfiguration()->getSiteConfiguration(); /** @var FrontendUrlService $urlService */ - $urlService = ObjectUtility::getObjectManager()->get(FrontendUrlService::class); - return $urlService->getFrontendUrlFromParameter(['luxletterlink' => $this->getHash()]); + $urlService = GeneralUtility::makeInstance(FrontendUrlService::class); + return $urlService->getFrontendUrlFromParameter(['luxletterlink' => $this->getHash()], $site); } /** diff --git a/Classes/Domain/Service/FrontendUrlService.php b/Classes/Domain/Service/FrontendUrlService.php index 95774b60..6877a53f 100644 --- a/Classes/Domain/Service/FrontendUrlService.php +++ b/Classes/Domain/Service/FrontendUrlService.php @@ -3,8 +3,6 @@ namespace In2code\Luxletter\Domain\Service; use In2code\Luxletter\Exception\MisconfigurationException; -use In2code\Luxletter\Utility\ConfigurationUtility; -use Psr\Http\Message\UriInterface; use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationExtensionNotConfiguredException; use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationPathDoesNotExistException; use TYPO3\CMS\Core\Exception\SiteNotFoundException; @@ -39,14 +37,14 @@ public function getTypolinkUrlFromParameter(int $pageIdentifier, array $argument /** * @param array $arguments + * @param Site $site * @return string - * @throws ExtensionConfigurationExtensionNotConfiguredException - * @throws ExtensionConfigurationPathDoesNotExistException - * @throws MisconfigurationException */ - public function getFrontendUrlFromParameter(array $arguments): string + public function getFrontendUrlFromParameter(array $arguments, Site $site): string { - $url = ConfigurationUtility::getDomain(); + /** @var SiteService $siteService */ + $siteService = GeneralUtility::makeInstance(SiteService::class); + $url = $siteService->getDomainFromSite($site); $url .= '/?' . http_build_query($arguments); return $url; } diff --git a/Classes/Domain/Service/LinkHashingService.php b/Classes/Domain/Service/LinkHashingService.php index b8d00d05..7d92f94a 100644 --- a/Classes/Domain/Service/LinkHashingService.php +++ b/Classes/Domain/Service/LinkHashingService.php @@ -9,11 +9,12 @@ use In2code\Luxletter\Exception\ArgumentMissingException; use In2code\Luxletter\Exception\MisconfigurationException; use In2code\Luxletter\Signal\SignalTrait; -use In2code\Luxletter\Utility\ConfigurationUtility; use In2code\Luxletter\Utility\ObjectUtility; use In2code\Luxletter\Utility\StringUtility; use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationExtensionNotConfiguredException; use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationPathDoesNotExistException; +use TYPO3\CMS\Core\Exception\SiteNotFoundException; +use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Object\Exception; use TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException; use TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotException; @@ -116,13 +117,17 @@ protected function hashLink(\DOMElement $aTag): void * * @param string $href * @return string - * @throws ExtensionConfigurationExtensionNotConfiguredException - * @throws ExtensionConfigurationPathDoesNotExistException + * @throws MisconfigurationException + * @throws SiteNotFoundException */ protected function convertToAbsoluteHref(string $href): string { if (StringUtility::startsWith($href, '/')) { - $href = ConfigurationUtility::getDomain() . $href; + /** @var SiteService $siteService */ + $siteService = GeneralUtility::makeInstance(SiteService::class); + $href = $siteService->getDomainFromSite( + $this->newsletter->getConfiguration()->getSiteConfiguration() + ) . $href; } return $href; } diff --git a/Classes/Domain/Service/SiteService.php b/Classes/Domain/Service/SiteService.php index d33a94fd..c1d6951e 100644 --- a/Classes/Domain/Service/SiteService.php +++ b/Classes/Domain/Service/SiteService.php @@ -2,7 +2,9 @@ declare(strict_types=1); namespace In2code\Luxletter\Domain\Service; +use In2code\Luxletter\Exception\MisconfigurationException; use In2code\Luxletter\Utility\FrontendUtility; +use In2code\Luxletter\Utility\StringUtility; use TYPO3\CMS\Core\Exception\SiteNotFoundException; use TYPO3\CMS\Core\Site\Entity\Site; use TYPO3\CMS\Core\Site\SiteFinder; @@ -14,6 +16,8 @@ class SiteService { /** + * Get a site from current page identifier. Works only in frontend context (so not when in CLI and BACKEND context) + * * @return Site * @throws SiteNotFoundException */ @@ -28,4 +32,20 @@ public function getSite(): Site throw new \LogicException('Not in frontend context? No page identifier given.', 1622813408); } } + + /** + * @return string "https://www.domain.org/" + * @throws MisconfigurationException + */ + public function getDomainFromSite(Site $site): string + { + $base = $site->getConfiguration()['base']; + if (StringUtility::startsWith($base, 'http') === false || StringUtility::endsWith($base, '/') === false) { + throw new MisconfigurationException( + 'Base settings in site configuration is not in format "https://domain.org/"', + 1622832844 + ); + } + return $base; + } } diff --git a/Classes/Mail/ProgressQueue.php b/Classes/Mail/ProgressQueue.php index 8f07aeae..2e0f36c1 100644 --- a/Classes/Mail/ProgressQueue.php +++ b/Classes/Mail/ProgressQueue.php @@ -111,10 +111,12 @@ public function progress(int $limit = 50): int protected function sendNewsletterToReceiverInQueue(Queue $queue): void { if ($queue->getUser() !== null) { + /** @var SendMail $sendMail */ $sendMail = ObjectUtility::getObjectManager()->get( SendMail::class, $this->getSubject($queue), - $this->getBodyText($queue) + $this->getBodyText($queue), + $queue->getNewsletter()->getConfiguration() ); $sendMail->sendNewsletter([$queue->getEmail() => $queue->getUser()->getReadableName()]); $logService = ObjectUtility::getObjectManager()->get(LogService::class); @@ -160,7 +162,8 @@ protected function getBodyText(Queue $queue): string $queue->getNewsletter()->getBodytext(), [ 'user' => $queue->getUser(), - 'newsletter' => $queue->getNewsletter() + 'newsletter' => $queue->getNewsletter(), + 'site' => $queue->getNewsletter()->getConfiguration()->getSiteConfiguration() ] ); $bodytext = $this->hashLinksInBodytext($queue, $bodytext); diff --git a/Classes/Utility/ConfigurationUtility.php b/Classes/Utility/ConfigurationUtility.php index bd5d91d8..667c8d6e 100644 --- a/Classes/Utility/ConfigurationUtility.php +++ b/Classes/Utility/ConfigurationUtility.php @@ -30,16 +30,6 @@ public static function getExtensionSettings(): array ); } - /** - * @return string like "https://www.luxletter.de" without trailing slash - */ - public static function getDomain(): string - { - throw new \LogicException('This function must be replaced by site configuration: ' . __FUNCTION__); - $domain = (string)GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('luxletter', 'domain'); - return rtrim($domain, '/'); - } - /** * @return string like "https://www.domain.org/" */ @@ -81,42 +71,6 @@ public static function isReceiverActionActivated(): bool return GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('luxletter', 'receiverAction') === '1'; } - /** - * @return string - */ - public static function getFromEmail(): string - { - throw new \LogicException('This function must be replaced by settings domain model: ' . __FUNCTION__); - return (string)GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('luxletter', 'fromEmail'); - } - - /** - * @return string - */ - public static function getFromName(): string - { - throw new \LogicException('This function must be replaced by settings domain model: ' . __FUNCTION__); - return (string)GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('luxletter', 'fromName'); - } - - /** - * @return string - */ - public static function getReplyEmail(): string - { - throw new \LogicException('This function must be replaced by settings domain model: ' . __FUNCTION__); - return (string)GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('luxletter', 'replyEmail'); - } - - /** - * @return string - */ - public static function getReplyName(): string - { - throw new \LogicException('This function must be replaced by settings domain model: ' . __FUNCTION__); - return (string)GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('luxletter', 'replyName'); - } - /** * @return string * @throws MisconfigurationException diff --git a/Classes/Utility/StringUtility.php b/Classes/Utility/StringUtility.php index 5e431006..383a1514 100644 --- a/Classes/Utility/StringUtility.php +++ b/Classes/Utility/StringUtility.php @@ -29,6 +29,18 @@ public static function startsWith(string $haystack, string $needle): bool return stristr($haystack, $needle) && strrpos($haystack, $needle, -strlen($haystack)) !== false; } + /** + * Check if string ends with another string + * + * @param string $haystack + * @param string $needle + * @return bool + */ + public static function endsWith(string $haystack, string $needle): bool + { + return stristr($haystack, $needle) !== false && substr($haystack, (strlen($needle) * -1)) === $needle; + } + /** * @param array $arguments * @return string diff --git a/Resources/Private/Language/de.locallang.xlf b/Resources/Private/Language/de.locallang.xlf index ff201da5..867728af 100644 --- a/Resources/Private/Language/de.locallang.xlf +++ b/Resources/Private/Language/de.locallang.xlf @@ -213,8 +213,8 @@ E-Mail Betreff - Choose an email subject for this newsletter. - Bitte Betreff für Newsletter eintragen. + Choose an email subject for this newsletter. It's possible to use variables like {user.email} or {user.firstName} + Bitte Betreff für Newsletter eintragen. Variablen können verwendet werden wie bsp {user.email} oder {user.firstName} Receiver diff --git a/Resources/Private/Language/locallang.xlf b/Resources/Private/Language/locallang.xlf index eb59ee63..7ab0db28 100644 --- a/Resources/Private/Language/locallang.xlf +++ b/Resources/Private/Language/locallang.xlf @@ -161,7 +161,7 @@ Mail subject - Choose an email subject for this newsletter. + Choose an email subject for this newsletter. It's possible to use variables like {user.email} or {user.firstName} Receiver diff --git a/ext_conf_template.txt b/ext_conf_template.txt index 04e36538..afb9e119 100644 --- a/ext_conf_template.txt +++ b/ext_conf_template.txt @@ -1,10 +1,3 @@ -# cat=basic//100; type=text; label= Webserver domain: Define a domain for frontend plugins (like opt out for the newsletter, etc...) -domain = https://www.domain.org - -# cat=basic//110; type=int+; label= Unsubscribe PID: Where to find the unsubscribe plugin? Please add the page identifier -pidUnsubscribe = 6 - - # cat=basic//200; type=boolean; label= Rewrite links in newsletter: All absolute links should be rewritten, so a click on a link can be tracked rewriteLinksInNewsletter = 1 @@ -13,16 +6,3 @@ addTypeNumToNumberLocation = 1562349004 # cat=basic//220; type=boolean; label= Show receiver action: show link to receiver view in newsletter module receiverAction = 1 - - -# cat=mail//300; type=text; label= Sender email address: Sender email address for your newsletter (Because of SPF defiance it should be a valid email - given from your mailserver administrator) -fromEmail = newsletter@yourserver.org - -# cat=mail//310; type=text; label= Sender name: Name of the sender for your newsletter -fromName = Sender name - -# cat=mail//320; type=text; label= Reply email address: Real email address of a person that should receive answers to this newsletter email -replyEmail = personal@youremail.org - -# cat=mail//320; type=text; label= Sender name: Name of the sender for your newsletter (mostly the same as fromName) -replyName = Sender name From bddd1e323f285bfe309291741a0c64cf5ebd6dc8 Mon Sep 17 00:00:00 2001 From: Alex Kellner Date: Sat, 5 Jun 2021 11:31:59 +0200 Subject: [PATCH 04/14] [TASK] Code Cleanup Remove technical dept and also drop TYPO3 9 support now --- Classes/Domain/Model/Dto/Filter.php | 12 ++-- Classes/Mail/MailMessage.php | 26 +------ Classes/Mail/MailMessageLegacy.php | 46 ------------- Classes/Mail/SendMail.php | 68 ++----------------- Configuration/Backend/AjaxRoutes.php | 8 ++- Configuration/Extbase/Persistence/Classes.php | 7 +- Configuration/RequestMiddlewares.php | 4 +- Configuration/TCA/Overrides/tt_content.php | 12 ++-- ...x_luxletter_domain_model_configuration.php | 6 +- .../TCA/tx_luxletter_domain_model_link.php | 9 ++- .../TCA/tx_luxletter_domain_model_log.php | 12 ++-- .../tx_luxletter_domain_model_newsletter.php | 12 ++-- .../TCA/tx_luxletter_domain_model_queue.php | 7 +- .../Luxletter/10_TableMapping.typoscript | 17 ----- composer.json | 3 +- ext_emconf.php | 2 +- ext_localconf.php | 8 +-- ext_tables.php | 5 +- 18 files changed, 64 insertions(+), 200 deletions(-) delete mode 100644 Classes/Mail/MailMessageLegacy.php delete mode 100644 Configuration/TypoScript/Basic/Luxletter/10_TableMapping.typoscript diff --git a/Classes/Domain/Model/Dto/Filter.php b/Classes/Domain/Model/Dto/Filter.php index 835c70fb..89e58bdb 100644 --- a/Classes/Domain/Model/Dto/Filter.php +++ b/Classes/Domain/Model/Dto/Filter.php @@ -2,6 +2,8 @@ declare(strict_types=1); namespace In2code\Luxletter\Domain\Model\Dto; +use In2code\Luxletter\Domain\Model\Usergroup; + /** * Class Filter */ @@ -14,7 +16,7 @@ class Filter protected $searchterm = ''; /** - * @var \In2code\Luxletter\Domain\Model\Usergroup + * @var Usergroup */ protected $usergroup = null; @@ -52,18 +54,18 @@ public function setSearchterm(string $searchterm): self } /** - * @return \In2code\Luxletter\Domain\Model\Usergroup + * @return Usergroup */ - public function getUsergroup(): ?\In2code\Luxletter\Domain\Model\Usergroup + public function getUsergroup(): ?Usergroup { return $this->usergroup; } /** - * @param \In2code\Luxletter\Domain\Model\Usergroup $usergroup + * @param Usergroup $usergroup * @return Filter */ - public function setUsergroup(?\In2code\Luxletter\Domain\Model\Usergroup $usergroup): self + public function setUsergroup(?Usergroup $usergroup): self { $this->usergroup = $usergroup; return $this; diff --git a/Classes/Mail/MailMessage.php b/Classes/Mail/MailMessage.php index fdeab20b..1c397d22 100644 --- a/Classes/Mail/MailMessage.php +++ b/Classes/Mail/MailMessage.php @@ -2,7 +2,7 @@ declare(strict_types=1); namespace In2code\Luxletter\Mail; -use Symfony\Component\Mailer\Exception\TransportExceptionInterface; +use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Mail\MailMessage as MailMessageCore; /** @@ -15,28 +15,6 @@ class MailMessage extends MailMessageCore */ private function initializeMailer() { - $this->mailer = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(Mailer::class); - } - - /** - * Sends the message. - * - * This is a short-hand method. It is however more useful to create - * a Mailer instance which can be used via Mailer->send($message); - * - * @return bool whether the message was accepted or not - * @throws TransportExceptionInterface - * Todo: sendMail() can be renamed to send() to overrule parent::send() when T3 9 support is dropped - */ - public function sendMail(): bool - { - $this->initializeMailer(); - $this->sent = false; - $this->mailer->send($this); - $sentMessage = $this->mailer->getSentMessage(); - if ($sentMessage) { - $this->sent = true; - } - return $this->sent; + $this->mailer = GeneralUtility::makeInstance(Mailer::class); } } diff --git a/Classes/Mail/MailMessageLegacy.php b/Classes/Mail/MailMessageLegacy.php deleted file mode 100644 index 8b36452e..00000000 --- a/Classes/Mail/MailMessageLegacy.php +++ /dev/null @@ -1,46 +0,0 @@ -mailer = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(Mailer::class); - } - - /** - * Sends the message and call our initializeMailer() function - * - * @return int the number of recipients who were accepted for delivery - * @throws TransportExceptionInterface - */ - public function sendMail() - { - // Ensure to always have a From: header set - if (empty($this->getFrom())) { - $this->setFrom(MailUtility::getSystemFrom()); - } - if (empty($this->getReplyTo())) { - $replyTo = MailUtility::getSystemReplyTo(); - if (!empty($replyTo)) { - $this->setReplyTo($replyTo); - } - } - $this->initializeMailer(); - $this->sent = true; - $this->getHeaders()->addTextHeader('X-Mailer', $this->mailerHeader); - return $this->mailer->send($this, $this->failedRecipients); - } -} diff --git a/Classes/Mail/SendMail.php b/Classes/Mail/SendMail.php index 450f5701..65d7cafe 100644 --- a/Classes/Mail/SendMail.php +++ b/Classes/Mail/SendMail.php @@ -4,12 +4,10 @@ use In2code\Luxletter\Domain\Model\Configuration; use In2code\Luxletter\Signal\SignalTrait; -use In2code\Luxletter\Utility\ConfigurationUtility; -use In2code\Luxletter\Utility\ObjectUtility; use Symfony\Component\Mailer\Exception\TransportExceptionInterface; use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationExtensionNotConfiguredException; use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationPathDoesNotExistException; -use TYPO3\CMS\Core\Site\Entity\Site; +use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Object\Exception; use TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotException; use TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotReturnException; @@ -60,74 +58,20 @@ public function __construct(string $subject, string $bodytext, Configuration $co * @throws Exception */ public function sendNewsletter(array $receiver): bool - { - if (ConfigurationUtility::isVersionToCompareSameOrLowerThenCurrentTypo3Version('10.0.0')) { - // TYPO3 10 - return $this->send($receiver); - } else { - // TYPO3 9 - return $this->sendLegacy($receiver); - } - } - - /** - * Send with new MailMessage from TYPO3 10 - * - * @param array $receiver - * @return bool - * @throws Exception - * @throws ExtensionConfigurationExtensionNotConfiguredException - * @throws ExtensionConfigurationPathDoesNotExistException - * @throws InvalidSlotException - * @throws InvalidSlotReturnException - * @throws TransportExceptionInterface - */ - protected function send(array $receiver): bool { $send = true; - $this->signalDispatch(__CLASS__, __FUNCTION__ . 'beforeSend', [&$send, $receiver, $this]); - $mailMessage = ObjectUtility::getObjectManager()->get(MailMessage::class); + $this->signalDispatch(__CLASS__, 'sendbeforeSend', [&$send, $receiver, $this]); + /** @var MailMessage $mailMessage */ + $mailMessage = GeneralUtility::makeInstance(MailMessage::class); $mailMessage ->setTo($receiver) ->setFrom([$this->configuration->getFromEmail() => $this->configuration->getFromName()]) ->setReplyTo([$this->configuration->getReplyEmail() => $this->configuration->getReplyName()]) ->setSubject($this->subject) ->html($this->bodytext); - $this->signalDispatch(__CLASS__, __FUNCTION__ . 'mailMessage', [$mailMessage, &$send, $receiver, $this]); - if ($send === true) { - // Todo: Can be renamed to send() when TYPO3 9 support is dropped - return $mailMessage->sendMail(); - } - return false; - } - - /** - * Send with old MailMessage from TYPO3 9 - * - * @param array $receiver - * @return bool - * @throws Exception - * @throws ExtensionConfigurationExtensionNotConfiguredException - * @throws ExtensionConfigurationPathDoesNotExistException - * @throws InvalidSlotException - * @throws InvalidSlotReturnException - * @throws TransportExceptionInterface - * Todo: Can be removed when TYPO3 9 support is dropped - */ - protected function sendLegacy(array $receiver): bool - { - $send = true; - $this->signalDispatch(__CLASS__, __FUNCTION__ . 'beforeSendLegacy', [&$send, $receiver, $this]); - $mailMessage = ObjectUtility::getObjectManager()->get(MailMessageLegacy::class); - $mailMessage - ->setTo($receiver) - ->setFrom([$this->configuration->getFromEmail() => $this->configuration->getFromName()]) - ->setReplyTo([$this->configuration->getReplyEmail() => $this->configuration->getReplyName()]) - ->setSubject($this->subject) - ->setBody($this->bodytext, 'text/html'); - $this->signalDispatch(__CLASS__, __FUNCTION__ . 'mailMessageLegacy', [$mailMessage, &$send, $receiver, $this]); + $this->signalDispatch(__CLASS__, 'sendmailMessage', [$mailMessage, &$send, $receiver, $this]); if ($send === true) { - return $mailMessage->send() > 0; + return $mailMessage->send(); } return false; } diff --git a/Configuration/Backend/AjaxRoutes.php b/Configuration/Backend/AjaxRoutes.php index 1ae03b2e..c8b60b27 100644 --- a/Configuration/Backend/AjaxRoutes.php +++ b/Configuration/Backend/AjaxRoutes.php @@ -1,15 +1,17 @@ [ 'path' => '/luxletter/wizardUserPreview', - 'target' => \In2code\Luxletter\Controller\NewsletterController::class . '::wizardUserPreviewAjax', + 'target' => NewsletterController::class . '::wizardUserPreviewAjax', ], '/luxletter/testMail' => [ 'path' => '/luxletter/testMail', - 'target' => \In2code\Luxletter\Controller\NewsletterController::class . '::testMailAjax', + 'target' => NewsletterController::class . '::testMailAjax', ], '/luxletter/receiverdetail' => [ 'path' => '/luxletter/receiverdetail', - 'target' => \In2code\Luxletter\Controller\NewsletterController::class . '::receiverDetailAjax', + 'target' => NewsletterController::class . '::receiverDetailAjax', ] ]; diff --git a/Configuration/Extbase/Persistence/Classes.php b/Configuration/Extbase/Persistence/Classes.php index 4ec670ac..cfc39d66 100644 --- a/Configuration/Extbase/Persistence/Classes.php +++ b/Configuration/Extbase/Persistence/Classes.php @@ -1,11 +1,14 @@ [ + User::class => [ 'tableName' => 'fe_users' ], - \In2code\Luxletter\Domain\Model\Usergroup::class => [ + Usergroup::class => [ 'tableName' => 'fe_groups' ], ]; diff --git a/Configuration/RequestMiddlewares.php b/Configuration/RequestMiddlewares.php index 2310d46a..cb77fbdd 100644 --- a/Configuration/RequestMiddlewares.php +++ b/Configuration/RequestMiddlewares.php @@ -1,8 +1,10 @@ [ 'luxletter-luxletterlink' => [ - 'target' => \In2code\Luxletter\Middleware\LuxletterLink::class, + 'target' => LuxletterLink::class, 'after' => [ 'typo3/cms-frontend/tsfe' ] diff --git a/Configuration/TCA/Overrides/tt_content.php b/Configuration/TCA/Overrides/tt_content.php index e419cb75..105ba469 100644 --- a/Configuration/TCA/Overrides/tt_content.php +++ b/Configuration/TCA/Overrides/tt_content.php @@ -1,4 +1,8 @@ 'EXT:luxletter/Resources/Public/Icons/' . Configuration::TABLE_NAME . '.svg', 'rootLevel' => -1 ], - 'interface' => [ - 'showRecordFieldList' => 'title,from_email,from_name,reply_email,reply_name,site', - ], 'types' => [ '1' => ['showitem' => 'title,from_email,from_name,reply_email,reply_name,site'], ], @@ -90,7 +88,7 @@ 'config' => [ 'type' => 'select', 'renderType' => 'selectSingle', - 'itemsProcFunc' => \In2code\Luxletter\Tca\SiteSelection::class . '->getAll', + 'itemsProcFunc' => SiteSelection::class . '->getAll', 'itemsProcConfig' => [ 'table' => 'tt_content' ], diff --git a/Configuration/TCA/tx_luxletter_domain_model_link.php b/Configuration/TCA/tx_luxletter_domain_model_link.php index 13d33f8b..6e801335 100644 --- a/Configuration/TCA/tx_luxletter_domain_model_link.php +++ b/Configuration/TCA/tx_luxletter_domain_model_link.php @@ -1,4 +1,6 @@ 'EXT:luxletter/Resources/Public/Icons/' . Link::TABLE_NAME . '.svg', 'rootLevel' => -1 ], - 'interface' => [ - 'showRecordFieldList' => 'newsletter,user,hash,target', - ], 'types' => [ '1' => ['showitem' => 'newsletter,user,hash,target'], ], @@ -35,7 +34,7 @@ 'config' => [ 'type' => 'group', 'internal_type' => 'db', - 'allowed' => \In2code\Luxletter\Domain\Model\Newsletter::TABLE_NAME, + 'allowed' => Newsletter::TABLE_NAME, 'size' => 1, 'maxitems' => 1, 'multiple' => 0, @@ -50,7 +49,7 @@ 'config' => [ 'type' => 'group', 'internal_type' => 'db', - 'allowed' => \In2code\Luxletter\Domain\Model\User::TABLE_NAME, + 'allowed' => User::TABLE_NAME, 'size' => 1, 'maxitems' => 1, 'multiple' => 0, diff --git a/Configuration/TCA/tx_luxletter_domain_model_log.php b/Configuration/TCA/tx_luxletter_domain_model_log.php index 26e6c2fc..d318db7a 100644 --- a/Configuration/TCA/tx_luxletter_domain_model_log.php +++ b/Configuration/TCA/tx_luxletter_domain_model_log.php @@ -1,4 +1,6 @@ 'EXT:luxletter/Resources/Public/Icons/' . Log::TABLE_NAME . '.svg', 'rootLevel' => -1 ], - 'interface' => [ - 'showRecordFieldList' => 'crdate,newsletter,user,status,properties', - ], 'types' => [ '1' => ['showitem' => 'crdate,newsletter,user,status,properties'], ], @@ -35,7 +34,8 @@ 'type' => 'input', 'size' => 30, 'eval' => 'datetime', - 'readOnly' => true + 'readOnly' => true, + 'renderType' => 'inputDateTime' ] ], 'newsletter' => [ @@ -45,7 +45,7 @@ 'config' => [ 'type' => 'group', 'internal_type' => 'db', - 'allowed' => \In2code\Luxletter\Domain\Model\Newsletter::TABLE_NAME, + 'allowed' => Newsletter::TABLE_NAME, 'size' => 1, 'maxitems' => 1, 'multiple' => 0, @@ -60,7 +60,7 @@ 'config' => [ 'type' => 'group', 'internal_type' => 'db', - 'allowed' => \In2code\Luxletter\Domain\Model\User::TABLE_NAME, + 'allowed' => User::TABLE_NAME, 'size' => 1, 'maxitems' => 1, 'multiple' => 0, diff --git a/Configuration/TCA/tx_luxletter_domain_model_newsletter.php b/Configuration/TCA/tx_luxletter_domain_model_newsletter.php index aa3f5661..04a97400 100644 --- a/Configuration/TCA/tx_luxletter_domain_model_newsletter.php +++ b/Configuration/TCA/tx_luxletter_domain_model_newsletter.php @@ -1,4 +1,5 @@ 'EXT:luxletter/Resources/Public/Icons/' . Newsletter::TABLE_NAME . '.svg', 'rootLevel' => -1 ], - 'interface' => [ - 'showRecordFieldList' => 'disabled,title,description,datetime,subject,receiver,configuration,origin,bodytext', - ], 'types' => [ '1' => ['showitem' => 'disabled,title,description,datetime,subject,receiver,configuration,origin,bodytext'], ], 'columns' => [ 'disabled' => [ 'exclude' => true, - 'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.hidden', + 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.hidden', 'config' => [ 'type' => 'check', ], @@ -63,14 +61,14 @@ 'config' => [ 'type' => 'input', 'size' => 13, - 'max' => 20, 'eval' => 'datetime', 'checkbox' => 0, 'default' => 0, 'range' => [ 'lower' => mktime(0, 0, 0, date('m'), date('d'), date('Y')) ], - 'readOnly' => true + 'readOnly' => true, + 'renderType' => 'inputDateTime' ] ], 'subject' => [ @@ -108,7 +106,7 @@ 'items' => [ ['', 0], ], - 'foreign_table' => \In2code\Luxletter\Domain\Model\Configuration::TABLE_NAME, + 'foreign_table' => Configuration::TABLE_NAME, 'foreign_table_where' => 'AND 1', 'default' => 0, 'readOnly' => true diff --git a/Configuration/TCA/tx_luxletter_domain_model_queue.php b/Configuration/TCA/tx_luxletter_domain_model_queue.php index 5c10a5e2..6bd15f47 100644 --- a/Configuration/TCA/tx_luxletter_domain_model_queue.php +++ b/Configuration/TCA/tx_luxletter_domain_model_queue.php @@ -23,9 +23,6 @@ 'iconfile' => 'EXT:luxletter/Resources/Public/Icons/' . Queue::TABLE_NAME . '.svg', 'rootLevel' => -1 ], - 'interface' => [ - 'showRecordFieldList' => 'email,newsletter,user,datetime,sent', - ], 'types' => [ '1' => ['showitem' => 'email,newsletter,user,datetime,sent'], ], @@ -77,14 +74,14 @@ 'config' => [ 'type' => 'input', 'size' => 13, - 'max' => 20, 'eval' => 'datetime', 'checkbox' => 0, 'default' => 0, 'range' => [ 'lower' => mktime(0, 0, 0, date('m'), date('d'), date('Y')) ], - 'readOnly' => true + 'readOnly' => true, + 'renderType' => 'inputDateTime' ] ], 'sent' => [ diff --git a/Configuration/TypoScript/Basic/Luxletter/10_TableMapping.typoscript b/Configuration/TypoScript/Basic/Luxletter/10_TableMapping.typoscript deleted file mode 100644 index 4eaf149c..00000000 --- a/Configuration/TypoScript/Basic/Luxletter/10_TableMapping.typoscript +++ /dev/null @@ -1,17 +0,0 @@ -# Table Mapping (Todo: still needed in TYPO3 9 - can be removed with TYPO3 10 and newer) -config.tx_extbase { - persistence { - classes { - In2code\Luxletter\Domain\Model\User { - mapping { - tableName = fe_users - } - } - In2code\Luxletter\Domain\Model\Usergroup { - mapping { - tableName = fe_groups - } - } - } - } -} diff --git a/composer.json b/composer.json index ffc72c10..a52d6cd1 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ "type": "typo3-cms-extension", "license": "GPL-2.0-or-later", "require": { - "typo3/cms-core": "^9.5 || ^10.4", + "typo3/cms-core": "^10.4", "php": ">=7.2.0", "ext-json": "*", "ext-dom": "*", @@ -61,7 +61,6 @@ }, "extra": { "typo3/cms": { - "cms-package-dir": "{$vendor-dir}/typo3/cms", "web-dir": ".Build/Web", "extension-key": "luxletter" } diff --git a/ext_emconf.php b/ext_emconf.php index 152eb04e..1bec2931 100644 --- a/ext_emconf.php +++ b/ext_emconf.php @@ -11,7 +11,7 @@ 'state' => 'stable', 'constraints' => [ 'depends' => [ - 'typo3' => '9.5.0-10.4.99' + 'typo3' => '10.4.0-10.4.99' ], 'conflicts' => [], 'suggests' => [ diff --git a/ext_localconf.php b/ext_localconf.php index c7556e22..07c45d30 100644 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -10,13 +10,13 @@ function () { * Include Frontend Plugins */ \TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin( - 'In2code.luxletter', + 'Luxletter', 'Fe', [ - 'Frontend' => 'unsubscribe,preview,trackingPixel' + \In2code\Luxletter\Controller\FrontendController::class => 'unsubscribe,preview,trackingPixel' ], [ - 'Frontend' => 'unsubscribe,preview,trackingPixel' + \In2code\Luxletter\Controller\FrontendController::class => 'unsubscribe,preview,trackingPixel' ] ); @@ -26,7 +26,7 @@ function () { $GLOBALS['TYPO3_CONF_VARS']['SYS']['fluid']['namespaces']['luxletter'][] = 'In2code\Luxletter\ViewHelpers'; /** - * Add an absRefPrefix for FluidStyledMailContent (could be overruled by site configuration) + * Add an absRefPrefix for FluidStyledMailContent to prefix images with absolute paths */ if (\TYPO3\CMS\Core\Core\Environment::isCli() === false) { \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTypoScript( diff --git a/ext_tables.php b/ext_tables.php index 892d57e4..7660d142 100644 --- a/ext_tables.php +++ b/ext_tables.php @@ -58,12 +58,13 @@ function () { } // Add module for analysis \TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerModule( - 'In2code.luxletter', + 'Luxletter', 'lux', 'luxletter', '', [ - 'Newsletter' => 'dashboard, list, new, create, enable, disable, delete, receiver', + \In2code\Luxletter\Controller\NewsletterController::class => + 'dashboard, list, new, create, enable, disable, delete, receiver', ], [ 'access' => 'user,group', From 64ccbf9daa6051b02f32660c72a23ba02a26e0f0 Mon Sep 17 00:00:00 2001 From: Alex Kellner Date: Sat, 5 Jun 2021 11:41:18 +0200 Subject: [PATCH 05/14] [FEATURE] Add another comand to clear the complete queue --- Classes/Command/ClearCommand.php | 1 + Classes/Command/ClearQueueCommand.php | 41 +++++++++++++++++++ Classes/Domain/Repository/QueueRepository.php | 13 ++++++ Configuration/Commands.php | 5 +++ 4 files changed, 60 insertions(+) create mode 100644 Classes/Command/ClearQueueCommand.php diff --git a/Classes/Command/ClearCommand.php b/Classes/Command/ClearCommand.php index d2b5561d..33fdafa4 100644 --- a/Classes/Command/ClearCommand.php +++ b/Classes/Command/ClearCommand.php @@ -32,6 +32,7 @@ public function configure() */ protected function execute(InputInterface $input, OutputInterface $output): int { + /** @var NewsletterRepository $newsletterRepository */ $newsletterRepository = ObjectUtility::getObjectManager()->get(NewsletterRepository::class); $newsletterRepository->truncateAll(); $output->writeln('Truncated all luxletter tables!'); diff --git a/Classes/Command/ClearQueueCommand.php b/Classes/Command/ClearQueueCommand.php new file mode 100644 index 00000000..dbe25ca7 --- /dev/null +++ b/Classes/Command/ClearQueueCommand.php @@ -0,0 +1,41 @@ +setDescription('Remove all queued newsletters'); + } + + /** + * Sends a bunch of emails from the queue + * + * @param InputInterface $input + * @param OutputInterface $output + * @return int|null + * @throws Exception + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + /** @var QueueRepository $queueRepository */ + $queueRepository = ObjectUtility::getObjectManager()->get(QueueRepository::class); + $queueRepository->truncate(); + $output->writeln('Truncated queue table!'); + return 0; + } +} diff --git a/Classes/Domain/Repository/QueueRepository.php b/Classes/Domain/Repository/QueueRepository.php index a0a83a9b..5a29b23f 100644 --- a/Classes/Domain/Repository/QueueRepository.php +++ b/Classes/Domain/Repository/QueueRepository.php @@ -83,4 +83,17 @@ public function isUserAndNewsletterAlreadyAddedToQueue(User $user, Newsletter $n ->execute() ->fetchColumn() > 0; } + + /** + * @return void + */ + public function truncate(): void + { + $tables = [ + Queue::TABLE_NAME + ]; + foreach ($tables as $table) { + DatabaseUtility::getConnectionForTable($table)->truncate($table); + } + } } diff --git a/Configuration/Commands.php b/Configuration/Commands.php index 1b409a11..fc0f4763 100644 --- a/Configuration/Commands.php +++ b/Configuration/Commands.php @@ -2,6 +2,7 @@ declare(strict_types=1); use In2code\Luxletter\Command\ClearCommand; +use In2code\Luxletter\Command\ClearQueueCommand; use In2code\Luxletter\Command\QueueCommand; return [ @@ -12,5 +13,9 @@ 'luxletter:clear' => [ 'class' => ClearCommand::class, 'schedulable' => false + ], + 'luxletter:clearqueue' => [ + 'class' => ClearQueueCommand::class, + 'schedulable' => false ] ]; From 5cb6d5786bd31fc93a548219d12d3de39c0549d1 Mon Sep 17 00:00:00 2001 From: Alex Kellner Date: Sat, 5 Jun 2021 11:46:06 +0200 Subject: [PATCH 06/14] [TASK] Don't execute queued but outdated newsletters Newsletters that were generated before 4.0 are without configuration relation. And this would break the new logic. --- Classes/Command/QueueCommand.php | 6 +++--- Classes/Domain/Repository/QueueRepository.php | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Classes/Command/QueueCommand.php b/Classes/Command/QueueCommand.php index c598da96..4189f0b4 100644 --- a/Classes/Command/QueueCommand.php +++ b/Classes/Command/QueueCommand.php @@ -5,7 +5,6 @@ use In2code\Luxletter\Exception\ArgumentMissingException; use In2code\Luxletter\Exception\MisconfigurationException; use In2code\Luxletter\Mail\ProgressQueue; -use In2code\Luxletter\Utility\ObjectUtility; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -13,6 +12,7 @@ use Symfony\Component\Mailer\Exception\TransportExceptionInterface; use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationExtensionNotConfiguredException; use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationPathDoesNotExistException; +use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Configuration\Exception\InvalidConfigurationTypeException; use TYPO3\CMS\Extbase\Object\Exception; use TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException; @@ -26,7 +26,6 @@ */ class QueueCommand extends Command { - /** * Configure the command by defining the name, options and arguments */ @@ -57,7 +56,8 @@ public function configure() */ protected function execute(InputInterface $input, OutputInterface $output): int { - $progressQueue = ObjectUtility::getObjectManager()->get(ProgressQueue::class, $output); + /** @var ProgressQueue $progressQueue */ + $progressQueue = GeneralUtility::makeInstance(ProgressQueue::class, $output); $progressed = $progressQueue->progress((int)$input->getArgument('amount')); if ($progressed > 0) { $output->writeln('Successfully sent ' . $progressed . ' email(s) from the queue...'); diff --git a/Classes/Domain/Repository/QueueRepository.php b/Classes/Domain/Repository/QueueRepository.php index 5a29b23f..ed1be84b 100644 --- a/Classes/Domain/Repository/QueueRepository.php +++ b/Classes/Domain/Repository/QueueRepository.php @@ -27,6 +27,7 @@ public function findDispatchableInQueue(int $limit): QueryResultInterface $query->lessThan('datetime', time()), $query->equals('sent', false), $query->equals('newsletter.disabled', false), + $query->greaterThan('newsletter.configuration', 0), $query->equals('user.deleted', false), $query->equals('user.disable', false) ]; From 09914562916b56f511ca66157ce919577727d5b6 Mon Sep 17 00:00:00 2001 From: Alex Kellner Date: Sat, 5 Jun 2021 13:14:24 +0200 Subject: [PATCH 07/14] [TASK] Newsletter viewhelpers should now also base on a site configuration to create url --- .../Domain/Service/ParseNewsletterService.php | 5 ++-- Classes/Domain/Service/SiteService.php | 3 +++ Classes/Mail/ProgressQueue.php | 3 ++- Classes/Utility/ConfigurationUtility.php | 2 +- .../Configuration/GetDomainViewHelper.php | 25 +++++++++++++------ .../Mail/GetTrackingPixelUrlViewHelper.php | 22 +++++++++++++--- .../Mail/GetUnsubscribeUrlViewHelper.php | 3 --- .../Private/Partials/Mail/TrackingPixel.html | 2 +- .../Templates/Mail/NewsletterContainer.html | 8 +++--- readme.md | 19 +++++++++++--- 10 files changed, 66 insertions(+), 26 deletions(-) diff --git a/Classes/Domain/Service/ParseNewsletterService.php b/Classes/Domain/Service/ParseNewsletterService.php index c881e6d0..e98661cb 100644 --- a/Classes/Domain/Service/ParseNewsletterService.php +++ b/Classes/Domain/Service/ParseNewsletterService.php @@ -4,7 +4,7 @@ use In2code\Luxletter\Signal\SignalTrait; use In2code\Luxletter\Utility\ConfigurationUtility; -use In2code\Luxletter\Utility\ObjectUtility; +use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Configuration\Exception\InvalidConfigurationTypeException; use TYPO3\CMS\Extbase\Object\Exception; use TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotException; @@ -30,7 +30,8 @@ class ParseNewsletterService public function parseMailText(string $bodytext, array $properties): string { $configuration = ConfigurationUtility::getExtensionSettings(); - $standaloneView = ObjectUtility::getObjectManager()->get(StandaloneView::class); + /** @var StandaloneView $standaloneView */ + $standaloneView = GeneralUtility::makeInstance(StandaloneView::class); $standaloneView->setTemplateRootPaths($configuration['view']['templateRootPaths']); $standaloneView->setLayoutRootPaths($configuration['view']['layoutRootPaths']); $standaloneView->setPartialRootPaths($configuration['view']['partialRootPaths']); diff --git a/Classes/Domain/Service/SiteService.php b/Classes/Domain/Service/SiteService.php index c1d6951e..67efc642 100644 --- a/Classes/Domain/Service/SiteService.php +++ b/Classes/Domain/Service/SiteService.php @@ -34,6 +34,9 @@ public function getSite(): Site } /** + * Get a domain from a site configuration that can be used to prefix (e.g.) links or assets in newsletter bodytext + * + * @param Site $site * @return string "https://www.domain.org/" * @throws MisconfigurationException */ diff --git a/Classes/Mail/ProgressQueue.php b/Classes/Mail/ProgressQueue.php index 2e0f36c1..698224ad 100644 --- a/Classes/Mail/ProgressQueue.php +++ b/Classes/Mail/ProgressQueue.php @@ -138,7 +138,8 @@ protected function getSubject(Queue $queue): string $queue->getNewsletter()->getSubject(), [ 'user' => $queue->getUser(), - 'newsletter' => $queue->getNewsletter() + 'newsletter' => $queue->getNewsletter(), + 'site' => $queue->getNewsletter()->getConfiguration()->getSiteConfiguration() ] ); } diff --git a/Classes/Utility/ConfigurationUtility.php b/Classes/Utility/ConfigurationUtility.php index 667c8d6e..755eda2b 100644 --- a/Classes/Utility/ConfigurationUtility.php +++ b/Classes/Utility/ConfigurationUtility.php @@ -35,7 +35,7 @@ public static function getExtensionSettings(): array */ public static function getCurrentDomain(): string { - if (GeneralUtility::getIndpEnv('HTTP_HOST') === 'null') { + if (GeneralUtility::getIndpEnv('HTTP_HOST') === null) { throw new \LogicException(__FUNCTION__ . ' must not be called from CLI context', 1622812071); } $uri = parse_url(GeneralUtility::getIndpEnv('TYPO3_REQUEST_URL'), PHP_URL_SCHEME); diff --git a/Classes/ViewHelpers/Configuration/GetDomainViewHelper.php b/Classes/ViewHelpers/Configuration/GetDomainViewHelper.php index 8b0b5d28..2034b0e9 100644 --- a/Classes/ViewHelpers/Configuration/GetDomainViewHelper.php +++ b/Classes/ViewHelpers/Configuration/GetDomainViewHelper.php @@ -2,10 +2,10 @@ declare(strict_types=1); namespace In2code\Luxletter\ViewHelpers\Configuration; +use In2code\Luxletter\Domain\Service\SiteService; use In2code\Luxletter\Exception\MisconfigurationException; -use In2code\Luxletter\Utility\ConfigurationUtility; -use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationExtensionNotConfiguredException; -use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationPathDoesNotExistException; +use TYPO3\CMS\Core\Site\Entity\Site; +use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper; /** @@ -15,13 +15,24 @@ class GetDomainViewHelper extends AbstractViewHelper { /** - * @return string - * @throws ExtensionConfigurationExtensionNotConfiguredException - * @throws ExtensionConfigurationPathDoesNotExistException + * @return void + */ + public function initializeArguments(): void + { + parent::initializeArguments(); + $this->registerArgument('site', Site::class, 'Site object', true); + } + + /** + * @return string like "https://domain.org/" * @throws MisconfigurationException */ public function render(): string { - return ConfigurationUtility::getCurrentDomain(); + /** @var Site $site */ + $site = $this->arguments['site']; + /** @var SiteService $siteService */ + $siteService = GeneralUtility::makeInstance(SiteService::class); + return $siteService->getDomainFromSite($site); } } diff --git a/Classes/ViewHelpers/Mail/GetTrackingPixelUrlViewHelper.php b/Classes/ViewHelpers/Mail/GetTrackingPixelUrlViewHelper.php index 85136fbb..e15fc449 100644 --- a/Classes/ViewHelpers/Mail/GetTrackingPixelUrlViewHelper.php +++ b/Classes/ViewHelpers/Mail/GetTrackingPixelUrlViewHelper.php @@ -4,10 +4,12 @@ use In2code\Luxletter\Domain\Model\Newsletter; use In2code\Luxletter\Domain\Model\User; +use In2code\Luxletter\Domain\Service\SiteService; use In2code\Luxletter\Exception\MisconfigurationException; -use In2code\Luxletter\Utility\ConfigurationUtility; use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationExtensionNotConfiguredException; use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationPathDoesNotExistException; +use TYPO3\CMS\Core\Site\Entity\Site; +use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper; /** @@ -24,6 +26,7 @@ public function initializeArguments(): void parent::initializeArguments(); $this->registerArgument('newsletter', Newsletter::class, 'Newsletter', false, null); $this->registerArgument('user', User::class, 'User', false, null); + $this->registerArgument('site', Site::class, 'Site object', true); } /** @@ -34,13 +37,26 @@ public function initializeArguments(): void */ public function render(): string { - $url = ConfigurationUtility::getCurrentDomain(); - $url .= '/?type=1561894816'; + $url = $this->getDomainPrefix(); + $url .= '?type=1561894816'; $url .= '&tx_luxletter_fe[user]=' . $this->getUserIdentifier(); $url .= '&tx_luxletter_fe[newsletter]=' . $this->getNewsletterIdentifier(); return $url; } + /** + * @return string + * @throws MisconfigurationException + */ + protected function getDomainPrefix(): string + { + /** @var Site $site */ + $site = $this->arguments['site']; + /** @var SiteService $siteService */ + $siteService = GeneralUtility::makeInstance(SiteService::class); + return $siteService->getDomainFromSite($site); + } + /** * @return int */ diff --git a/Classes/ViewHelpers/Mail/GetUnsubscribeUrlViewHelper.php b/Classes/ViewHelpers/Mail/GetUnsubscribeUrlViewHelper.php index 93178bb1..1b830a93 100644 --- a/Classes/ViewHelpers/Mail/GetUnsubscribeUrlViewHelper.php +++ b/Classes/ViewHelpers/Mail/GetUnsubscribeUrlViewHelper.php @@ -7,15 +7,12 @@ use In2code\Luxletter\Domain\Service\FrontendUrlService; use In2code\Luxletter\Exception\MisconfigurationException; use In2code\Luxletter\Exception\UserValuesAreMissingException; -use In2code\Luxletter\Utility\FrontendUtility; use In2code\Luxletter\Utility\ObjectUtility; use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationExtensionNotConfiguredException; use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationPathDoesNotExistException; use TYPO3\CMS\Core\Exception\SiteNotFoundException; use TYPO3\CMS\Core\Routing\InvalidRouteArgumentsException; use TYPO3\CMS\Core\Site\Entity\Site; -use TYPO3\CMS\Core\Site\SiteFinder; -use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Object\Exception; use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper; diff --git a/Resources/Private/Partials/Mail/TrackingPixel.html b/Resources/Private/Partials/Mail/TrackingPixel.html index af3b4ebb..2271d529 100644 --- a/Resources/Private/Partials/Mail/TrackingPixel.html +++ b/Resources/Private/Partials/Mail/TrackingPixel.html @@ -1,4 +1,4 @@ This pixel is needed to find out if the receiver opens the mail - + diff --git a/Resources/Private/Templates/Mail/NewsletterContainer.html b/Resources/Private/Templates/Mail/NewsletterContainer.html index 94cfe251..d803feae 100644 --- a/Resources/Private/Templates/Mail/NewsletterContainer.html +++ b/Resources/Private/Templates/Mail/NewsletterContainer.html @@ -180,16 +180,16 @@

Company newsletter

- + - + - + - +
diff --git a/readme.md b/readme.md index 63d62e72..56da31f9 100644 --- a/readme.md +++ b/readme.md @@ -103,9 +103,20 @@ composer require "in2code/luxletter" ## Breaking changes !!! -| Version | Situation | Upgrade instructions | -| --------------------------- | --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| From former versions to 4.x | Multiple sender can be defined in records | Add one (ore more) record(s) with sender information on any sysfolder, Update your site configuration with a unsubscribe pid, Create new newsletter records with new configuration | +### Upgrade to 4.x + +Multiple sender can now be defined in records, in addition it's not needed to define a domain in extension configuration +any more. We now look into site configuration. But that change needs you to adjust some stuff. + +Breaking changes in detail and what you have to do step by step after you have updated the extension: + +* Add one (ore more) record(s) with sender information on any sysfolder +* Update your site configuration with an unsubscribe pid (so you could use different unsubscribe plugins now) +* Create new newsletter records with the new sender configuration. **Note:** Old newsletters won't be queued any more because a sender configuration is missing +* Update your HTML template files (compare your files with `EXT:luxletter/Resources/Private/Templates/Mail/NewsletterContainer.html`) + * If you are using the viewhelper `luxletter:mail.getUnsubscribeUrl` now another argument must be passed: `site` - example: `{luxletter:mail.getUnsubscribeUrl(newsletter:newsletter,user:user,site:site)}` + * If you are usint the viewhelper `luxletter:configuration.getDomain` also `site` must be passed as argument - example: `{luxletter:configuration.getDomain(site:site)}` + * If you have changed the TrackingPixel.html partial file, take also care that `site` is now passed to `luxletter:mail.getTrackingPixelUrl` - example: `{luxletter:mail.getTrackingPixelUrl(newsletter:newsletter,user:user,site:site)}` @@ -113,7 +124,7 @@ composer require "in2code/luxletter" | Version | Date | State | Description | | ---------- | ----------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| !!! 4.0.0 | 2021.06.10 | Feature | Multiple sender configuration supported (see breaking changes above) | +| !!! 4.0.0 | 2021.06.10 | Feature | Multiple sender configuration supported (see breaking changes above), Testmails can be send multiple times, TYPO3 9 support finally dropped | | 3.1.4 | 2021.06.04 | Bugfix | Allow rendering of widgets without EXT:lux | | 3.1.3 | 2021.04.29 | Task | Pass arguments in signal as reference | | 3.1.2 | 2021.03.17 | Task | Add extension key to composer.json | From bdf0921d7e684ca0b9aad8d4a3e7306d556d459c Mon Sep 17 00:00:00 2001 From: Alex Kellner Date: Sat, 5 Jun 2021 13:23:45 +0200 Subject: [PATCH 08/14] [TASK] Make labels in ext_conf_template file a bit more understandable --- ext_conf_template.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ext_conf_template.txt b/ext_conf_template.txt index afb9e119..c51cba20 100644 --- a/ext_conf_template.txt +++ b/ext_conf_template.txt @@ -1,8 +1,8 @@ -# cat=basic//200; type=boolean; label= Rewrite links in newsletter: All absolute links should be rewritten, so a click on a link can be tracked +# cat=basic//200; type=boolean; label= Rewrite links in newsletter: Absolute links in your newsletters can be rewritten automatically, to track all link clicks. If you disable this feature, clicks are not tracked. rewriteLinksInNewsletter = 1 -# cat=basic//210; type=int+; label= Add typenum: If you just add a number in newletter backend module to describe on which pid the newsletter is located, this typenum will be added. Note: Typenum will not be added to real urls. +# cat=basic//210; type=int+; label= Add typenum: Everytime you parse a html for a new newsletter, this type will be added (can be used in fluidStyledMailContent). This will work only for PID in origin, not for absolute URL. addTypeNumToNumberLocation = 1562349004 -# cat=basic//220; type=boolean; label= Show receiver action: show link to receiver view in newsletter module +# cat=basic//220; type=boolean; label= Show receiver action: Show link to receiver view in newsletter module. This view is maybe disturbing if you don't use extension lux in addition. receiverAction = 1 From 101b6c3f5c9fa9ff548bb68a3138dd89f64bf5f2 Mon Sep 17 00:00:00 2001 From: Alex Kellner Date: Sat, 5 Jun 2021 13:31:46 +0200 Subject: [PATCH 09/14] [BUGFIX] Avoid double slashes in hashed link --- Classes/Domain/Model/Link.php | 1 - Classes/Domain/Repository/LinkRepository.php | 1 - Classes/Domain/Service/FrontendUrlService.php | 2 +- Classes/Domain/Service/LinkHashingService.php | 2 ++ Classes/Mail/ProgressQueue.php | 4 +++- 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Classes/Domain/Model/Link.php b/Classes/Domain/Model/Link.php index 822da301..cf3d0223 100644 --- a/Classes/Domain/Model/Link.php +++ b/Classes/Domain/Model/Link.php @@ -9,7 +9,6 @@ use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationPathDoesNotExistException; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; -use TYPO3\CMS\Extbase\Object\Exception; /** * Class Link diff --git a/Classes/Domain/Repository/LinkRepository.php b/Classes/Domain/Repository/LinkRepository.php index 4d43d2e8..83f38460 100644 --- a/Classes/Domain/Repository/LinkRepository.php +++ b/Classes/Domain/Repository/LinkRepository.php @@ -11,7 +11,6 @@ */ class LinkRepository extends AbstractRepository { - /** * @param string $hash * @return bool diff --git a/Classes/Domain/Service/FrontendUrlService.php b/Classes/Domain/Service/FrontendUrlService.php index 6877a53f..97056da5 100644 --- a/Classes/Domain/Service/FrontendUrlService.php +++ b/Classes/Domain/Service/FrontendUrlService.php @@ -45,7 +45,7 @@ public function getFrontendUrlFromParameter(array $arguments, Site $site): strin /** @var SiteService $siteService */ $siteService = GeneralUtility::makeInstance(SiteService::class); $url = $siteService->getDomainFromSite($site); - $url .= '/?' . http_build_query($arguments); + $url .= '?' . http_build_query($arguments); return $url; } } diff --git a/Classes/Domain/Service/LinkHashingService.php b/Classes/Domain/Service/LinkHashingService.php index 7d92f94a..3ec1b347 100644 --- a/Classes/Domain/Service/LinkHashingService.php +++ b/Classes/Domain/Service/LinkHashingService.php @@ -99,6 +99,7 @@ protected function hashLink(\DOMElement $aTag): void $href = $this->convertToAbsoluteHref($href); if (StringUtility::isValidUrl($href)) { if ($aTag->getAttribute('data-luxletter-parselink') !== 'false') { + /** @var Link $link */ $link = ObjectUtility::getObjectManager()->get(Link::class) ->setNewsletter($this->newsletter) ->setUser($this->user) @@ -123,6 +124,7 @@ protected function hashLink(\DOMElement $aTag): void protected function convertToAbsoluteHref(string $href): string { if (StringUtility::startsWith($href, '/')) { + $href = ltrim($href, '/'); /** @var SiteService $siteService */ $siteService = GeneralUtility::makeInstance(SiteService::class); $href = $siteService->getDomainFromSite( diff --git a/Classes/Mail/ProgressQueue.php b/Classes/Mail/ProgressQueue.php index 698224ad..f7ff9b64 100644 --- a/Classes/Mail/ProgressQueue.php +++ b/Classes/Mail/ProgressQueue.php @@ -17,6 +17,7 @@ use Symfony\Component\Mailer\Exception\TransportExceptionInterface; use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationExtensionNotConfiguredException; use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationPathDoesNotExistException; +use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Configuration\Exception\InvalidConfigurationTypeException; use TYPO3\CMS\Extbase\Object\Exception; use TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException; @@ -187,7 +188,8 @@ protected function getBodyText(Queue $queue): string protected function hashLinksInBodytext(Queue $queue, string $bodytext): string { if (ConfigurationUtility::isRewriteLinksInNewsletterActivated()) { - $linkHashing = ObjectUtility::getObjectManager()->get( + /** @var LinkHashingService $linkHashing */ + $linkHashing = GeneralUtility::makeInstance( LinkHashingService::class, $queue->getNewsletter(), $queue->getUser() From db177a6b7d1f770c0ec52dcba69126555271be43 Mon Sep 17 00:00:00 2001 From: Alex Kellner Date: Sat, 5 Jun 2021 13:36:10 +0200 Subject: [PATCH 10/14] [TASK] Errormessage for parsing problems should also show the error number now --- Classes/Controller/FrontendController.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Classes/Controller/FrontendController.php b/Classes/Controller/FrontendController.php index b0be29d6..04c8f048 100644 --- a/Classes/Controller/FrontendController.php +++ b/Classes/Controller/FrontendController.php @@ -16,7 +16,6 @@ use In2code\Luxletter\Exception\UserValuesAreMissingException; use In2code\Luxletter\Utility\BackendUserUtility; use In2code\Luxletter\Utility\LocalizationUtility; -use In2code\Luxletter\Utility\ObjectUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; use TYPO3\CMS\Extbase\Object\Exception; @@ -63,11 +62,11 @@ public function previewAction(string $origin): string /** @var SiteService $siteService */ $siteService = GeneralUtility::makeInstance(SiteService::class); /** @var ParseNewsletterUrlService $urlService */ - $urlService = ObjectUtility::getObjectManager()->get(ParseNewsletterUrlService::class, $origin); + $urlService = GeneralUtility::makeInstance(ParseNewsletterUrlService::class, $origin); return $urlService->getParsedContent($siteService->getSite()); } catch (\Exception $exception) { - return 'Origin ' . htmlspecialchars($origin) . ' could not be converted into a valid url!
' - . 'Message: ' . $exception->getMessage(); + return 'Error: Origin ' . htmlspecialchars($origin) . ' could not be converted into a valid url!
' + . 'Reason: ' . $exception->getMessage() . ' (' . $exception->getCode() . ')'; } } From 01c041b1149dd115b46728b89ff743e1c83247e5 Mon Sep 17 00:00:00 2001 From: Alex Kellner Date: Sat, 5 Jun 2021 22:04:54 +0200 Subject: [PATCH 11/14] [FEATURE] Render all links and images with absolute URL in fluidStyledMailContent It turns out that absRefPrefix will only be used for image rendering while parseFunc can be used for links. Nevertheless if you use a viewHelper for linking you have to add absolute="1" by hand. --- .../FluidStyledMailContent/setup.typoscript | 29 ++++++++++++------- .../FluidStyledContent/Templates/Teaser.html | 17 +++++++++-- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/Configuration/TypoScript/FluidStyledMailContent/setup.typoscript b/Configuration/TypoScript/FluidStyledMailContent/setup.typoscript index a0b3a97d..fa31f893 100644 --- a/Configuration/TypoScript/FluidStyledMailContent/setup.typoscript +++ b/Configuration/TypoScript/FluidStyledMailContent/setup.typoscript @@ -1,17 +1,24 @@ -# Fluid Styled Mail Content (needs fluid_styled_content loaded before) +# Fluid Styled Mail Content (needs fluid_styled_content loaded before) for rendering content elements for newsletters [getTSFE().type == 1562349004] -lib.contentElement { - templateRootPaths { - 100 = EXT:luxletter/Resources/Private/FluidStyledMailContent/Templates/ - } - partialRootPaths { - 100 = EXT:luxletter/Resources/Private/FluidStyledMailContent/Partials/ - } - layoutRootPaths { - 100 = EXT:luxletter/Resources/Private/FluidStyledMailContent/Layouts/ + lib.contentElement { + templateRootPaths { + 100 = EXT:luxletter/Resources/Private/FluidStyledMailContent/Templates/ + } + partialRootPaths { + 100 = EXT:luxletter/Resources/Private/FluidStyledMailContent/Partials/ + } + layoutRootPaths { + 100 = EXT:luxletter/Resources/Private/FluidStyledMailContent/Layouts/ + } } -} + + // Use absolute URL for all kind of links within fluidStyledMailContent + // (absRefPrefix is also used for absolute images paths - see ext_localconf.php) + lib.parseFunc.tags.a.typolink.forceAbsoluteUrl = 1 + lib.parseFunc.tags.link.typolink.forceAbsoluteUrl = 1 + lib.parseFunc_RTE.tags.a.typolink.forceAbsoluteUrl = 1 + lib.parseFunc_RTE.tags.link.typolink.forceAbsoluteUrl = 1 [end] fluidStyledMailContent = PAGE diff --git a/Resources/Private/FluidStyledContent/Templates/Teaser.html b/Resources/Private/FluidStyledContent/Templates/Teaser.html index 70460bab..814d3013 100644 --- a/Resources/Private/FluidStyledContent/Templates/Teaser.html +++ b/Resources/Private/FluidStyledContent/Templates/Teaser.html @@ -2,7 +2,10 @@ - {teaserElement.html} + {teaserElement.html} @@ -51,7 +54,11 @@

Quickstart:

- +
{flexformConfiguration.buttontext}{flexformConfiguration.buttontext}
@@ -67,5 +74,9 @@

Quickstart:

MoreButton: View for normal website -

{flexformConfiguration.buttontext}

+

{flexformConfiguration.buttontext}

From d7d6ae7f435438efe573c740822f1fefc0c72700 Mon Sep 17 00:00:00 2001 From: Alex Kellner Date: Sat, 5 Jun 2021 22:12:30 +0200 Subject: [PATCH 12/14] [FEATURE] Define which newsletter should be send optinally via CLI queue command as second parameter --- Classes/Command/QueueCommand.php | 11 ++++++++++- Classes/Domain/Repository/QueueRepository.php | 6 +++++- Classes/Mail/ProgressQueue.php | 7 ++++--- Documentation/Installation/Index.md | 12 +++++++++++- 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/Classes/Command/QueueCommand.php b/Classes/Command/QueueCommand.php index 4189f0b4..5cfbf38b 100644 --- a/Classes/Command/QueueCommand.php +++ b/Classes/Command/QueueCommand.php @@ -33,6 +33,12 @@ public function configure() { $this->setDescription('Send a bunch of emails from the queue.'); $this->addArgument('amount', InputArgument::OPTIONAL, 'How many mails should be send per wave?', 50); + $this->addArgument( + 'newsletter', + InputArgument::OPTIONAL, + 'Newsletter uid if only queued mails from a specific NL should be send', + 0 + ); } /** @@ -58,7 +64,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int { /** @var ProgressQueue $progressQueue */ $progressQueue = GeneralUtility::makeInstance(ProgressQueue::class, $output); - $progressed = $progressQueue->progress((int)$input->getArgument('amount')); + $progressed = $progressQueue->progress( + (int)$input->getArgument('amount'), + (int)$input->getArgument('newsletter') + ); if ($progressed > 0) { $output->writeln('Successfully sent ' . $progressed . ' email(s) from the queue...'); } else { diff --git a/Classes/Domain/Repository/QueueRepository.php b/Classes/Domain/Repository/QueueRepository.php index ed1be84b..f46ad757 100644 --- a/Classes/Domain/Repository/QueueRepository.php +++ b/Classes/Domain/Repository/QueueRepository.php @@ -17,10 +17,11 @@ class QueueRepository extends AbstractRepository { /** * @param int $limit + * @param int $newsletterIdentifier * @return QueryResultInterface * @throws InvalidQueryException */ - public function findDispatchableInQueue(int $limit): QueryResultInterface + public function findDispatchableInQueue(int $limit, int $newsletterIdentifier): QueryResultInterface { $query = $this->createQuery(); $and = [ @@ -31,6 +32,9 @@ public function findDispatchableInQueue(int $limit): QueryResultInterface $query->equals('user.deleted', false), $query->equals('user.disable', false) ]; + if ($newsletterIdentifier > 0) { + $and[] = $query->equals('newsletter.uid', $newsletterIdentifier); + } $query->matching($query->logicalAnd($and)); $query->setLimit($limit); $query->setOrderings(['tstamp' => QueryInterface::ORDER_ASCENDING]); diff --git a/Classes/Mail/ProgressQueue.php b/Classes/Mail/ProgressQueue.php index f7ff9b64..770c4dd5 100644 --- a/Classes/Mail/ProgressQueue.php +++ b/Classes/Mail/ProgressQueue.php @@ -63,6 +63,7 @@ public function __construct(OutputInterface $output) /** * @param int $limit + * @param int $newsletterIdentifier * @return int Number of progressed queued mails * @throws ArgumentMissingException * @throws Exception @@ -74,12 +75,12 @@ public function __construct(OutputInterface $output) * @throws InvalidSlotException * @throws InvalidSlotReturnException * @throws MisconfigurationException - * @throws UnknownObjectException * @throws TransportExceptionInterface + * @throws UnknownObjectException */ - public function progress(int $limit = 50): int + public function progress(int $limit, int $newsletterIdentifier): int { - $queues = $this->queueRepository->findDispatchableInQueue($limit); + $queues = $this->queueRepository->findDispatchableInQueue($limit, $newsletterIdentifier); if ($queues->count() > 0) { $progress = new ProgressBar($this->output, $queues->count()); $progress->start(); diff --git a/Documentation/Installation/Index.md b/Documentation/Installation/Index.md index c87b319f..54b746df 100644 --- a/Documentation/Installation/Index.md +++ b/Documentation/Installation/Index.md @@ -132,4 +132,14 @@ good solution. As an alternative, you could also process the queue directly from the console: -`./vendor/bin/typo3cms luxletter:queue 50` +``` +# Send 50 newsletters that are queued +./vendor/bin/typo3 luxletter:queue + +# Send a specific number of newsletters from queue +./vendor/bin/typo3cms luxletter:queue 10 + +# Send some queued newsletters from newsletter with uid 123 +./vendor/bin/typo3cms luxletter:queue 10 123 +``` + From 1ee91d1b4052f9af2d4775e6be7bb91428dcd0a7 Mon Sep 17 00:00:00 2001 From: Alex Kellner Date: Sat, 5 Jun 2021 23:03:22 +0200 Subject: [PATCH 13/14] [TASK] Code cleanup Extract all link service methods from FrontendUrlService to SiteService and check for valid site configuration --- Classes/Domain/Model/Link.php | 14 +++-- Classes/Domain/Service/FrontendUrlService.php | 51 ------------------- .../Service/ParseNewsletterUrlService.php | 14 ++--- Classes/Domain/Service/SiteService.php | 45 +++++++++++++++- .../Mail/GetUnsubscribeUrlViewHelper.php | 22 ++------ 5 files changed, 62 insertions(+), 84 deletions(-) delete mode 100644 Classes/Domain/Service/FrontendUrlService.php diff --git a/Classes/Domain/Model/Link.php b/Classes/Domain/Model/Link.php index cf3d0223..7fa89ba0 100644 --- a/Classes/Domain/Model/Link.php +++ b/Classes/Domain/Model/Link.php @@ -2,11 +2,10 @@ declare(strict_types=1); namespace In2code\Luxletter\Domain\Model; -use In2code\Luxletter\Domain\Service\FrontendUrlService; +use In2code\Luxletter\Domain\Service\SiteService; use In2code\Luxletter\Exception\MisconfigurationException; use In2code\Luxletter\Utility\StringUtility; -use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationExtensionNotConfiguredException; -use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationPathDoesNotExistException; +use TYPO3\CMS\Core\Exception\SiteNotFoundException; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; @@ -95,16 +94,15 @@ public function setHash(string $hash): self * Get hashed uri * * @return string - * @throws ExtensionConfigurationExtensionNotConfiguredException - * @throws ExtensionConfigurationPathDoesNotExistException * @throws MisconfigurationException + * @throws SiteNotFoundException */ public function getUriFromHash(): string { $site = $this->getNewsletter()->getConfiguration()->getSiteConfiguration(); - /** @var FrontendUrlService $urlService */ - $urlService = GeneralUtility::makeInstance(FrontendUrlService::class); - return $urlService->getFrontendUrlFromParameter(['luxletterlink' => $this->getHash()], $site); + /** @var SiteService $siteService */ + $siteService = GeneralUtility::makeInstance(SiteService::class); + return $siteService->getFrontendUrlFromParameter(['luxletterlink' => $this->getHash()], $site); } /** diff --git a/Classes/Domain/Service/FrontendUrlService.php b/Classes/Domain/Service/FrontendUrlService.php deleted file mode 100644 index 97056da5..00000000 --- a/Classes/Domain/Service/FrontendUrlService.php +++ /dev/null @@ -1,51 +0,0 @@ -getSiteByPageId($pageIdentifier); - $uri = $site->getRouter()->generateUri($pageIdentifier, $arguments); - $url = $uri->__tostring(); - return $url; - } - - /** - * @param array $arguments - * @param Site $site - * @return string - */ - public function getFrontendUrlFromParameter(array $arguments, Site $site): string - { - /** @var SiteService $siteService */ - $siteService = GeneralUtility::makeInstance(SiteService::class); - $url = $siteService->getDomainFromSite($site); - $url .= '?' . http_build_query($arguments); - return $url; - } -} diff --git a/Classes/Domain/Service/ParseNewsletterUrlService.php b/Classes/Domain/Service/ParseNewsletterUrlService.php index 00c253a0..e29d7e2f 100644 --- a/Classes/Domain/Service/ParseNewsletterUrlService.php +++ b/Classes/Domain/Service/ParseNewsletterUrlService.php @@ -55,7 +55,6 @@ class ParseNewsletterUrlService * @param string $origin can be a page uid or a complete url * @throws InvalidSlotException * @throws InvalidSlotReturnException - * @throws Exception */ public function __construct(string $origin) { @@ -66,8 +65,9 @@ public function __construct(string $origin) if ($typenum > 0) { $arguments = ['type' => $typenum]; } - $urlService = ObjectUtility::getObjectManager()->get(FrontendUrlService::class); - $url = $urlService->getTypolinkUrlFromParameter((int)$origin, $arguments); + /** @var SiteService $siteService */ + $siteService = GeneralUtility::makeInstance(SiteService::class); + $url = $siteService->getPageUrlFromParameter((int)$origin, $arguments); } elseif (StringUtility::isValidUrl($origin)) { $url = $origin; } @@ -90,7 +90,7 @@ public function __construct(string $origin) public function getParsedContent(Site $site, User $user = null): string { if ($user === null) { - $userFactory = ObjectUtility::getObjectManager()->get(UserFactory::class); + $userFactory = GeneralUtility::makeInstance(UserFactory::class); $user = $userFactory->getDummyUser(); } $this->signalDispatch(__CLASS__, __FUNCTION__ . 'BeforeParsing', [$user, $this]); @@ -114,7 +114,7 @@ protected function getNewsletterContainerAndContent(string $content, Site $site, $templateName = 'Mail/NewsletterContainer.html'; if ($this->isParsingActive()) { $configuration = ConfigurationUtility::getExtensionSettings(); - $standaloneView = ObjectUtility::getObjectManager()->get(StandaloneView::class); + $standaloneView = GeneralUtility::makeInstance(StandaloneView::class); $standaloneView->setTemplateRootPaths($configuration['view']['templateRootPaths']); $standaloneView->setLayoutRootPaths($configuration['view']['layoutRootPaths']); $standaloneView->setPartialRootPaths($configuration['view']['partialRootPaths']); @@ -161,7 +161,7 @@ protected function getNewsletterContainerAndContent(string $content, Site $site, */ protected function getContentObjectVariables(array $configuration): array { - $tsService = ObjectUtility::getObjectManager()->get(TypoScriptService::class); + $tsService = GeneralUtility::makeInstance(TypoScriptService::class); $tsConfiguration = $tsService->convertPlainArrayToTypoScriptArray($configuration); $variables = []; @@ -205,7 +205,7 @@ protected function getContentFromOrigin(User $user): string } $string = $this->getBodyFromHtml($string); if ($this->isParsingActive()) { - $parseService = ObjectUtility::getObjectManager()->get(ParseNewsletterService::class); + $parseService = GeneralUtility::makeInstance(ParseNewsletterService::class); $string = $parseService->parseMailText($string, ['user' => $user]); } $this->signalDispatch(__CLASS__, __FUNCTION__, [$string, $user, $this]); diff --git a/Classes/Domain/Service/SiteService.php b/Classes/Domain/Service/SiteService.php index 67efc642..2d7cfe6f 100644 --- a/Classes/Domain/Service/SiteService.php +++ b/Classes/Domain/Service/SiteService.php @@ -41,6 +41,50 @@ public function getSite(): Site * @throws MisconfigurationException */ public function getDomainFromSite(Site $site): string + { + $this->checkForValidSite($site); + return $site->getConfiguration()['base']; + } + + /** + * @param int $pageIdentifier + * @param array $arguments + * @return string + * @throws MisconfigurationException + */ + public function getPageUrlFromParameter(int $pageIdentifier, array $arguments = []): string + { + /** @var Site $site */ + $site = GeneralUtility::makeInstance(SiteFinder::class)->getSiteByPageId($pageIdentifier); + $this->checkForValidSite($site); + $uri = $site->getRouter()->generateUri($pageIdentifier, $arguments); + return $uri->__tostring(); + } + + /** + * Just build an url with a domain and some arguments (so not page needed) + * + * @param array $arguments + * @param Site $site + * @return string + * @throws MisconfigurationException + */ + public function getFrontendUrlFromParameter(array $arguments, Site $site): string + { + $this->checkForValidSite($site); + /** @var SiteService $siteService */ + $siteService = GeneralUtility::makeInstance(SiteService::class); + $url = $siteService->getDomainFromSite($site); + $url .= '?' . http_build_query($arguments); + return $url; + } + + /** + * @param Site $site + * @return void + * @throws MisconfigurationException + */ + protected function checkForValidSite(Site $site): void { $base = $site->getConfiguration()['base']; if (StringUtility::startsWith($base, 'http') === false || StringUtility::endsWith($base, '/') === false) { @@ -49,6 +93,5 @@ public function getDomainFromSite(Site $site): string 1622832844 ); } - return $base; } } diff --git a/Classes/ViewHelpers/Mail/GetUnsubscribeUrlViewHelper.php b/Classes/ViewHelpers/Mail/GetUnsubscribeUrlViewHelper.php index 1b830a93..9e4dbf4a 100644 --- a/Classes/ViewHelpers/Mail/GetUnsubscribeUrlViewHelper.php +++ b/Classes/ViewHelpers/Mail/GetUnsubscribeUrlViewHelper.php @@ -4,16 +4,11 @@ use In2code\Luxletter\Domain\Model\Newsletter; use In2code\Luxletter\Domain\Model\User; -use In2code\Luxletter\Domain\Service\FrontendUrlService; +use In2code\Luxletter\Domain\Service\SiteService; use In2code\Luxletter\Exception\MisconfigurationException; use In2code\Luxletter\Exception\UserValuesAreMissingException; -use In2code\Luxletter\Utility\ObjectUtility; -use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationExtensionNotConfiguredException; -use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationPathDoesNotExistException; -use TYPO3\CMS\Core\Exception\SiteNotFoundException; -use TYPO3\CMS\Core\Routing\InvalidRouteArgumentsException; use TYPO3\CMS\Core\Site\Entity\Site; -use TYPO3\CMS\Extbase\Object\Exception; +use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper; /** @@ -35,19 +30,14 @@ public function initializeArguments(): void /** * @return string - * @throws ExtensionConfigurationExtensionNotConfiguredException - * @throws ExtensionConfigurationPathDoesNotExistException - * @throws InvalidRouteArgumentsException - * @throws SiteNotFoundException * @throws UserValuesAreMissingException * @throws MisconfigurationException - * @throws Exception */ public function render(): string { - /** @var FrontendUrlService $frontendUrlService */ - $frontendUrlService = ObjectUtility::getObjectManager()->get(FrontendUrlService::class); - $url = $frontendUrlService->getTypolinkUrlFromParameter( + /** @var SiteService $siteService */ + $siteService = GeneralUtility::makeInstance(SiteService::class); + return $siteService->getPageUrlFromParameter( $this->getPidUnsubscribe(), [ 'tx_luxletter_fe' => [ @@ -57,13 +47,11 @@ public function render(): string ] ] ); - return $url; } /** * @return int * @throws MisconfigurationException - * @throws SiteNotFoundException */ protected function getPidUnsubscribe(): int { From ef0ce5ddf713ec27b4869c89cb125e87c7dc3c2e Mon Sep 17 00:00:00 2001 From: Alex Kellner Date: Sat, 5 Jun 2021 23:41:02 +0200 Subject: [PATCH 14/14] [TASK] Small documentation changes --- Documentation/Newsletter/Index.md | 12 ++++++------ Documentation/Tech/Index.md | 8 +++++--- Resources/Private/Templates/Newsletter/Receiver.html | 4 ++-- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/Documentation/Newsletter/Index.md b/Documentation/Newsletter/Index.md index 201196fe..d2813725 100644 --- a/Documentation/Newsletter/Index.md +++ b/Documentation/Newsletter/Index.md @@ -123,13 +123,13 @@ plugin { tx_luxletter_fe { view { templateRootPaths { - 1 = EXT:yoursitepackage/Resources/Private/Templates/Extensions/Luxletter/ + 2 = EXT:yoursitepackage/Resources/Private/Templates/Extensions/Luxletter/ } partialRootPaths { - 1 = EXT:yoursitepackage/Resources/Private/Partials/Extensions/Luxletter/ + 2 = EXT:yoursitepackage/Resources/Private/Partials/Extensions/Luxletter/ } layoutRootPaths { - 1 = EXT:yoursitepackage/Resources/Private/Layouts/Extensions/Luxletter/ + 2 = EXT:yoursitepackage/Resources/Private/Layouts/Extensions/Luxletter/ } } } @@ -138,13 +138,13 @@ module { tx_luxletter { view { templateRootPaths { - 1 = EXT:yoursitepackage/Resources/Private/Templates/Extensions/Luxletter/ + 2 = EXT:yoursitepackage/Resources/Private/Templates/Extensions/Luxletter/ } partialRootPaths { - 1 = EXT:yoursitepackage/Resources/Private/Partials/Extensions/Luxletter/ + 2 = EXT:yoursitepackage/Resources/Private/Partials/Extensions/Luxletter/ } layoutRootPaths { - 1 = EXT:yoursitepackage/Resources/Private/Layouts/Extensions/Luxletter/ + 2 = EXT:yoursitepackage/Resources/Private/Layouts/Extensions/Luxletter/ } } } diff --git a/Documentation/Tech/Index.md b/Documentation/Tech/Index.md index be91592d..a5037282 100644 --- a/Documentation/Tech/Index.md +++ b/Documentation/Tech/Index.md @@ -13,15 +13,17 @@ plugin { view { templateRootPaths { 0 = EXT:luxletter/Resources/Private/Templates/ - 1 = EXT:sitepackage/Resources/Private/Templates/ + 1 = EXT:lux/Resources/Private/Templates/ + 2 = EXT:sitepackage/Resources/Private/Templates/ } partialRootPaths { 0 = EXT:luxletter/Resources/Private/Partials/ - 1 = EXT:sitepackage/Resources/Private/Partials/ + 1 = EXT:lux/Resources/Private/Partials/ + 2 = EXT:sitepackage/Resources/Private/Partials/ } layoutRootPaths { 0 = EXT:luxletter/Resources/Private/Layouts/ - 1 = EXT:sitepackage/Resources/Private/Layouts/ + 2 = EXT:sitepackage/Resources/Private/Layouts/ } } } diff --git a/Resources/Private/Templates/Newsletter/Receiver.html b/Resources/Private/Templates/Newsletter/Receiver.html index 5f059a7a..cd835e5a 100644 --- a/Resources/Private/Templates/Newsletter/Receiver.html +++ b/Resources/Private/Templates/Newsletter/Receiver.html @@ -17,7 +17,7 @@