Commit 57d02059 authored by Kevin Ditscheid's avatar Kevin Ditscheid
Browse files

[TASK] Fix bugs, language migration wizard, more reasonable error logging

parent 262ba3b5
......@@ -25,14 +25,11 @@
namespace SGalinski\SgMail\Command;
use SGalinski\SgMail\Domain\Model\Mail;
use SGalinski\SgMail\Domain\Repository\MailRepository;
use SGalinski\SgMail\Service\PlaintextService;
use SGalinski\SgMail\Service\MailTemplateService;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use TYPO3\CMS\Core\Mail\MailMessage;
use TYPO3\CMS\Core\Resource\FileInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use Symfony\Component\Console\Command\Command;
use TYPO3\CMS\Core\Utility\VersionNumberUtility;
......@@ -54,17 +51,10 @@ class SendMailCommandController extends Command {
}
/**
* Execute the command
*
* @param InputInterface $input
* @param OutputInterface $output
* @return int
* @return MailRepository
* @throws Exception
* @throws IllegalObjectTypeException
* @throws UnknownObjectException
*/
public function execute(InputInterface $input, OutputInterface $output): int {
$sendCount = $input->getArgument('sendCount');
protected function getMailRepository(): MailRepository {
if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0', '<')) {
$objectManager = GeneralUtility::makeInstance(ObjectManager::class);
/** @var MailRepository $mailRepository */
......@@ -73,93 +63,25 @@ class SendMailCommandController extends Command {
$mailRepository = GeneralUtility::makeInstance(MailRepository::class);
}
$mailsToSend = $mailRepository->findMailsToSend($sendCount);
foreach ($mailsToSend as $mailToSend) {
/** @var Mail $mailToSend */
$fromAddress = $mailToSend->getFromAddress();
$toAddresses = trim($mailToSend->getToAddress());
$addressesArray = GeneralUtility::trimExplode(',', $toAddresses, TRUE);
if (\count($addressesArray) > 1) {
$toAddresses = $addressesArray;
}
$ccAddresses = GeneralUtility::trimExplode(',', $mailToSend->getCcAddresses(), TRUE);
$bccAddresses = GeneralUtility::trimExplode(',', $mailToSend->getBccAddresses(), TRUE);
$mailSubject = $mailToSend->getMailSubject();
$mailBody = $mailToSend->getMailBody();
$mailToSend->setSendingTime(time());
$mailToSend->setLastSendingTime(time());
if (empty($fromAddress) || empty($toAddresses)) {
continue;
}
$mailRepository->update($mailToSend);
$mailMessage = GeneralUtility::makeInstance(MailMessage::class);
$mailMessage->setFrom($fromAddress, $mailToSend->getFromName());
$mailMessage->setTo($toAddresses);
$mailMessage->setSubject($mailSubject);
if (\count($ccAddresses)) {
$mailMessage->setCc($ccAddresses);
}
if (\count($bccAddresses)) {
$mailMessage->setBcc($bccAddresses);
}
$replyTo = $mailToSend->getReplyTo();
if ($replyTo) {
$mailMessage->setReplyTo($replyTo);
}
$plaintextService = GeneralUtility::makeInstance(PlaintextService::class);
$plaintextBody = $plaintextService->makePlain($mailBody);
if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0', '<')) {
$mailMessage->setBody($mailBody, 'text/html');
$mailMessage->addPart($plaintextBody, 'text/plain');
} else {
$mailMessage->html($mailBody);
$mailMessage->text($plaintextBody);
}
$attachments = $mailToSend->getAttachments();
if ($attachments->count() > 0) {
foreach ($attachments as $attachment) {
try {
/** @var FileInterface $file */
$file = $attachment->getOriginalResource();
if (!$file) {
continue;
}
$file = $file->getOriginalFile();
if (!$file) {
continue;
}
if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0', '<')) {
$mailMessage->attach(
\Swift_Attachment::newInstance(
$file->getContents(), $file->getName(), $file->getMimeType()
)
);
} else {
$mailMessage->attach($file->getContents(), $file->getName(), $file->getMimeType());
}
} catch (\Exception $exception) {
continue;
}
}
}
return $mailRepository;
}
try {
$mailMessage->send();
} catch (\Exception $exception) {
// Ignore that. We can't do much here in a misconfiguration case.
}
}
/**
* Execute the command
*
* @param InputInterface $input
* @param OutputInterface $output
* @return int
* @throws Exception
* @throws IllegalObjectTypeException
* @throws UnknownObjectException
*/
public function execute(InputInterface $input, OutputInterface $output): int {
$sendCount = $input->getArgument('sendCount');
// Important for command controllers that change data
$mailRepository->persist();
$mailsToSend = $this->getMailRepository()->findMailsToSend($sendCount)->toArray();
$mailService = GeneralUtility::makeInstance(MailTemplateService::class);
$mailService->sendMailsFromQueue($mailsToSend);
return 0;
}
}
......@@ -25,6 +25,7 @@
namespace SGalinski\SgMail\Controller;
use SGalinski\SgMail\Domain\Model\Mail;
use SGalinski\SgMail\Domain\Repository\MailRepository;
use SGalinski\SgMail\Service\BackendService;
use SGalinski\SgMail\Service\MailTemplateService;
......@@ -32,16 +33,13 @@ use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException;
use TYPO3\CMS\Core\Exception\SiteNotFoundException;
use TYPO3\CMS\Core\Messaging\FlashMessage;
use TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException;
use TYPO3\CMS\Core\Site\SiteFinder;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException;
use TYPO3\CMS\Extbase\Mvc\Exception\StopActionException;
use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
use TYPO3\CMS\Extbase\Object\Exception;
use TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException;
use TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException;
use TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException;
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
/**
......@@ -140,23 +138,35 @@ class QueueController extends AbstractController {
/**
* send or resend a mail in the queue
*
* @param int $uid
* @throws IllegalObjectTypeException
* @throws ResourceDoesNotExistException
* @param Mail $mail
* @throws StopActionException
* @throws UnknownObjectException
*/
public function sendMailAction(int $uid): void {
public function sendMailAction(Mail $mail): void {
$mailService = new MailTemplateService();
if ($mailService->sendMailFromQueue($uid)) {
$message = LocalizationUtility::translate('backend.success_mail_queue', 'sg_mail');
$this->addFlashMessage($message, '', FlashMessage::OK);
} else {
try {
$mailService->sendMailsFromQueue([$mail]);
} catch (\TYPO3\CMS\Core\Exception $exception) {
$message = LocalizationUtility::translate(
'backend.error_mail_queue',
'sg_mail'
);
$this->addFlashMessage($message, '', FlashMessage::ERROR);
$this->redirect('index', NULL, NULL, $this->request->getArguments());
}
if ($mail->getStatus() !== Mail::STATUS_ERROR) {
$this->addFlashMessage(
LocalizationUtility::translate('backend.success_mail_queue', 'sg_mail'),
'',
FlashMessage::OK
);
} else {
$this->addFlashMessage(
$mail->getErrorMessage(),
'',
FlashMessage::ERROR
);
}
$this->redirect('index', NULL, NULL, $this->request->getArguments());
......@@ -165,12 +175,10 @@ class QueueController extends AbstractController {
/**
* Preview for a mail
*
* @param int $uid
* @param Mail $mail
*/
public function previewAction(int $uid): void {
$mailService = new MailTemplateService();
$mailToPreview = $mailService->getMailObjectByUid($uid);
$this->view->assign('mail', $mailToPreview);
public function previewAction(Mail $mail): void {
$this->view->assign('mail', $mail);
}
/**
......
......@@ -39,6 +39,9 @@ class Mail extends AbstractEntity {
public const PRIORITY_MEDIUM = 100;
public const PRIORITY_HIGH = 150;
public const PRIORITY_HIGHEST = 200;
public const STATUS_PENDING = 'pending';
public const STATUS_SENT = 'sent';
public const STATUS_ERROR = 'error';
/**
* @var string
......@@ -120,6 +123,16 @@ class Mail extends AbstractEntity {
*/
protected $attachments;
/**
* @var string
*/
protected $status = self::STATUS_PENDING;
/**
* @var string
*/
protected $errorMessage = '';
/**
* Mail constructor.
*/
......@@ -371,4 +384,32 @@ class Mail extends AbstractEntity {
public function addAttachment(FileReference $attachment): void {
$this->attachments->attach($attachment);
}
/**
* @return string
*/
public function getStatus(): string {
return $this->status;
}
/**
* @param string $status
*/
public function setStatus(string $status): void {
$this->status = $status;
}
/**
* @return string
*/
public function getErrorMessage(): string {
return $this->errorMessage;
}
/**
* @param string $errorMessage
*/
public function setErrorMessage(string $errorMessage): void {
$this->errorMessage = $errorMessage;
}
}
This diff is collapsed.
<?php
/*******************************************************************************
* Copyright notice
*
* (c) sgalinski Internet Services (https://www.sgalinski.de)
*
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
******************************************************************************/
namespace SGalinski\SgMail\Updates;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Site\SiteFinder;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Install\Updates\DatabaseUpdatedPrerequisite;
use TYPO3\CMS\Install\Updates\UpgradeWizardInterface;
class LanguageMigrationUpdate implements UpgradeWizardInterface {
public const IDENTIFIER = 'sgmail_languagemigrationupdate';
/**
* @return string
*/
public function getIdentifier(): string {
return self::IDENTIFIER;
}
/**
* @return string
*/
public function getTitle(): string {
return 'Language migration wizard';
}
/**
* @return string
*/
public function getDescription(): string {
return 'This wizard migrates the language values of mails and templates to more reasonable values then two letter isocodes';
}
/**
* @return bool
*/
public function executeUpdate(): bool {
$sites = GeneralUtility::makeInstance(SiteFinder::class)->getAllSites();
$connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
foreach ($sites as $site) {
$languages = $site->getAllLanguages();
foreach ($languages as $language) {
$queryBuilder = $connectionPool->getQueryBuilderForTable('tx_sgmail_domain_model_mail');
$queryBuilder->update('tx_sgmask_domain_model_mail')
->set('language', explode('.', $language->getLocale()))
->where(
$queryBuilder->expr()->like('language', $language->getTypo3Language())
)->execute();
$queryBuilder = $connectionPool->getQueryBuilderForTable('tx_sgmail_domain_model_template');
$queryBuilder->update('tx_sgmail_domain_model_template')
->set('sys_language_uid', $language->getLanguageId())
->where(
$queryBuilder->expr()->like('language', $language->getTypo3Language())
)->execute();
}
}
return TRUE;
}
/**
* @return bool
*/
public function updateNecessary(): bool {
return TRUE;
}
/**
* @return string[]
*/
public function getPrerequisites(): array {
return [
DatabaseUpdatedPrerequisite::class
];
}
}
<?php
/*******************************************************************************
* Copyright notice
*
* (c) sgalinski Internet Services (https://www.sgalinski.de)
*
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
******************************************************************************/
namespace SGalinski\SgMail\Updates;
use SGalinski\SgMail\Domain\Model\Mail;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Install\Updates\DatabaseUpdatedPrerequisite;
use TYPO3\CMS\Install\Updates\UpgradeWizardInterface;
/**
* Class SendStatusUpdate
*
* @package SGalinski\SgMail\Updates
*/
class SendStatusUpdate implements UpgradeWizardInterface {
public const IDENTIFIER = 'sgmail_sendstatusupdate';
/**
* @inheritDoc
*/
public function getIdentifier(): string {
return self::IDENTIFIER;
}
/**
* @inheritDoc
*/
public function getTitle(): string {
return 'Update the send status of mails';
}
/**
* @inheritDoc
*/
public function getDescription(): string {
return 'This wizard updates the status of mails that have a sending_time set to sent appropriately.';
}
/**
* @inheritDoc
*/
public function executeUpdate(): bool {
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_sgmail_domain_model_mail');
$queryBuilder->update('tx_sgmail_domain_model_mail')
->set('status', Mail::STATUS_SENT)
->where(
$queryBuilder->expr()->gt('sending_time', 0),
$queryBuilder->expr()->eq('status', Mail::STATUS_PENDING)
)->execute();
return TRUE;
}
/**
* @inheritDoc
*/
public function updateNecessary(): bool {
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_sgmail_domain_model_mail');
$count = $queryBuilder->count('*')
->from('tx_sgmail_domain_model_mail')
->where(
$queryBuilder->expr()->gt('sending_time', 0),
$queryBuilder->expr()->eq('status', Mail::STATUS_PENDING)
)->execute()->fetchOne();
return $count > 0;
}
/**
* @inheritDoc
*/
public function getPrerequisites(): array {
return [
DatabaseUpdatedPrerequisite::class
];
}
}
<?php
/***************************************************************
* Copyright notice
*
* (c) sgalinski Internet Services (https://www.sgalinski.de)
*
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
namespace SGalinski\SgMail\Updates;
use TYPO3\CMS\Core\Database\Connection;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Install\Updates\DatabaseUpdatedPrerequisite;
use TYPO3\CMS\Install\Updates\UpgradeWizardInterface;
/**
* Makes german templates the default and former default as english templates
*/
class UpdateGermanAsDefault implements UpgradeWizardInterface {
/**
* The wizard identifier
*/
public const IDENTIFIER = 'tx_sgmail_update_german_as_default';
/**
* @var string
*/
protected $table = 'tx_sgmail_domain_model_template';
/**
* @return string
*/
public function getIdentifier(): string {
return self::IDENTIFIER;
}
/**
* @return string
*/
public function getTitle(): string {
return 'Makes german templates the default and former default as english templates. WARNING: ONLY EXECUTE THIS IF IT MAKES SENSE FOR YOUR TYPO3 INSTANCE';
}
/**
* @return string
*/
public function getDescription(): string {
return '';
}
/**
* @return bool
*/
public function executeUpdate(): bool {
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->table);
$queryBuilder->getRestrictions()->removeAll();
$resultGerman = $queryBuilder->select('uid')
->from($this->table)
->where(
$queryBuilder->expr()->eq('language', $queryBuilder->createNamedParameter('de'))
)
->execute()->fetchAllAssociative();
$resultDefault = $queryBuilder->select('uid')
->from($this->table)
->where(
$queryBuilder->expr()->eq('language', $queryBuilder->createNamedParameter('default'))
)
->execute()->fetchAllAssociative();
/** @var array $resultGerman */
foreach ($resultGerman as $row) {
$queryBuilder->update($this->table)
->where(
$queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($row[0], Connection::PARAM_INT))
)
->set('language', 'default', TRUE)
->execute();
}
/** @var array $resultGerman */
foreach ($resultDefault as $row) {
$queryBuilder->update($this->table)
->where(
$queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($row[0], Connection::PARAM_INT))
)
->set('language', 'en', TRUE)
->execute();
}
return TRUE;
}
/**
* @return bool
*/
public function updateNecessary(): bool {
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->table);
$queryBuilder->getRestrictions()->removeAll();
$rowCount = $queryBuilder->select('*')