diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..410d80ba1 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,56 @@ +# EditorConfig is awesome: http://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +charset = utf-8 +end_of_line = lf +indent_style = space +indent_size = 4 +insert_final_newline = true +trim_trailing_whitespace = true + +# TS/JS-Files +[*.{ts,js}] +indent_size = 2 + +# JSON-Files +[*.json] +indent_style = tab + +# ReST-Files +[*.rst] +indent_size = 4 +max_line_length = 80 + +# YAML-Files +[*.{yaml,yml}] +indent_size = 2 + +# NEON-Files +[*.neon] +indent_size = 2 +indent_style = tab + +# package.json +[package.json] +indent_size = 2 + +# TypoScript +[*.{typoscript,tsconfig}] +indent_size = 2 + +# XLF-Files +[*.xlf] +indent_style = tab + +# SQL-Files +[*.sql] +indent_style = tab +indent_size = 2 + +# .htaccess +[{_.htaccess,.htaccess}] +indent_style = tab diff --git a/Classes/Command/AnalyzeBounceMailCommand.php b/Classes/Command/AnalyzeBounceMailCommand.php new file mode 100644 index 000000000..a16b96bef --- /dev/null +++ b/Classes/Command/AnalyzeBounceMailCommand.php @@ -0,0 +1,274 @@ +setDescription('This command will get bounce mail from the configured mailbox') + ->addOption( + 'server', + 's', + InputOption::VALUE_REQUIRED, + 'Server URL/IP' + ) + ->addOption( + 'port', + 'p', + InputOption::VALUE_REQUIRED, + 'Port number' + ) + ->addOption( + 'user', + 'u', + InputOption::VALUE_REQUIRED, + 'Username' + ) + ->addOption( + 'password', + 'pw', + InputOption::VALUE_REQUIRED, + 'Password' + ) + ->addOption( + 'type', + 't', + InputOption::VALUE_REQUIRED, + 'Type of mailserver (imap or pop3)' + ) + ->addOption( + 'count', + 'c', + InputOption::VALUE_REQUIRED, + 'Number of bounce mail to be processed' + ) + //->setHelp('') + ; + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $io = new SymfonyStyle($input, $output); + $io->title($this->getDescription()); + $this->setLanguageService(); + + $server = ''; + $port = 0; + $user = ''; + $password = ''; + $type = ''; + $count = 0; + // check if PHP IMAP is installed + if (!extension_loaded('imap')) { + $io->error($this->languageService->getLL('scheduler.bounceMail.phpImapError')); + return Command::FAILURE; + } + + if ($input->getOption('server')) { + $server = $input->getOption('server'); + //$io->writeln($server); + } + if ($input->getOption('port')) { + $port = (int)$input->getOption('port'); + //$io->writeln($port); + } + if ($input->getOption('user')) { + $user = $input->getOption('user'); + //$io->writeln($user); + } + if ($input->getOption('password')) { + $password = $input->getOption('password'); + //$io->writeln($password); + } + if ($input->getOption('type')) { + $type = $input->getOption('type'); + //$io->writeln($type); + if(!in_array($type, ['imap', 'pop3'])) { + $io->warning('Type: only imap or pop3'); + return Command::FAILURE; + } + } + if ($input->getOption('count')) { + $count = (int)$input->getOption('count'); + //$io->writeln($count); + } + + // try connect to mail server + $mailServer = $this->connectMailServer($server, $port, $type, $user, $password, $io); + if ($mailServer instanceof Server) { + // we are connected to mail server + // get unread mails + $messages = $mailServer->search('UNSEEN', $count); + if(count($messages)) { + /** @var Message $message The message object */ + foreach ($messages as $message) { + // process the mail + if ($this->processBounceMail($message)) { + //$io->writeln($message->getSubject()); + // set delete + $message->delete(); + } + else { + $message->setFlag('SEEN'); + } + } + } + // expunge to delete permanently + $mailServer->expunge(); + imap_close($mailServer->getImapStream()); + return Command::SUCCESS; + } + else { + return Command::FAILURE; + } + + return Command::SUCCESS; + } + + /** + * Process the bounce mail + * @param Message $message the message object + * @return bool true if bounce mail can be parsed, else false + */ + private function processBounceMail($message) + { + /** @var Readmail $readMail */ + $readMail = GeneralUtility::makeInstance(Readmail::class); + + // get attachment + $attachmentArray = $message->getAttachments(); + $midArray = []; + if (is_array($attachmentArray)) { + // search in attachment + foreach ($attachmentArray as $attachment) { + $bouncedMail = $attachment->getData(); + // Find mail id + $midArray = $readMail->find_XTypo3MID($bouncedMail); + if (false === empty($midArray)) { + // if mid, rid and rtbl are found, then stop looping + break; + } + } + } + else { + // search in MessageBody (see rfc822-headers as Attachments placed ) + $midArray = $readMail->find_XTypo3MID($message->getMessageBody()); + } + + if (empty($midArray)) { + // no mid, rid and rtbl found - exit + return false; + } + + // Extract text content + $cp = $readMail->analyseReturnError($message->getMessageBody()); + + $row = GeneralUtility::makeInstance(SysDmailMaillogRepository::class)->selectForAnalyzeBounceMail($midArray['rid'], $midArray['rtbl'], $midArray['mid']); + + // only write to log table, if we found a corresponding recipient record + if (!empty($row)) { + $tableMaillog = 'sys_dmail_maillog'; + /** @var Connection $connection */ + $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($tableMaillog); + try { + $midArray['email'] = $row['email']; + $insertFields = [ + 'tstamp' => $this->getTimestampFromAspect(), + 'response_type' => -127, + 'mid' => (int)$midArray['mid'], + 'rid' => (int)$midArray['rid'], + 'email' => $midArray['email'], + 'rtbl' => $midArray['rtbl'], + 'return_content' => serialize($cp), + 'return_code' => (int)$cp['reason'] + ]; + $connection->insert($tableMaillog, $insertFields); + $sql_insert_id = $connection->lastInsertId($tableMaillog); + return (bool)$sql_insert_id; + } catch (\Doctrine\DBAL\DBALException $e) { + // Log $e->getMessage(); + return false; + } + } + else { + return false; + } + } + + /** + * Create connection to mail server. + * Return mailServer object or false on error + * + * @param string $server + * @param int $port + * @param string $type + * @param string $user + * @param string $password + * @param SymfonyStyle $io + * @return bool|Server + */ + private function connectMailServer(string $server, int $port, string $type, string $user, string $password, SymfonyStyle $io) + { + // check if we can connect using the given data + /** @var Server $mailServer */ + $mailServer = GeneralUtility::makeInstance( + Server::class, + $server, + $port, + $type + ); + + // set mail username and password + $mailServer->setAuthentication($user, $password); + + try { + $imapStream = $mailServer->getImapStream(); + return $mailServer; + } catch (\Exception $e) { + $io->error($this->languageService->getLL('scheduler.bounceMail.dataVerification').$e->getMessage()); + return false; + } + } + + /** + * + * @return int + */ + private function getTimestampFromAspect(): int { + $context = GeneralUtility::makeInstance(Context::class); + return $context->getPropertyFromAspect('date', 'timestamp'); + } + + /** + * @return void + */ + private function setLanguageService(): void { + $languageServiceFactory = GeneralUtility::makeInstance(LanguageServiceFactory::class); + $this->languageService = $languageServiceFactory->create('en'); //@TODO + $this->languageService->includeLLFile('EXT:direct_mail/Resources/Private/Language/locallang_mod2-6.xlf'); + } +} diff --git a/Classes/Command/DirectmailCommand.php b/Classes/Command/DirectmailCommand.php new file mode 100644 index 000000000..e1dc6a9f0 --- /dev/null +++ b/Classes/Command/DirectmailCommand.php @@ -0,0 +1,39 @@ +setDescription('This command invokes dmailer in order to process queued messages.'); + //$this->setHelp(''); + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $io = new SymfonyStyle($input, $output); + $io->title($this->getDescription()); + /** + * The direct_mail engine + * @var $htmlmail Dmailer + */ + $htmlmail = GeneralUtility::makeInstance(Dmailer::class); + $htmlmail->start(); + $htmlmail->runcron(); + return Command::SUCCESS; + } +} \ No newline at end of file diff --git a/Classes/Command/InvokeMailerEngineCommand.php b/Classes/Command/InvokeMailerEngineCommand.php index 7f5e0aaac..afb60bfc0 100644 --- a/Classes/Command/InvokeMailerEngineCommand.php +++ b/Classes/Command/InvokeMailerEngineCommand.php @@ -56,8 +56,6 @@ public function configure() } /** - * Executes the command for showing sys_log entries - * * @param InputInterface $input * @param OutputInterface $output */ @@ -72,7 +70,7 @@ protected function execute(InputInterface $input, OutputInterface $output) // If the lock is not older than 1 day, skip: if (filemtime($lockfile) > (time() - (60 * 60 * 24))) { $io->warning('TYPO3 Direct Mail Cron: Aborting, another process is already running!'); - return 0; + return Command::FAILURE; } else { $io->writeln('TYPO3 Direct Mail Cron: A .lock file was found but it is older than 1 day! Processing mails ...'); } @@ -91,6 +89,6 @@ protected function execute(InputInterface $input, OutputInterface $output) $htmlmail->runcron(); unlink($lockfile); - return 0; + return Command::SUCCESS; } } diff --git a/Classes/Container.php b/Classes/Container.php index 62363c09a..7a98f41c8 100644 --- a/Classes/Container.php +++ b/Classes/Container.php @@ -17,12 +17,13 @@ use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\MailUtility; +use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer; use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController; /** * Container class for auxilliary functions of tx_directmail * - * @author Kasper Sk�rh�j @typo3.com> + * @author Kasper Skårhøj @typo3.com> * @author Thorsten Kahler * * @package TYPO3 @@ -36,8 +37,18 @@ class Container /** * @var TypoScriptFrontendController */ - public $cObj; - + protected $cObj; + + /** + * https://docs.typo3.org/c/typo3/cms-core/main/en-us/Changelog/11.4/Deprecation-94956-PublicCObj.html + * + * @param ContentObjectRenderer $cObj + */ + public function setContentObjectRenderer(ContentObjectRenderer $cObj): void + { + $this->cObj = $cObj; + } + /** * This function wraps HTML comments around the content. * The comments contain the uids of assigned direct mail categories. @@ -48,7 +59,7 @@ class Container * * @return string content of the email with dmail boundaries */ - public function insert_dMailer_boundaries($content, $conf = array()) + public function insert_dMailer_boundaries($content, $conf = []) { if (isset($conf['useParentCObj']) && $conf['useParentCObj']) { $this->cObj = $conf['parentObj']->cObj; @@ -95,7 +106,7 @@ public function insert_dMailer_boundaries($content, $conf = array()) ->execute(); - while (($row = $statement->fetch())) { + while ($row = $statement->fetch()) { $categoryList .= $row['uid'] . ','; } $categoryList = rtrim($categoryList, ','); @@ -169,7 +180,7 @@ public function insertSitemapBoundaries($content, array $conf) if (count($categories) > 0) { - $categoryList = array(); + $categoryList = []; foreach ($categories as $category) { $categoryList[] = $category['uid_foreign']; } diff --git a/Classes/DirectMailUtility.php b/Classes/DirectMailUtility.php index d8900c4ce..5a222acb8 100644 --- a/Classes/DirectMailUtility.php +++ b/Classes/DirectMailUtility.php @@ -14,29 +14,24 @@ * The TYPO3 project - inspiring people to share! */ +use DirectMailTeam\DirectMail\Repository\PagesRepository; +use DirectMailTeam\DirectMail\Repository\SysDmailRepository; +use DirectMailTeam\DirectMail\Utility\DmRegistryUtility; use TYPO3\CMS\Backend\Routing\UriBuilder; use TYPO3\CMS\Backend\Tree\View\PageTreeView; use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\DataHandling\DataHandler; use TYPO3\CMS\Core\Messaging\FlashMessageRendererResolver; use TYPO3\CMS\Extbase\Configuration\ConfigurationManager; -use TYPO3\CMS\Core\Crypto\Random; use TYPO3\CMS\Core\Error\Http\ServiceUnavailableException; -use TYPO3\CMS\Core\Exception\SiteNotFoundException; use TYPO3\CMS\Core\Http\ImmediateResponseException; use TYPO3\CMS\Core\Imaging\Icon; use TYPO3\CMS\Core\Imaging\IconFactory; +use TYPO3\CMS\Core\Localization\LanguageService; use TYPO3\CMS\Core\Messaging\FlashMessage; -use TYPO3\CMS\Core\Registry; use TYPO3\CMS\Core\Resource\FileRepository; -use TYPO3\CMS\Core\Routing\InvalidRouteArgumentsException; -use TYPO3\CMS\Core\Site\SiteFinder; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\MathUtility; -use TYPO3\CMS\Core\Database\ConnectionPool; -use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction; -use TYPO3\CMS\Core\Database\Connection; -use TYPO3\CMS\Core\Utility\VersionNumberUtility; use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface; use TYPO3\CMS\Extbase\Object\ObjectManager; @@ -44,7 +39,7 @@ * Static class. * Functions in this class are used by more than one modules. * - * @author Kasper Sk�rh�j + * @author Kasper Skaarhoj * @author Jan-Erik Revsbech * @author Stanislas Rolland * @author Ivan-Dharma Kartolo @@ -54,58 +49,6 @@ */ class DirectMailUtility { - - /** - * Get recipient DB record given on the ID - * - * @param array $listArr List of recipient IDs - * @param string $table Table name - * @param string $fields Field to be selected - * - * @return array recipients' data - */ - public static function fetchRecordsListValues(array $listArr, $table, $fields='uid,name,email') - { - $outListArr = array(); - if (is_array($listArr) && count($listArr)) { - $idlist = implode(',', $listArr); - - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table); - $queryBuilder - ->getRestrictions() - ->removeAll() - ->add(GeneralUtility::makeInstance(DeletedRestriction::class)); - - $fieldArray = GeneralUtility::trimExplode(',', $fields); - - // handle selecting multiple fields - foreach ($fieldArray as $i => $field) { - if ($i) { - $queryBuilder->addSelect($field); - } else { - $queryBuilder->select($field); - } - } - - $res = $queryBuilder->from($table) - ->where( - $queryBuilder->expr()->in( - 'uid', - $queryBuilder->createNamedParameter( - GeneralUtility::intExplode(',', $idlist), - Connection::PARAM_INT_ARRAY - ) - ) - ) - ->execute(); - - while ($row = $res->fetch()) { - $outListArr[$row['uid']] = $row; - } - } - return $outListArr; - } - /** * Get the ID of page in a tree * @@ -138,506 +81,22 @@ public static function cleanPlainList(array $plainlist) /** * $plainlist is a multidimensional array. * this method only remove if a value has the same array - * $plainlist = array( - * 0 => array( - * name => '', - * email => '', - * ), - * 1 => array( - * name => '', - * email => '', - * ), - * - * ); + * $plainlist = [ + * 0 => [ + * name => '', + * email => '', + * ], + * 1 => [ + * name => '', + * email => '', + * ], + * ]; */ $plainlist = array_map('unserialize', array_unique(array_map('serialize', $plainlist))); return $plainlist; } - /** - * Return all uid's from $table where the $pid is in $pidList. - * If $cat is 0 or empty, then all entries (with pid $pid) is returned else only - * entires which are subscribing to the categories of the group with uid $group_uid is returned. - * The relation between the recipients in $table and sys_dmail_categories is a true MM relation - * (Must be correctly defined in TCA). - * - * @param string $table The table to select from - * @param string $pidList The pidList - * @param int $groupUid The groupUid. - * @param int $cat The number of relations from sys_dmail_group to sysmail_categories - * - * @return array The resulting array of uid's - */ - public static function getIdList($table, $pidList, $groupUid, $cat) - { - $addWhere = ''; - - if ($table == 'fe_groups') { - $switchTable = 'fe_users'; - } else { - $switchTable = $table; - } - - $pidArray = GeneralUtility::intExplode(',', $pidList); - - /** @var \TYPO3\CMS\Core\Database\Connection $connection */ - $connection = GeneralUtility::makeInstance(ConnectionPool::class) - ->getConnectionForTable($table); - $queryBuilder = $connection->createQueryBuilder(); - - if ($switchTable == 'fe_users') { - //$addWhere = ' AND fe_users.module_sys_dmail_newsletter = 1'; - $addWhere = $queryBuilder->expr()->eq( - 'fe_users.module_sys_dmail_newsletter', - 1 - ); - } - - // fe user group uid should be in list of fe users list of user groups - // $field = $switchTable.'.usergroup'; - // $command = $table.'.uid'; - // This approach, using standard SQL, does not work, - // even when fe_users.usergroup is defined as varchar(255) instead of tinyblob - // $usergroupInList = ' AND ('.$field.' LIKE \'%,\'||'.$command.'||\',%\' OR '.$field.' LIKE '.$command.'||\',%\' OR '.$field.' LIKE \'%,\'||'.$command.' OR '.$field.'='.$command.')'; - // The following will work but INSTR and CONCAT are available only in mySQL - - - - $mmTable = $GLOBALS['TCA'][$switchTable]['columns']['module_sys_dmail_category']['config']['MM']; - $cat = intval($cat); - if ($cat < 1) { - if ($table == 'fe_groups') { - $res = $queryBuilder - ->selectLiteral('DISTINCT ' . $switchTable . '.uid', $switchTable . '.email') - ->from($switchTable, $switchTable) - ->from($table, $table) - ->andWhere( - $queryBuilder->expr()->andX() - ->add($queryBuilder->expr()->in('fe_groups.pid', $queryBuilder->createNamedParameter($pidArray, Connection::PARAM_INT_ARRAY))) - ->add('INSTR( CONCAT(\',\',fe_users.usergroup,\',\'),CONCAT(\',\',fe_groups.uid ,\',\') )') - ->add( - $queryBuilder->expr()->neq($switchTable . '.email', $queryBuilder->createNamedParameter('')) - ) - ->add($addWhere) - ) - ->orderBy($switchTable . '.uid') - ->addOrderBy($switchTable . '.email') - ->execute(); - } else { - $res = $queryBuilder - ->selectLiteral('DISTINCT ' . $switchTable . '.uid', $switchTable . '.email') - ->from($switchTable) - ->andWhere( - $queryBuilder->expr()->andX() - ->add($queryBuilder->expr()->in($switchTable . '.pid', $queryBuilder->createNamedParameter($pidArray, Connection::PARAM_INT_ARRAY))) - ->add( - $queryBuilder->expr()->neq($switchTable . '.email', $queryBuilder->createNamedParameter('')) - ) - ->add($addWhere) - ) - ->orderBy($switchTable . '.uid') - ->addOrderBy($switchTable . '.email') - ->execute(); - } - } else { - if ($table == 'fe_groups') { - $res = $queryBuilder - ->selectLiteral('DISTINCT ' . $switchTable . '.uid', $switchTable . '.email') - ->from('sys_dmail_group', 'sys_dmail_group') - ->from('sys_dmail_group_category_mm', 'g_mm') - ->from('fe_groups', 'fe_groups') - ->from($mmTable, 'mm_1') - ->leftJoin( - 'mm_1', - $switchTable, - $switchTable, - $queryBuilder->expr()->eq($switchTable .'.uid', $queryBuilder->quoteIdentifier('mm_1.uid_local')) - ) - ->andWhere( - $queryBuilder->expr()->andX() - ->add($queryBuilder->expr()->in('fe_groups.pid', $queryBuilder->createNamedParameter($pidArray, Connection::PARAM_INT_ARRAY))) - ->add('INSTR( CONCAT(\',\',fe_users.usergroup,\',\'),CONCAT(\',\',fe_groups.uid ,\',\') )') - ->add($queryBuilder->expr()->eq('mm_1.uid_foreign', $queryBuilder->quoteIdentifier('g_mm.uid_foreign'))) - ->add($queryBuilder->expr()->eq('sys_dmail_group.uid', $queryBuilder->quoteIdentifier('g_mm.uid_local'))) - ->add($queryBuilder->expr()->eq('sys_dmail_group.uid', $queryBuilder->createNamedParameter($groupUid, \PDO::PARAM_INT))) - ->add( - $queryBuilder->expr()->neq($switchTable . '.email', $queryBuilder->createNamedParameter('')) - ) - ->add($addWhere) - ) - ->orderBy($switchTable . '.uid') - ->addOrderBy($switchTable . '.email') - ->execute(); - } else { - $res = $queryBuilder - ->selectLiteral('DISTINCT ' . $switchTable . '.uid', $switchTable . '.email') - ->from('sys_dmail_group', 'sys_dmail_group') - ->from('sys_dmail_group_category_mm', 'g_mm') - ->from($mmTable, 'mm_1') - ->leftJoin( - 'mm_1', - $table, - $table, - $queryBuilder->expr()->eq($table .'.uid', $queryBuilder->quoteIdentifier('mm_1.uid_local')) - ) - ->andWhere( - $queryBuilder->expr()->andX() - ->add($queryBuilder->expr()->in($switchTable . '.pid', $queryBuilder->createNamedParameter($pidArray, Connection::PARAM_INT_ARRAY))) - ->add($queryBuilder->expr()->eq('mm_1.uid_foreign', $queryBuilder->quoteIdentifier('g_mm.uid_foreign'))) - ->add($queryBuilder->expr()->eq('sys_dmail_group.uid', $queryBuilder->quoteIdentifier('g_mm.uid_local'))) - ->add($queryBuilder->expr()->eq('sys_dmail_group.uid', $queryBuilder->createNamedParameter($groupUid, \PDO::PARAM_INT))) - ->add( - $queryBuilder->expr()->neq($switchTable . '.email', $queryBuilder->createNamedParameter('')) - ) - ->add($addWhere) - ) - ->orderBy($switchTable . '.uid') - ->addOrderBy($switchTable . '.email') - ->execute(); - } - } - $outArr = array(); - while (($row = $res->fetch())) { - $outArr[] = $row['uid']; - } - return $outArr; - } - - /** - * Return all uid's from $table for a static direct mail group. - * - * @param string $table The table to select from - * @param int $uid The uid of the direct_mail group - * - * @return array The resulting array of uid's - */ - public static function getStaticIdList($table, $uid) - { - if ($table == 'fe_groups') { - $switchTable = 'fe_users'; - } else { - $switchTable = $table; - } - - $connection = GeneralUtility::makeInstance(ConnectionPool::class) - ->getConnectionForTable($table); - $queryBuilder = $connection->createQueryBuilder(); - - // fe user group uid should be in list of fe users list of user groups - // $field = $switchTable.'.usergroup'; - // $command = $table.'.uid'; - - // See comment above - // $usergroupInList = ' AND ('.$field.' LIKE \'%,\'||'.$command.'||\',%\' OR '.$field.' LIKE '.$command.'||\',%\' OR '.$field.' LIKE \'%,\'||'.$command.' OR '.$field.'='.$command.')'; - - // for fe_users and fe_group, only activated modulde_sys_dmail_newsletter - if ($switchTable == 'fe_users') { - $addWhere = $queryBuilder->expr()->eq( - $switchTable . '.module_sys_dmail_newsletter', - 1 - ); - } - - if ($table == 'fe_groups') { - $res = $queryBuilder - ->selectLiteral('DISTINCT ' . $switchTable . '.uid', $switchTable . '.email') - ->from('sys_dmail_group_mm', 'sys_dmail_group_mm') - ->innerJoin( - 'sys_dmail_group_mm', - 'sys_dmail_group', - 'sys_dmail_group', - $queryBuilder->expr()->eq('sys_dmail_group_mm.uid_local', $queryBuilder->quoteIdentifier('sys_dmail_group.uid')) - ) - ->innerJoin( - 'sys_dmail_group_mm', - $table, - $table, - $queryBuilder->expr()->eq('sys_dmail_group_mm.uid_foreign', $queryBuilder->quoteIdentifier($table . '.uid')) - ) - ->innerJoin( - $table, - $switchTable, - $switchTable, - $queryBuilder->expr()->inSet($switchTable.'.usergroup', $queryBuilder->quoteIdentifier($table.'.uid')) - ) - ->andWhere( - $queryBuilder->expr()->andX() - ->add($queryBuilder->expr()->eq('sys_dmail_group_mm.uid_local', $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT))) - ->add($queryBuilder->expr()->eq('sys_dmail_group_mm.tablenames', $queryBuilder->createNamedParameter($table))) - ->add($queryBuilder->expr()->neq($switchTable . '.email', $queryBuilder->createNamedParameter(''))) - ->add($queryBuilder->expr()->eq('sys_dmail_group.deleted', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT))) - ->add($addWhere) - ) - ->orderBy($switchTable . '.uid') - ->addOrderBy($switchTable . '.email') - ->execute(); - } else { - $res = $queryBuilder - ->selectLiteral('DISTINCT ' . $switchTable . '.uid', $switchTable . '.email') - ->from('sys_dmail_group_mm', 'sys_dmail_group_mm') - ->innerJoin( - 'sys_dmail_group_mm', - 'sys_dmail_group', - 'sys_dmail_group', - $queryBuilder->expr()->eq('sys_dmail_group_mm.uid_local', $queryBuilder->quoteIdentifier('sys_dmail_group.uid')) - ) - ->innerJoin( - 'sys_dmail_group_mm', - $switchTable, - $switchTable, - $queryBuilder->expr()->eq('sys_dmail_group_mm.uid_foreign', $queryBuilder->quoteIdentifier($switchTable . '.uid')) - ) - ->andWhere( - $queryBuilder->expr()->andX() - ->add($queryBuilder->expr()->eq('sys_dmail_group_mm.uid_local', $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT))) - ->add($queryBuilder->expr()->eq('sys_dmail_group_mm.tablenames', $queryBuilder->createNamedParameter($switchTable))) - ->add($queryBuilder->expr()->neq($switchTable . '.email', $queryBuilder->createNamedParameter(''))) - ->add($queryBuilder->expr()->eq('sys_dmail_group.deleted', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT))) - ->add($addWhere) - ) - ->orderBy($switchTable . '.uid') - ->addOrderBy($switchTable . '.email') - ->execute(); - } - - $outArr = array(); - - while (($row = $res->fetch())) { - $outArr[] = $row['uid']; - } - - if ($table == 'fe_groups') { - // get the uid of the current fe_group - $connection = GeneralUtility::makeInstance(ConnectionPool::class) - ->getConnectionForTable($table); - $queryBuilder = $connection->createQueryBuilder(); - - $res = $queryBuilder - ->selectLiteral('DISTINCT ' . $table . '.uid') - ->from($table, $table) - ->from('sys_dmail_group', 'sys_dmail_group') - ->leftJoin( - 'sys_dmail_group', - 'sys_dmail_group_mm', - 'sys_dmail_group_mm', - $queryBuilder->expr()->eq('sys_dmail_group_mm.uid_local', $queryBuilder->quoteIdentifier('sys_dmail_group.uid')) - ) - ->andWhere( - $queryBuilder->expr()->andX() - ->add($queryBuilder->expr()->eq('sys_dmail_group.uid', $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT))) - ->add($queryBuilder->expr()->eq('fe_groups.uid', $queryBuilder->quoteIdentifier('sys_dmail_group_mm.uid_foreign'))) - ->add($queryBuilder->expr()->eq('sys_dmail_group_mm.tablenames', $queryBuilder->createNamedParameter($table))) - ) - ->execute(); - - list($groupId) = $res->fetchAll(); - - // recursively get all subgroups of this fe_group - $subgroups = self::getFEgroupSubgroups($groupId); - - if (!empty($subgroups)) { - $usergroupInList = null; - foreach ($subgroups as $subgroup) { - $usergroupInList .= (($usergroupInList == null) ? null : ' OR') . ' INSTR( CONCAT(\',\',fe_users.usergroup,\',\'),CONCAT(\',' . intval($subgroup) . ',\') )'; - } - $usergroupInList = '(' . $usergroupInList . ')'; - - // fetch all fe_users from these subgroups - $connection = GeneralUtility::makeInstance(ConnectionPool::class) - ->getConnectionForTable($table); - $queryBuilder = $connection->createQueryBuilder(); - // for fe_users and fe_group, only activated modulde_sys_dmail_newsletter - if ($switchTable == 'fe_users') { - $addWhere = $queryBuilder->expr()->eq( - $switchTable . '.module_sys_dmail_newsletter', - 1 - ); - } - - $res = $queryBuilder - ->selectLiteral('DISTINCT ' . $switchTable . '.uid', $switchTable . '.email') - ->from($table, $table) - ->innerJoin( - $table, - $switchTable, - $switchTable - ) - ->orWhere($usergroupInList) - ->andWhere( - $queryBuilder->expr()->andX() - ->add($queryBuilder->expr()->neq($switchTable . '.email', $queryBuilder->createNamedParameter(''))) - ->add($addWhere) - ) - ->orderBy($switchTable . '.uid') - ->addOrderBy($switchTable . '.email') - ->execute(); - - while ($row = $res->fetch()) { - $outArr[]=$row['uid']; - } - } - } - - return $outArr; - } - - /** - * Construct the array of uid's from $table selected - * by special query of mail group of such type - * - * @param MailSelect $queryGenerator The query generator object - * @param string $table The table to select from - * @param array $group The direct_mail group record - * - * @return array The resulting query. - */ - public static function getSpecialQueryIdList(MailSelect &$queryGenerator, $table, array $group): array - { - $outArr = array(); - if ($group['query']) { - $queryGenerator->init('dmail_queryConfig', $table); - $queryGenerator->queryConfig = $queryGenerator->cleanUpQueryConfig(unserialize($group['query'])); - - $queryGenerator->extFieldLists['queryFields'] = 'uid'; - $select = $queryGenerator->getSelectQuery(); - /** @var Connection $connection */ - $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table); - $recipients = $connection->executeQuery($select)->fetchAll(); - - foreach ($recipients as $recipient) { - $outArr[] = $recipient['uid']; - } - } - return $outArr; - } - - /** - * Get all group IDs - * - * @param string $list Comma-separated ID - * @param array $parsedGroups Groups ID, which is already parsed - * @param string $perms_clause Permission clause (Where) - * - * @return array the new Group IDs - */ - public static function getMailGroups($list, array $parsedGroups, $perms_clause) - { - $groupIdList = GeneralUtility::intExplode(',', $list); - $groups = array(); - - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_dmail_group'); - $queryBuilder - ->getRestrictions() - ->removeAll() - ->add(GeneralUtility::makeInstance(DeletedRestriction::class)); - $res = $queryBuilder->select('sys_dmail_group.*') - ->from('sys_dmail_group', 'sys_dmail_group') - ->leftJoin( - 'sys_dmail_group', - 'pages', - 'pages', - $queryBuilder->expr()->eq('pages.uid', $queryBuilder->quoteIdentifier('sys_dmail_group.pid')) - ) - ->add('where', 'sys_dmail_group.uid IN (' . implode(',', $groupIdList) . ')' . - ' AND ' . $perms_clause) - ->execute(); - - while (($row=$res->fetch())) { - if ($row['type'] == 4) { - // Other mail group... - if (!in_array($row['uid'], $parsedGroups)) { - $parsedGroups[] = $row['uid']; - $groups = array_merge($groups, self::getMailGroups($row['mail_groups'], $parsedGroups, $perms_clause)); - } - } else { - // Normal mail group, just add to list - $groups[] = $row['uid']; - } - } - return $groups; - } - - /** - * Parse CSV lines into array form - * - * @param array $lines CSV lines - * @param string $fieldList List of the fields - * - * @return array parsed CSV values - */ - public static function rearrangeCsvValues(array $lines, $fieldList) - { - $out = array(); - if (is_array($lines) && count($lines)>0) { - // Analyse if first line is fieldnames. - // Required is it that every value is either - // 1) found in the list fieldsList in this class, - // 2) the value is empty (value omitted then) or - // 3) the field starts with "user_". - // In addition fields may be prepended with "[code]". - // This is used if the incoming value is true in which case '+[value]' - // adds that number to the field value (accummulation) and '=[value]' - // overrides any existing value in the field - $first = $lines[0]; - $fieldListArr = explode(',', $fieldList); - if ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['direct_mail']['addRecipFields']) { - $fieldListArr = array_merge($fieldListArr, explode(',', $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['direct_mail']['addRecipFields'])); - } - $fieldName = 1; - $fieldOrder = array(); - - foreach ($first as $v) { - list($fName, $fConf) = preg_split('|[\[\]]|', $v); - $fName = trim($fName); - $fConf = trim($fConf); - $fieldOrder[] = array($fName,$fConf); - if ($fName && substr($fName, 0, 5) != 'user_' && !in_array($fName, $fieldListArr)) { - $fieldName = 0; - break; - } - } - // If not field list, then: - if (!$fieldName) { - $fieldOrder = array(array('name'),array('email')); - } - // Re-map values - reset($lines); - if ($fieldName) { - // Advance pointer if the first line was field names - next($lines); - } - - $c = 0; - foreach ($lines as $data) { - // Must be a line with content. - // This sorts out entries with one key which is empty. Those are empty lines. - if (count($data)>1 || $data[0]) { - // Traverse fieldOrder and map values over - foreach ($fieldOrder as $kk => $fN) { - // print "Checking $kk::".t3lib_div::view_array($fN).'
'; - if ($fN[0]) { - if ($fN[1]) { - // If is true - if (trim($data[$kk])) { - if (substr($fN[1], 0, 1) == '=') { - $out[$c][$fN[0]] = trim(substr($fN[1], 1)); - } elseif (substr($fN[1], 0, 1) == '+') { - $out[$c][$fN[0]] += substr($fN[1], 1); - } - } - } else { - $out[$c][$fN[0]] = trim($data[$kk]); - } - } - } - $c++; - } - } - } - return $out; - } - /** * Rearrange emails array into a 2-dimensional array * @@ -645,9 +104,9 @@ public static function rearrangeCsvValues(array $lines, $fieldList) * * @return array a 2-dimensional array consisting email and name */ - public static function rearrangePlainMails(array $plainMails) + public static function rearrangePlainMails(array $plainMails): array { - $out = array(); + $out = []; if (is_array($plainMails)) { $c = 0; foreach ($plainMails as $v) { @@ -659,202 +118,6 @@ public static function rearrangePlainMails(array $plainMails) return $out; } - /** - * Compile the categories enables for this $row of this $table. - * - * @param string $table Table name - * @param array $row Row from table - * @param int $sysLanguageUid User language ID - * - * @return array the categories in an array with the cat id as keys - */ - public static function makeCategories($table, array $row, $sysLanguageUid) - { - $categories = array(); - - $mmField = 'module_sys_dmail_category'; - if ($table == 'sys_dmail_group') { - $mmField = 'select_categories'; - } - - $pageTsConfig = BackendUtility::getTCEFORM_TSconfig($table, $row); - if (is_array($pageTsConfig[$mmField])) { - $pidList = $pageTsConfig[$mmField]['PAGE_TSCONFIG_IDLIST']; - if ($pidList) { - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_dmail_category'); - $res = $queryBuilder->select('*') - ->from('sys_dmail_category') - ->add('where', 'sys_dmail_category.pid IN (' . str_replace(',', "','", $queryBuilder->createNamedParameter($pidList)) . ')' . - ' AND l18n_parent=0') - ->execute(); - while (($rowCat = $res->fetch())) { - if (($localizedRowCat = self::getRecordOverlay('sys_dmail_category', $rowCat, $sysLanguageUid, ''))) { - $categories[$localizedRowCat['uid']] = htmlspecialchars($localizedRowCat['category']); - } - } - } - } - return $categories; - } - - /** - * Import from t3lib_page in order to create backend version - * Creates language-overlay for records in general - * (where translation is found in records from the same table) - * - * @param string $table Table name - * @param array $row Record to overlay. Must contain uid, pid and languageField - * @param int $sys_language_content Language ID of the content - * @param string $OLmode Overlay mode. If "hideNonTranslated" then records without translation will not be returned un-translated but unset (and return value is false) - * - * @return mixed Returns the input record, possibly overlaid with a translation. But if $OLmode is "hideNonTranslated" then it will return false if no translation is found. - */ - public static function getRecordOverlay($table, array $row, $sys_language_content, $OLmode = '') - { - if ($row['uid']>0 && $row['pid']>0) { - if ($GLOBALS['TCA'][$table] && $GLOBALS['TCA'][$table]['ctrl']['languageField'] && $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']) { - if (!$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerTable']) { - // Will try to overlay a record only - // if the sys_language_content value is larger that zero. - if ($sys_language_content > 0) { - // Must be default language or [All], otherwise no overlaying: - if ($row[$GLOBALS['TCA'][$table]['ctrl']['languageField']]<=0) { - // Select overlay record: - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table); - $res = $queryBuilder->select('*') - ->from($table) - ->add('where', 'pid=' . intval($row['pid']) . - ' AND ' . $GLOBALS['TCA'][$table]['ctrl']['languageField'] . '=' . intval($sys_language_content) . - ' AND ' . $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] . '=' . intval($row['uid'])) - ->setMaxResults(1)/* LIMIT 1*/ - ->execute(); - - $olrow = $res->fetch(); - - // Merge record content by traversing all fields: - if (is_array($olrow)) { - foreach ($row as $fN => $fV) { - if ($fN!='uid' && $fN!='pid' && isset($olrow[$fN])) { - if ($GLOBALS['TCA'][$table]['l10n_mode'][$fN]!='exclude' && ($GLOBALS['TCA'][$table]['l10n_mode'][$fN]!='mergeIfNotBlank' || strcmp(trim($olrow[$fN]), ''))) { - $row[$fN] = $olrow[$fN]; - } - } - } - } elseif ($OLmode === 'hideNonTranslated' && $row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] == 0) { - // Unset, if non-translated records should be hidden. - // ONLY done if the source record really is default language and not [All] in which case it is allowed. - unset($row); - } - - // Otherwise, check if sys_language_content is different from the value of the record - // that means a japanese site might try to display french content. - } elseif ($sys_language_content!=$row[$GLOBALS['TCA'][$table]['ctrl']['languageField']]) { - unset($row); - } - } else { - // When default language is displayed, - // we never want to return a record carrying another language!: - if ($row[$GLOBALS['TCA'][$table]['ctrl']['languageField']]>0) { - unset($row); - } - } - } - } - } - - return $row; - } - - /** - * Print out an array as a table - * - * @param array $tableLines Content of the cell - * @param array $cellParams The additional cell parameter - * @param bool $header If set, the first arrray is the header of the table - * @param array $cellcmd If set, the content is HTML escaped - * @param string $tableParams The additional table parameter - * - * @return string HTML table - */ - public static function formatTable(array $tableLines, array $cellParams, $header, array $cellcmd = array(), $tableParams = 'class="table table-striped table-hover"') - { - reset($tableLines); - $cols = empty($tableLines) ? 0 : count(current($tableLines)); - - reset($tableLines); - $lines = array(); - $first = $header?1:0; - - foreach ($tableLines as $r) { - $rowA = array(); - for ($k=0; $k<$cols; $k++) { - $v = $r[$k]; - $v = strlen($v) ? ($cellcmd[$k]?$v:htmlspecialchars($v)) : ' '; - if ($first) { - $rowA[] = '' . $v . ''; - } else { - $rowA[] = '' . $v . ''; - } - } - $lines[] = '' . implode('', $rowA) . ''; - $first = 0; - } - $table = '' . implode('', $lines) . '
'; - return $table; - } - - /** - * Get the base URL - * - * @param int $pageId - * @param bool $getFullUrl - * @param string $htmlParams - * @param string $plainParams - * @return array|string Array returns if getFullUrl is true - * @throws SiteNotFoundException - * @throws InvalidRouteArgumentsException - */ - public static function getUrlBase(int $pageId, bool $getFullUrl = false, string $htmlParams = '', string $plainParams = '') - { - if ($pageId > 0) { - $pageInfo = BackendUtility::getRecord('pages', $pageId, '*'); - /** @var SiteFinder $siteFinder */ - $siteFinder = GeneralUtility::makeInstance(SiteFinder::class); - if (!empty($siteFinder->getAllSites())) { - $site = $siteFinder->getSiteByPageId($pageId); - $base = $site->getBase(); - - $baseUrl = sprintf('%s://%s', $base->getScheme(), $base->getHost()); - $htmlUrl = ''; - $plainTextUrl = ''; - - if ($getFullUrl === true) { - $route = $site->getRouter()->generateUri($pageId, ['_language' => $pageInfo['sys_language_uid']]); - $htmlUrl = $route; - $plainTextUrl = $route; - // Parse htmlUrl as string \TYPO3\CMS\Core\Http\Uri::parseUri() - if ($htmlParams !== '') { - $htmlUrl .= '?' . $htmlParams; - } else { - $htmlUrl .= ''; - } - // Parse plainTextUrl as string \TYPO3\CMS\Core\Http\Uri::parseUri() - if ($plainParams !== '') { - $plainTextUrl .= '?' . $plainParams; - } else { - $plainTextUrl .= ''; - } - } - - return $htmlUrl !== '' ? [ 'baseUrl' => $baseUrl, 'htmlUrl' => $htmlUrl, 'plainTextUrl' => $plainTextUrl] : $baseUrl; - } else { - return ''; // No site found in root line of pageId - } - } else { - return ''; // No valid pageId - } - } - /** * Get locallang label * @@ -864,371 +127,17 @@ public static function getUrlBase(int $pageId, bool $getFullUrl = false, string */ public static function fName($name) { - return stripslashes($GLOBALS['LANG']->sL(BackendUtility::getItemLabel('sys_dmail', $name))); - } - - /** - * Parsing csv-formated text to an array - * - * @param string $str String in csv-format - * @param string $sep Separator - * - * @return array Parsed csv in an array - */ - public static function getCsvValues($str, $sep=',') - { - $fh = tmpfile(); - fwrite($fh, trim($str)); - fseek($fh, 0); - $lines = array(); - if ($sep == 'tab') { - $sep = "\t"; - } - while (($data = fgetcsv($fh, 1000, $sep))) { - $lines[] = $data; - } - - fclose($fh); - return $lines; - } - - - /** - * Show DB record in HTML table format - * - * @param array $listArr All DB records to be formated - * @param string $table Table name - * @param int $pageId PageID, to which the link points to - * @param bool|int $editLinkFlag If set, edit link is showed - * @param int $sys_dmail_uid ID of the sys_dmail object - * - * @return string list of record in HTML format - */ - public static function getRecordList(array $listArr, $table, $pageId, $editLinkFlag = 1, $sys_dmail_uid = 0) - { - $count = 0; - $lines = []; - $out = ''; - - // init iconFactory - $iconFactory = GeneralUtility::makeInstance(IconFactory::class); - - $isAllowedDisplayTable = $GLOBALS['BE_USER']->check('tables_select', $table); - $isAllowedEditTable = $GLOBALS['BE_USER']->check('tables_modify', $table); - $notAllowedPlaceholder = $GLOBALS['LANG']->getLL('mailgroup_table_disallowed_placeholder'); - - if (is_array($listArr)) { - $count = count($listArr); - $returnUrl = GeneralUtility::getIndpEnv('REQUEST_URI'); - foreach ($listArr as $row) { - $tableIcon = ''; - $editLink = ''; - if ($row['uid']) { - $tableIcon = sprintf('%s', $iconFactory->getIconForRecord($table, [])); - if ($editLinkFlag && $isAllowedEditTable) { - $urlParameters = [ - 'edit' => [ - $table => [ - $row['uid'] => 'edit' - ] - ], - 'returnUrl' => $returnUrl - ]; - - $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); - $editLink = sprintf( - '%s', - $uriBuilder->buildUriFromRoute('record_edit', $urlParameters), - $GLOBALS['LANG']->getLL('dmail_edit'), - $iconFactory->getIcon('actions-open', Icon::SIZE_SMALL) - ); - } - } - - if ($isAllowedDisplayTable) { - $exampleData = [ - 'email' => ' ' . htmlspecialchars($row['email']) . ' ', - 'name' => ' ' . htmlspecialchars($row['name']) . ' ' - ]; - } else { - $exampleData = [ - 'email' => '' . $notAllowedPlaceholder . '', - 'name' => '' - ]; - } - - $lines[] = sprintf( - '%s%s%s%s', - $tableIcon, - $editLink, - $exampleData['email'], - $exampleData['name'] - ); - } - } - if (count($lines)) { - $out = $GLOBALS['LANG']->getLL('dmail_number_records') . ' ' . $count . '
'; - $out .= '' . implode(LF, $lines) . '
'; - } - - return $out; - } - - /** - * Get all subsgroups recursively. - * - * @param int $groupId Parent fe usergroup - * - * @return array The all id of fe_groups - */ - public static function getFEgroupSubgroups($groupId) - { - // get all subgroups of this fe_group - // fe_groups having this id in their subgroup field - - $table = 'fe_groups'; - $mmTable = 'sys_dmail_group_mm'; - $groupTable = 'sys_dmail_group'; - - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table); - - $res = $queryBuilder->selectLiteral('DISTINCT fe_groups.uid') - ->from($table, $table) - ->join( - $table, - $mmTable, - $mmTable, - $queryBuilder->expr()->eq( - $mmTable . '.uid_local', - $queryBuilder->quoteIdentifier($table . '.uid') - ) - ) - ->join( - $mmTable, - $groupTable, - $groupTable, - $queryBuilder->expr()->eq( - $mmTable . '.uid_local', - $queryBuilder->quoteIdentifier($groupTable . '.uid') - ) - ) - ->andWhere('INSTR( CONCAT(\',\',fe_groups.subgroup,\',\'),\',' . intval($groupId) . ',\' )') - ->execute(); - $groupArr = array(); - - while (($row = $res->fetch())) { - $groupArr[] = $row['uid']; - - // add all subgroups recursively too - $groupArr = array_merge($groupArr, self::getFEgroupSubgroups($row['uid'])); - } - - return $groupArr; + return stripslashes(self::getLanguageService()->sL(BackendUtility::getItemLabel('sys_dmail', $name))); } /** - * Creates a directmail entry in th DB. - * Used only for internal pages - * - * @param int $pageUid The page ID - * @param array $parameters The dmail Parameter - * - * @param int $sysLanguageUid - * @return int|bool new record uid or FALSE if failed + * @return LanguageService */ - public static function createDirectMailRecordFromPage($pageUid, array $parameters, $sysLanguageUid = 0) + public static function getLanguageService(): LanguageService { - $result = false; - - $newRecord = array( - 'type' => 0, - 'pid' => $parameters['pid'], - 'from_email' => $parameters['from_email'], - 'from_name' => $parameters['from_name'], - 'replyto_email' => $parameters['replyto_email'], - 'replyto_name' => $parameters['replyto_name'], - 'return_path' => $parameters['return_path'], - 'priority' => $parameters['priority'], - 'use_rdct' => (!empty($parameters['use_rdct']) ? $parameters['use_rdct']:0), /*$parameters['use_rdct'],*/ - 'long_link_mode' => (!empty($parameters['long_link_mode']) ? $parameters['long_link_mode']:0),//$parameters['long_link_mode'], - 'organisation' => $parameters['organisation'], - 'authcode_fieldList' => $parameters['authcode_fieldList'], - 'sendOptions' => $GLOBALS['TCA']['sys_dmail']['columns']['sendOptions']['config']['default'], - 'long_link_rdct_url' => self::getUrlBase((int)$pageUid), - 'sys_language_uid' => (int)$sysLanguageUid, - 'attachment' => '', - 'mailContent' => '' - ); - - if ($newRecord['sys_language_uid'] > 0) { - $langParam = self::getLanguageParam($newRecord['sys_language_uid'], $parameters); - $parameters['plainParams'] .= $langParam; - $parameters['HTMLParams'] .= $langParam; - } - - - // If params set, set default values: - $paramsToOverride = array('sendOptions', 'includeMedia', 'flowedFormat', 'HTMLParams', 'plainParams'); - foreach ($paramsToOverride as $param) { - if (isset($parameters[$param])) { - $newRecord[$param] = $parameters[$param]; - } - } - if (isset($parameters['direct_mail_encoding'])) { - $newRecord['encoding'] = $parameters['direct_mail_encoding']; - } - - $pageRecord = BackendUtility::getRecord('pages', $pageUid); - // Fetch page title from translated page - if ($newRecord['sys_language_uid'] > 0) { - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages'); - $queryBuilder - ->select('title') - ->from('pages') - ->where($queryBuilder->expr()->eq('l10n_parent', $queryBuilder->createNamedParameter($pageUid, \PDO::PARAM_INT))); - - $pageRecordOverlay = $queryBuilder->andWhere( - $queryBuilder->expr()->eq( - 'sys_language_uid', - $queryBuilder->createNamedParameter($newRecord['sys_language_uid'], \PDO::PARAM_INT) - ) - )->execute()->fetch(); - - if (is_array($pageRecordOverlay)) { - $pageRecord['title'] = $pageRecordOverlay['title']; - } - } - - if ($pageRecord['doktype']) { - $newRecord['subject'] = $pageRecord['title']; - $newRecord['page'] = $pageRecord['uid']; - $newRecord['charset'] = self::getCharacterSet(); - } - - // save to database - if ($newRecord['page'] && $newRecord['sendOptions']) { - $tcemainData = array( - 'sys_dmail' => array( - 'NEW' => $newRecord - ) - ); - - /* @var $tce \TYPO3\CMS\Core\DataHandling\DataHandler */ - $tce = GeneralUtility::makeInstance(DataHandler::class); - $tce->stripslashes_values = 0; - $tce->start($tcemainData, array()); - $tce->process_datamap(); - $result = $tce->substNEWwithIDs['NEW']; - } elseif (!$newRecord['sendOptions']) { - $result = false; - } - return $result; + return $GLOBALS['LANG']; } - - /** - * Get language param - * - * @param string $sysLanguageUid - * @param array $params direct_mail settings - * @return string - */ - public static function getLanguageParam($sysLanguageUid, array $params) - { - if (isset($params['langParams.'][$sysLanguageUid])) { - $param = $params['langParams.'][$sysLanguageUid]; - - // fallback: L == sys_language_uid - } else { - $param = '&L=' . $sysLanguageUid; - } - - return $param; - } - - - /** - * Creates a directmail entry in th DB. - * Used only for external pages - * - * @param string $subject Subject of the newsletter - * @param string $externalUrlHtml Link to the HTML version - * @param string $externalUrlPlain Linkt to the text version - * @param array $parameters Additional newsletter parameters - * - * @return int/bool Error or warning message produced during the process - */ - public static function createDirectMailRecordFromExternalURL($subject, $externalUrlHtml, $externalUrlPlain, array $parameters) - { - $result = false; - - $newRecord = array( - 'type' => 1, - 'pid' => $parameters['pid'], - 'subject' => $subject, - 'from_email' => $parameters['from_email'], - 'from_name' => $parameters['from_name'], - 'replyto_email' => $parameters['replyto_email'], - 'replyto_name' => $parameters['replyto_name'], - 'return_path' => $parameters['return_path'], - 'priority' => $parameters['priority'], - 'use_rdct' => (!empty($parameters['use_rdct']) ? $parameters['use_rdct']:0), - 'long_link_mode' => $parameters['long_link_mode'], - 'organisation' => $parameters['organisation'], - 'authcode_fieldList' => $parameters['authcode_fieldList'], - 'sendOptions' => $GLOBALS['TCA']['sys_dmail']['columns']['sendOptions']['config']['default'], - 'long_link_rdct_url' => self::getUrlBase((int)$parameters['page']) - ); - - - // If params set, set default values: - $paramsToOverride = array('sendOptions', 'includeMedia', 'flowedFormat', 'HTMLParams', 'plainParams'); - foreach ($paramsToOverride as $param) { - if (isset($parameters[$param])) { - $newRecord[$param] = $parameters[$param]; - } - } - if (isset($parameters['direct_mail_encoding'])) { - $newRecord['encoding'] = $parameters['direct_mail_encoding']; - } - - $urlParts = @parse_url($externalUrlPlain); - // No plain text url - if (!$externalUrlPlain || $urlParts === false || !$urlParts['host']) { - $newRecord['plainParams'] = ''; - $newRecord['sendOptions']&=254; - } else { - $newRecord['plainParams'] = $externalUrlPlain; - } - - // No html url - $urlParts = @parse_url($externalUrlHtml); - if (!$externalUrlHtml || $urlParts === false || !$urlParts['host']) { - $newRecord['sendOptions']&=253; - } else { - $newRecord['HTMLParams'] = $externalUrlHtml; - } - - // save to database - if ($newRecord['pid'] && $newRecord['sendOptions']) { - $tcemainData = array( - 'sys_dmail' => array( - 'NEW' => $newRecord - ) - ); - - /* @var $tce \TYPO3\CMS\Core\DataHandling\DataHandler */ - $tce = GeneralUtility::makeInstance(DataHandler::class); - $tce->stripslashes_values = 0; - $tce->start($tcemainData, array()); - $tce->process_datamap(); - $result = $tce->substNEWwithIDs['NEW']; - } elseif (!$newRecord['sendOptions']) { - $result = false; - } - return $result; - } - - + /** * Fetch content of a page (only internal and external page) * @@ -1240,9 +149,10 @@ public static function createDirectMailRecordFromExternalURL($subject, $external */ public static function fetchUrlContentsForDirectMailRecord(array $row, array $params, $returnArray = false) { + $lang = self::getLanguageService(); $theOutput = ''; - $errorMsg = array(); - $warningMsg = array(); + $errorMsg = []; + $warningMsg = []; $urls = self::getFullUrlsForDirectMailRecord($row); $plainTextUrl = $urls['plainTextUrl']; $htmlUrl = $urls['htmlUrl']; @@ -1251,11 +161,7 @@ public static function fetchUrlContentsForDirectMailRecord(array $row, array $pa // Make sure long_link_rdct_url is consistent with baseUrl. $row['long_link_rdct_url'] = $urlBase; - if (strpos($urlBase, '?') !== false ) { - $glue = '&'; - } else { - $glue = '?'; - } + $glue = (strpos($urlBase, '?') !== false ) ? '&' : '?'; // Compile the mail /* @var $htmlmail Dmailer */ @@ -1274,45 +180,47 @@ public static function fetchUrlContentsForDirectMailRecord(array $row, array $pa $htmlmail->start(); $htmlmail->charset = $row['charset']; - $htmlmail->http_username = $params['http_username']; - $htmlmail->http_password = $params['http_password']; - $htmlmail->simulateUsergroup = $params['simulate_usergroup']; + $htmlmail->simulateUsergroup = $params['simulate_usergroup'] ?? false; $htmlmail->includeMedia = $row['includeMedia']; if ($plainTextUrl) { - $mailContent = GeneralUtility::getURL(self::addUserPass($plainTextUrl, $params), 0, array('User-Agent: Direct Mail')); + $mailContent = GeneralUtility::getURL(self::addUserPass($plainTextUrl, $params)); $htmlmail->addPlain($mailContent); if (!$mailContent || !$htmlmail->theParts['plain']['content']) { - $errorMsg[] = $GLOBALS['LANG']->getLL('dmail_no_plain_content'); - } elseif (!strstr($htmlmail->theParts['plain']['content'], '', $bContent, 2); } - $this->flag_html = ($this->theParts['html']['content'] ? 1 : 0); - $this->flag_plain = ($this->theParts['plain']['content'] ? 1 : 0); + $this->flag_html = (($this->theParts['html']['content'] ?? false) ? 1 : 0); + $this->flag_plain = (($this->theParts['plain']['content'] ?? false) ? 1 : 0); $this->includeMedia = $row['includeMedia']; } @@ -234,7 +239,6 @@ public function removeHTMLComments($content) return preg_replace('/\/\*getCharsetConverter()->conv($recipRow[$substField], $this->backendCharset, $this->charset); $markers['###USER_' . strtoupper($substField) . '###'] = strtoupper($subst); @@ -270,10 +274,10 @@ public function replaceMailMarkers($content, array $recipRow, array $markers) if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/direct_mail']['res/scripts/class.dmailer.php']['mailMarkersHook'])) { $mailMarkersHook =& $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/direct_mail']['res/scripts/class.dmailer.php']['mailMarkersHook']; if (is_array($mailMarkersHook)) { - $hookParameters = array( + $hookParameters = [ 'row' => &$recipRow, 'markers' => &$markers, - ); + ]; $hookReference = &$this; foreach ($mailMarkersHook as $hookFunction) { GeneralUtility::callUserFunction($hookFunction, $hookParameters, $hookReference); @@ -298,7 +302,7 @@ public function replaceMailMarkers($content, array $recipRow, array $markers) public function dmailer_sendAdvanced(array $recipRow, $tableNameChar) { $returnCode = 0; - $tempRow = array(); + $tempRow = []; // check recipRow for HTML foreach ($recipRow as $k => $v) { @@ -314,9 +318,10 @@ public function dmailer_sendAdvanced(array $recipRow, $tableNameChar) if ($recipRow['email']) { $midRidId = 'MID' . $this->dmailer['sys_dmail_uid'] . '_' . $tableNameChar . $recipRow['uid']; $uniqMsgId = md5(microtime()) . '_' . $midRidId; - $authCode = GeneralUtility::stdAuthCode($recipRow, $this->authCode_fieldList); + // https://docs.typo3.org/c/typo3/cms-core/main/en-us/Changelog/11.3/Deprecation-94309-DeprecatedGeneralUtilitystdAuthCode.html + $authCode = GeneralUtility::stdAuthCode($recipRow, $this->authCode_fieldList); //@TODO - $additionalMarkers = array( + $additionalMarkers = [ // Put in the tablename of the userinformation '###SYS_TABLE_NAME###' => $tableNameChar, // Put in the uid of the mail-record @@ -324,7 +329,7 @@ public function dmailer_sendAdvanced(array $recipRow, $tableNameChar) '###SYS_AUTHCODE###' => $authCode, // Put in the unique message id in HTML-code $this->dmailer['messageID'] => $uniqMsgId, - ); + ]; $this->mediaList = ''; $this->theParts['html']['content'] = ''; @@ -355,7 +360,7 @@ public function dmailer_sendAdvanced(array $recipRow, $tableNameChar) $this->dmailer['sys_dmail_rec']['return_path'] = str_replace('###XID###', $midRidId, $this->dmailer['sys_dmail_rec']['return_path']); // check if the email valids - $recipient = array(); + $recipient = []; if (GeneralUtility::validEmail($recipRow['email'])) { $email = $recipRow['email']; $name = $this->ensureCorrectEncoding($recipRow['name']); @@ -379,12 +384,12 @@ public function dmailer_sendAdvanced(array $recipRow, $tableNameChar) */ public function dmailer_sendSimple($addressList) { - if ($this->theParts['html']['content']) { + if ($this->theParts['html']['content'] ?? false) { $this->theParts['html']['content'] = $this->encodeMsg($this->dmailer_getBoundaryParts($this->dmailer['boundaryParts_html'], -1)); } else { $this->theParts['html']['content'] = ''; } - if ($this->theParts['plain']['content']) { + if ($this->theParts['plain']['content'] ?? false) { $this->theParts['plain']['content'] = $this->encodeMsg($this->dmailer_getBoundaryParts($this->dmailer['boundaryParts_plain'], -1)); } else { $this->theParts['plain']['content'] = ''; @@ -417,6 +422,7 @@ public function dmailer_getBoundaryParts($cArray, $userCategories) foreach ($cArray as $bKey => $cP) { $key = substr($cP[0], 1); $isSubscribed = false; + $cP['mediaList'] = $cP['mediaList'] ?? ''; if (!$key || (intval($userCategories) == -1)) { $returnVal .= $cP[1]; $this->mediaList .= $cP['mediaList']; @@ -623,7 +629,7 @@ public function shipOfMail(int $mid, array $recipRow, string $tableKey): void public static function convertFields(array $recipRow): array { // Compensation for the fact that fe_users has the field 'telephone' instead of 'phone' - if ($recipRow['telephone']) { + if ($recipRow['telephone'] ?? false) { $recipRow['phone'] = $recipRow['telephone']; } @@ -757,7 +763,7 @@ public function dmailer_getSentMails(int $mid, string $rtbl): string */ public function dmailer_addToMailLog(int $mid, string $rid, int $size, int $parsetime, int $html, string $email): int { - list($rtbl, $rid) = explode('_', $rid); + [$rtbl, $rid] = explode('_', $rid); $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_dmail_maillog'); $queryBuilder @@ -829,10 +835,10 @@ public function runcron() if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/direct_mail']['res/scripts/class.dmailer.php']['queryInfoHook'])) { $queryInfoHook =& $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/direct_mail']['res/scripts/class.dmailer.php']['queryInfoHook']; if (is_array($queryInfoHook)) { - $hookParameters = array( + $hookParameters = [ 'row' => $row, 'query_info' => &$query_info, - ); + ]; $hookReference = &$this; foreach ($queryInfoHook as $hookFunction) { GeneralUtility::callUserFunction($hookFunction, $hookParameters, $hookReference); @@ -887,7 +893,7 @@ public function start($user_dmailer_sendPerCycle = 50, $user_dmailer_lang = 'en' // Mailer engine parameters $this->sendPerCycle = $user_dmailer_sendPerCycle; $this->user_dmailerLang = $user_dmailer_lang; - if (!$this->nonCron) { + if (isset($this->nonCron) && !$this->nonCron) { $this->logger->debug('Starting directmail cronjob'); // write this temp file for checking the engine in the status module $this->dmailer_log('starting directmail cronjob'); @@ -945,7 +951,7 @@ public function setContent(&$mailer) /** * Send of the email using php mail function. * - * @param Address $recipient The recipient to send the mail to + * @param Address|string $recipient The recipient to send the mail to * @param array $recipRow Recipient's data array * * @return void @@ -988,10 +994,10 @@ public function sendTheMail($recipient, $recipRow = null) if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/direct_mail']['res/scripts/class.dmailer.php']['mailHeadersHook'])) { $mailHeadersHook =& $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/direct_mail']['res/scripts/class.dmailer.php']['mailHeadersHook']; if (is_array($mailHeadersHook)) { - $hookParameters = array( + $hookParameters = [ 'row' => &$recipRow, 'header' => &$header, - ); + ]; $hookReference = &$this; foreach ($mailHeadersHook as $hookFunction) { GeneralUtility::callUserFunction($hookFunction, $hookParameters, $hookReference); @@ -1054,6 +1060,7 @@ public function fetchHTML($url) $urlPart['scheme'] = 'http'; } + $user = ''; if (!empty($urlPart['user'])) { $user = $urlPart['user']; if (!empty($urlPart['pass'])) { @@ -1146,7 +1153,7 @@ public function addPlain($content) */ public function substHTTPurlsInPlainText($content) { - if (!$this->jumperURL_prefix) { + if (!isset($this->jumperURL_prefix) || !$this->jumperURL_prefix) { return $content; } @@ -1215,17 +1222,17 @@ public function setHtml($content) */ public function extractMediaLinks() { - $this->theParts['html']['media'] = array(); + $this->theParts['html']['media'] = []; $htmlContent = $this->theParts['html']['content']; - $attribRegex = $this->tag_regex(array('img', 'table', 'td', 'tr', 'body', 'iframe', 'script', 'input', 'embed')); + $attribRegex = $this->tag_regex(['img', 'table', 'td', 'tr', 'body', 'iframe', 'script', 'input', 'embed']); $imageList = ''; // split the document by the beginning of the above tags $codepieces = preg_split($attribRegex, $htmlContent); $len = strlen($codepieces[0]); $pieces = count($codepieces); - $reg = array(); + $reg = []; for ($i = 1; $i < $pieces; $i++) { $tag = strtolower(strtok(substr($htmlContent, $len + 1, 10), ' ')); $len += strlen($tag) + strlen($codepieces[$i]) + 2; @@ -1233,10 +1240,10 @@ public function extractMediaLinks() // Fetches the attributes for the tag $attributes = $this->get_tag_attributes($reg[0]); - $imageData = array(); + $imageData = []; // Finds the src or background attribute - $imageData['ref'] = ($attributes['src'] ? $attributes['src'] : $attributes['background']); + $imageData['ref'] = ($attributes['src'] ?? $attributes['background'] ?? ''); if ($imageData['ref']) { // find out if the value had quotes around it $imageData['quotes'] = (substr($codepieces[$i], strpos($codepieces[$i], $imageData['ref']) - 1, 1) == '"') ? '"' : ''; @@ -1246,7 +1253,7 @@ public function extractMediaLinks() $imageList .= '|' . $imageData['subst_str'] . '|'; $imageData['absRef'] = $this->absRef($imageData['ref']); $imageData['tag'] = $tag; - $imageData['use_jumpurl'] = $attributes['dmailerping'] ? 1 : 0; + $imageData['use_jumpurl'] = (isset($attributes['dmailerping']) && $attributes['dmailerping']) ? 1 : 0; $imageData['do_not_embed'] = !empty($attributes['do_not_embed']); $this->theParts['html']['media'][] = $imageData; } @@ -1254,7 +1261,7 @@ public function extractMediaLinks() } // Extracting stylesheets - $attribRegex = $this->tag_regex(array('link')); + $attribRegex = $this->tag_regex(['link']); // Split the document by the beginning of the above tags $codepieces = preg_split($attribRegex, $htmlContent); $pieces = count($codepieces); @@ -1262,7 +1269,7 @@ public function extractMediaLinks() $dummy = preg_match('/[^>]*/', $codepieces[$i], $reg); // fetches the attributes for the tag $attributes = $this->get_tag_attributes($reg[0]); - $imageData = array(); + $imageData = []; if (strtolower($attributes['rel']) == 'stylesheet' && $attributes['href']) { // Finds the src or background attribute $imageData['ref'] = $attributes['href']; @@ -1320,7 +1327,7 @@ public function extractHyperLinks() $linkList = ''; $htmlContent = $this->theParts['html']['content']; - $attribRegex = $this->tag_regex(array('a', 'form', 'area')); + $attribRegex = $this->tag_regex(['a', 'form', 'area']); // Splits the document by the beginning of the above tags $codepieces = preg_split($attribRegex, $htmlContent); @@ -1333,8 +1340,8 @@ public function extractHyperLinks() $dummy = preg_match('/[^>]*/', $codepieces[$i], $reg); // Fetches the attributes for the tag $attributes = $this->get_tag_attributes($reg[0], false); - $hrefData = array(); - $hrefData['ref'] = $attributes['href'] ?: $attributes['action']; + $hrefData = []; + $hrefData['ref'] = ($attributes['href'] ?? '') ?: ($attributes['action'] ?? ''); $quotes = (substr($hrefData['ref'], 0, 1) === '"') ? '"' : ''; $hrefData['ref'] = trim($hrefData['ref'], '"'); if ($hrefData['ref']) { @@ -1346,7 +1353,7 @@ public function extractHyperLinks() $linkList .= '|' . $hrefData['subst_str'] . '|'; $hrefData['absRef'] = $this->absRef($hrefData['ref']); $hrefData['tag'] = $tag; - $hrefData['no_jumpurl'] = intval(trim($attributes['no_jumpurl'], '"')) ? 1 : 0; + $hrefData['no_jumpurl'] = intval(trim(($attributes['no_jumpurl'] ?? ''), '"')) ? 1 : 0; $this->theParts['html']['hrefs'][] = $hrefData; } } @@ -1361,7 +1368,7 @@ public function extractHyperLinks() $hrefData['quotes'] = "'"; // subst_str is the string to look for, when substituting lateron $hrefData['subst_str'] = $hrefData['quotes'] . $hrefData['ref'] . $hrefData['quotes']; - if ($hrefData['ref'] && !strstr($linkList, '|' . $hrefData['subst_str'] . '|')) { + if (!strstr($linkList, '|' . $hrefData['subst_str'] . '|')) { $linkList .= '|' . $hrefData['subst_str'] . '|'; $hrefData['absRef'] = $this->absRef($hrefData['ref']); $this->theParts['html']['hrefs'][] = $hrefData; @@ -1388,7 +1395,7 @@ public function extractHyperLinks() public function extractFramesInfo() { $htmlCode = $this->theParts['html']['content']; - $info = array(); + $info = []; if (strpos(' ' . $htmlCode, 'tag_regex('frame'); // Splits the document by the beginning of the above tags @@ -1398,7 +1405,7 @@ public function extractFramesInfo() $dummy = preg_match('/[^>]*/', $codepieces[$i], $reg); // Fetches the attributes for the tag $attributes = $this->get_tag_attributes($reg[0]); - $frame = array(); + $frame = []; $frame['src'] = $attributes['src']; $frame['name'] = $attributes['name']; $frame['absRef'] = $this->absRef($frame['src']); @@ -1418,7 +1425,7 @@ public function extractFramesInfo() */ public function tag_regex($tags) { - $tags = (!is_array($tags) ? array($tags) : $tags); + $tags = (!is_array($tags) ? [$tags] : $tags); $regexp = '/'; $c = count($tags); foreach ($tags as $tag) { @@ -1441,7 +1448,7 @@ public function tag_regex($tags) */ public function get_tag_attributes($tag, $removeQuotes = true) { - $attributes = array(); + $attributes = []; $tag = ltrim(preg_replace('/^<[^ ]*/', '', trim($tag))); $tagLen = strlen($tag); $safetyCounter = 100; @@ -1490,13 +1497,13 @@ public function absRef($ref) { $ref = trim($ref); $info = parse_url($ref); - if ($info['scheme']) { + if ($info['scheme'] ?? false) { // if ref is an url // do nothing } elseif (preg_match('/^\//', $ref)) { // if ref is an absolute link $addr = parse_url($this->theParts['html']['path']); - $ref = $addr['scheme'] . '://' . $addr['host'] . ($addr['port'] ? ':' . $addr['port'] : '') . $ref; + $ref = $addr['scheme'] . '://' . $addr['host'] . (($addr['port'] ?? false) ? ':' . $addr['port'] : '') . $ref; } else { // If the reference is relative, the path is added, // in order for us to fetch the content diff --git a/Classes/Hooks/TypoScriptFrontendController.php b/Classes/Hooks/TypoScriptFrontendController.php index 563fe2318..e02fd8265 100644 --- a/Classes/Hooks/TypoScriptFrontendController.php +++ b/Classes/Hooks/TypoScriptFrontendController.php @@ -14,7 +14,7 @@ * The TYPO3 project - inspiring people to share! */ -use DirectMailTeam\DirectMail\DirectMailUtility; +use DirectMailTeam\DirectMail\Utility\DmRegistryUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; /** @@ -36,17 +36,18 @@ class TypoScriptFrontendController * * @return void */ - public function simulateUsergroup($parameters, \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController $typoScriptFrontendController) + public function simulateUsergroup($parameters, \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController $typoScriptFrontendController): void { $directMailFeGroup = (int)GeneralUtility::_GET('dmail_fe_group'); - $accessToken = GeneralUtility::_GET('access_token'); - if ($directMailFeGroup > 0 && DirectMailUtility::validateAndRemoveAccessToken($accessToken)) { + $accessToken = (string)GeneralUtility::_GET('access_token'); + if ($directMailFeGroup > 0 && GeneralUtility::makeInstance(DmRegistryUtility::class)->validateAndRemoveAccessToken($accessToken)) { if ($typoScriptFrontendController->fe_user->user) { $typoScriptFrontendController->fe_user->user[$typoScriptFrontendController->usergroup_column] = $directMailFeGroup; - } else { - $typoScriptFrontendController->fe_user->user = array( + } + else { + $typoScriptFrontendController->fe_user->user = [ $typoScriptFrontendController->fe_user->usergroup_column => $directMailFeGroup - ); + ]; } } } diff --git a/Classes/Importer.php b/Classes/Importer.php index 8f30e84f8..940121c29 100644 --- a/Classes/Importer.php +++ b/Classes/Importer.php @@ -15,17 +15,21 @@ */ use DirectMailTeam\DirectMail\Module\RecipientList; +use DirectMailTeam\DirectMail\Repository\PagesRepository; +use DirectMailTeam\DirectMail\Repository\SysDmailCategoryRepository; +use DirectMailTeam\DirectMail\Repository\SysDmailTtAddressCategoryMmRepository; +use DirectMailTeam\DirectMail\Repository\TtAddressRepository; +use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\Charset\CharsetConverter; +use TYPO3\CMS\Core\Context\Context; use TYPO3\CMS\Core\Core\Environment; -use TYPO3\CMS\Core\Database\ConnectionPool; -use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction; use TYPO3\CMS\Core\DataHandling\DataHandler; use TYPO3\CMS\Core\Localization\LanguageService; +use TYPO3\CMS\Core\Resource\DuplicationBehavior; +use TYPO3\CMS\Core\Resource\ResourceFactory; use TYPO3\CMS\Core\Utility\ArrayUtility; use TYPO3\CMS\Core\Utility\File\ExtendedFileUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Backend\Utility\BackendUtility; -use TYPO3\CMS\Core\Resource\DuplicationBehavior; /** * Recipient list module for tx_directmail extension @@ -41,8 +45,8 @@ class Importer * The GET-Data * @var array */ - public $indata = array(); - public $params = array(); + public $indata = []; + public $params = []; /** * Parent object @@ -51,13 +55,6 @@ class Importer */ public $parent; - /** - * File Processor FAL - * - * @var ExtendedFileUtility - */ - public $fileProcessor; - /** * Init the class * @@ -76,19 +73,93 @@ public function init(&$pObj) /** * Import CSV-Data in step-by-step mode * - * @return string HTML form + * @return array HTML form */ - public function cmd_displayImport() + public function displayImport() { + $output = [ + 'title' => '', + 'subtitle' => '', + 'upload' => [ + 'show' => false, + 'current' => false, + 'fileInfo' => [], + 'csv' => '', + 'target' => '', + 'target_disabled' => '', + 'newFile' => '', + 'newFileUid' => 0 + ], + 'conf' => [ + 'show' => false, + 'remove_existing' => false, + 'first_fieldname' => false, + 'delimiter' => '', + 'delimiterSelected' => '', + 'encapsulation' => '', + 'valid_email' => false, + 'remove_dublette' => false, + 'update_unique' => false, + 'record_unique' => '', + 'newFile' => '', + 'newFileUid' => 0, + 'disableInput' => false + ], + 'mapping' => [ + 'show' => false, + 'charset' => '', + 'charsetSelected' => '', + 'newFile' => '', + 'newFileUid' => 0, + 'storage' => '', + 'remove_existing' => false, + 'first_fieldname' => false, + 'delimiter' => '', + 'encapsulation' => '', + 'valid_email' => false, + 'remove_dublette' => false, + 'update_unique' => false, + 'record_unique' => '', + 'all_html' => false, + 'mapping_cats' => [], + 'show_add_cat' => false, + 'add_cat' => false, + 'error' => [], + 'table' => [], + 'fields' => [] + ], + 'startImport' => [ + 'show' => false, + 'charset' => '', + 'charsetSelected' => '', + 'newFile' => '', + 'newFileUid' => 0, + 'storage' => '', + 'remove_existing' => false, + 'first_fieldname' => false, + 'delimiter' => '', + 'encapsulation' => '', + 'valid_email' => false, + 'remove_dublette' => false, + 'update_unique' => false, + 'record_unique' => '', + 'all_html' => false, + 'hiddenMap' => [], + 'hiddenCat' => [], + 'add_cat' => false, + 'tables' => [] + ] + ]; + + $beUser = $this->getBeUser(); $step = GeneralUtility::_GP('importStep'); - - $defaultConf = array( + $defaultConf = [ 'remove_existing' => 0, 'first_fieldname' => 0, 'valid_email' => 0, 'remove_dublette' => 0, 'update_unique' => 0 - ); + ]; if (GeneralUtility::_GP('CSV_IMPORT')) { $importerConfig = GeneralUtility::_GP('CSV_IMPORT'); @@ -100,65 +171,60 @@ public function cmd_displayImport() } if (empty($this->indata)) { - $this->indata = array(); + $this->indata = []; } if (empty($this->params)) { - $this->params = array(); + $this->params = []; } // merge it with inData, but inData has priority. $this->indata += $this->params; - - // $currentFileInfo = BasicFileUtility::getTotalFileInfo($this->indata['newFile']); - // $currentFileName = $currentFileInfo['file']; - // $currentFileSize = GeneralUtility::formatSize($currentFileInfo['size']); - // $currentFileMessage = $currentFileName . ' (' . $currentFileSize . ')'; - if (empty($this->indata['csv']) && !empty($_FILES['upload_1']['name'])) { - $this->indata['newFile'] = $this->checkUpload(); - // TYPO3 6.0 returns an object... - if (is_object($this->indata['newFile'][0])) { - $storageConfig = $this->indata['newFile'][0]->getStorage()->getConfiguration(); - $this->indata['newFile'] = rtrim($storageConfig['basePath'], '/') . '/' . ltrim($this->indata['newFile'][0]->getIdentifier(), '/'); - } - } elseif (!empty($this->indata['csv']) && empty($_FILES['upload_1']['name'])) { - if (((strpos($currentFileInfo['file'], 'import')=== false)?0:1) && ($currentFileInfo['realFileext'] === 'txt')) { - // do nothing - } else { - unset($this->indata['newFile']); - } + $tempFile = $this->checkUpload(); + $this->indata['newFile'] = $tempFile['newFile']; + $this->indata['newFileUid'] = $tempFile['newFileUid']; } - - if ($this->indata['back']) { + elseif (!empty($this->indata['csv']) && empty($_FILES['upload_1']['name'])) { + unset($this->indata['newFile']); + unset($this->indata['newFileUid']); + } + $stepCurrent = ''; + if ($this->indata['back'] ?? false) { $stepCurrent = $step['back']; - } elseif ($this->indata['next']) { + } + elseif ($this->indata['next'] ?? false) { $stepCurrent = $step['next']; - } elseif ($this->indata['update']) { + } + elseif ($this->indata['update'] ?? false) { $stepCurrent = 'mapping'; } - if (strlen($this->indata['csv']) > 0) { + if (strlen($this->indata['csv'] ?? '') > 0) { $this->indata['mode'] = 'csv'; - $this->indata['newFile'] = $this->writeTempFile(); - } elseif (!empty($this->indata['newFile'])) { + $tempFile = $this->writeTempFile($this->indata['csv'] ?? '', $this->indata['newFile'] ?? '', $this->indata['newFileUid'] ?? 0); + $this->indata['newFile'] = $tempFile['newFile']; + $this->indata['newFileUid'] = $tempFile['newFileUid']; + } + elseif (!empty($this->indata['newFile'])) { $this->indata['mode'] = 'file'; - } else { + } + else { unset($stepCurrent); } // check if "email" is mapped - if ($stepCurrent === 'import') { + if (isset($stepCurrent) && $stepCurrent === 'startImport') { $map = $this->indata['map']; - $error = array(); + $error = []; // check noMap $newMap = ArrayUtility::removeArrayEntryByValue(array_unique($map), 'noMap'); if (empty($newMap)) { - $error[]='noMap'; - } elseif (!in_array('email', $map)) { + $error[] = 'noMap'; + } + elseif (!in_array('email', $map)) { $error[] = 'email'; } - - if ($error) { + if (count($error)) { $stepCurrent = 'mapping'; } } @@ -166,151 +232,128 @@ public function cmd_displayImport() $out = ''; switch ($stepCurrent) { case 'conf': + $output['conf']['show'] = true; + $output['conf']['newFile'] = $this->indata['newFile']; + $output['conf']['newFileUid'] = $this->indata['newFileUid']; + + $pagePermsClause3 = $beUser->getPagePermsClause(3); + $pagePermsClause1 = $beUser->getPagePermsClause(1); // get list of sysfolder // TODO: maybe only subtree von this->id?? - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages'); - $statement = $queryBuilder - ->select('uid', 'title') - ->from('pages') - ->where( - $GLOBALS['BE_USER']->getPagePermsClause(3), - $queryBuilder->expr()->eq( - 'doktype', - '254' - ) - ) - ->orderBy('uid') - ->execute(); - - $optStorage = array(); - while (($row = $statement->fetch())) { - if (BackendUtility::readPageAccess($row['uid'], $GLOBALS['BE_USER']->getPagePermsClause(1))) { - $optStorage[] = array($row['uid'],$row['title'] . ' [uid:' . $row['uid'] . ']'); + $optStorage = []; + $subfolders = GeneralUtility::makeInstance(PagesRepository::class)->selectSubfolders($pagePermsClause3); + if($subfolders && count($subfolders)) { + foreach($subfolders as $subfolder) { + if (BackendUtility::readPageAccess($subfolder['uid'], $pagePermsClause1)) { + $optStorage[] = [ + 'val' => $subfolder['uid'], + 'text' => $subfolder['title'] . ' [uid:' . $subfolder['uid'] . ']' + ]; + } } } - $optDelimiter=array( - array('comma',$this->getLanguageService()->getLL('mailgroup_import_separator_comma')), - array('semicolon',$this->getLanguageService()->getLL('mailgroup_import_separator_semicolon')), - array('colon',$this->getLanguageService()->getLL('mailgroup_import_separator_colon')), - array('tab',$this->getLanguageService()->getLL('mailgroup_import_separator_tab')) - ); + $optDelimiter = [ + ['val' => 'comma', 'text' => $this->getLanguageService()->getLL('mailgroup_import_separator_comma')], + ['val' => 'semicolon', 'text' => $this->getLanguageService()->getLL('mailgroup_import_separator_semicolon')], + ['val' => 'colon', 'text' => $this->getLanguageService()->getLL('mailgroup_import_separator_colon')], + ['val' => 'tab', 'text' => $this->getLanguageService()->getLL('mailgroup_import_separator_tab')] + ]; - $optEncap = array( - array('doubleQuote',' " '), - array('singleQuote'," ' "), - ); + $optEncap = [ + ['val' => 'doubleQuote', 'text' => ' " '], + ['val' => 'singleQuote', 'text' => " ' "], + ]; // TODO: make it variable? - $optUnique = array( - array('email','email'), - array('name','name') - ); + $optUnique = [ + ['val' => 'email', 'text' => 'email'], + ['val' =>'name', 'text' => 'name'] + ]; - ($this->params['inputDisable'] == 1) ? $disableInput = 'disabled="disabled"' : $disableInput = ''; + $output['conf']['disableInput'] = $this->params['inputDisable'] == 1 ? true : false; // show configuration - $out = '

' . $this->getLanguageService()->getLL('mailgroup_import_header_conf') . '

'; - $tblLines = array(); + $output['subtitle'] = $this->getLanguageService()->getLL('mailgroup_import_header_conf'); // get the all sysfolder - $tblLines[] = array( - $this->getLanguageService()->getLL('mailgroup_import_storage'), - $this->makeDropdown('CSV_IMPORT[storage]', $optStorage, $this->indata['storage']) - ); + $output['conf']['storage'] = $optStorage; + $output['conf']['storageSelected'] = $this->indata['storage'] ?? ''; // remove existing option - $tblLines[] = array( - $this->getLanguageService()->getLL('mailgroup_import_remove_existing'), - 'indata['remove_existing']?'':' checked="checked"') . ' ' . $disableInput . '/> ' - ); + $output['conf']['remove_existing'] = !$this->indata['remove_existing'] ? false : true; // first line in csv is to be ignored - $tblLines[] = array( - $this->getLanguageService()->getLL('mailgroup_import_first_fieldnames'), - 'indata['first_fieldname']?'':' checked="checked"') . ' ' . $disableInput . '/> ' - ); + $output['conf']['first_fieldname'] = !$this->indata['first_fieldname'] ? false : true; // csv separator - $tblLines[] = array( - $this->getLanguageService()->getLL('mailgroup_import_separator'), - $this->makeDropdown('CSV_IMPORT[delimiter]', $optDelimiter, $this->indata['delimiter'], $disableInput) - ); - + $output['conf']['delimiter'] = $optDelimiter; + $output['conf']['delimiterSelected'] = $this->indata['delimiter'] ?? ''; + // csv encapsulation - $tblLines[] = array( - $this->getLanguageService()->getLL('mailgroup_import_encapsulation'), - $this->makeDropdown('CSV_IMPORT[encapsulation]', $optEncap, $this->indata['encapsulation'], $disableInput) - ); + $output['conf']['encapsulation'] = $optEncap; + $output['conf']['encapsulationSelected'] = $this->indata['encapsulation'] ?? ''; // import only valid email - $tblLines[] = array( - $this->getLanguageService()->getLL('mailgroup_import_csv_validemail-description'), - 'indata['valid_email']?'':' checked="checked"') . ' ' . $disableInput . '/> ' - ); + $output['conf']['valid_email'] = !$this->indata['valid_email'] ? false : true; // only import distinct records - $tblLines[] = array( - $this->getLanguageService()->getLL('mailgroup_import_csv_dublette-description'), - 'indata['remove_dublette']?'':' checked="checked"') . ' ' . $disableInput . '/> ' - ); + $output['conf']['remove_dublette'] = !$this->indata['remove_dublette'] ? false : true; // update the record instead renaming the new one - $tblLines[] = array( - $this->getLanguageService()->getLL('mailgroup_import_update_unique'), - 'indata['update_unique']?'':' checked="checked"') . ' ' . $disableInput . '/>' - ); + $output['conf']['update_unique'] = !$this->indata['update_unique'] ? false : true; // which field should be use to show uniqueness of the records - $tblLines[] = array( - $this->getLanguageService()->getLL('mailgroup_import_record_unique'), - $this->makeDropdown('CSV_IMPORT[record_unique]', $optUnique, $this->indata['record_unique'], $disableInput) - ); - - $out .= $this->formatTable($tblLines, array('width=300', 'nowrap'), 0, array(0, 1)); - $out .= '

'; - $out .= ' - ' . - $this->makeHidden(array( - 'CMD' => 'displayImport', - 'importStep[next]' => 'mapping', - 'importStep[back]' => 'upload', - 'CSV_IMPORT[newFile]' => $this->indata['newFile'])); + $output['conf']['record_unique'] = $optUnique; + $output['conf']['record_uniqueSelected'] = $this->indata['record_unique'] ?? ''; + break; case 'mapping': + $output['mapping']['show'] = true; + $output['mapping']['newFile'] = $this->indata['newFile']; + $output['mapping']['newFileUid'] = $this->indata['newFileUid']; + $output['mapping']['storage'] = $this->indata['storage']; + $output['mapping']['remove_existing'] = $this->indata['remove_existing']; + $output['mapping']['first_fieldname'] = $this->indata['first_fieldname']; + $output['mapping']['delimiter'] = $this->indata['delimiter']; + $output['mapping']['encapsulation'] = $this->indata['encapsulation']; + $output['mapping']['valid_email'] = $this->indata['valid_email']; + $output['mapping']['remove_dublette'] = $this->indata['remove_dublette']; + $output['mapping']['update_unique'] = $this->indata['update_unique']; + $output['mapping']['record_unique'] = $this->indata['record_unique']; + $output['mapping']['all_html'] = !$this->indata['all_html'] ? false : true; + $output['mapping']['error'] = $error; + // show charset selector $cs = array_unique(array_values(mb_list_encodings())); - $charSets = array(); + $charSets = []; foreach ($cs as $charset) { - $charSets[] = array($charset,$charset); + $charSets[] = ['val' => $charset, 'text' => $charset]; } if (!isset($this->indata['charset'])) { $this->indata['charset'] = 'ISO-8859-1'; } - $out .= '

' . $this->getLanguageService()->getLL('mailgroup_import_mapping_charset') . '

'; - $tblLines = array(); - $tblLines[] = array($this->getLanguageService()->getLL('mailgroup_import_mapping_charset_choose'), $this->makeDropdown('CSV_IMPORT[charset]', $charSets, $this->indata['charset'])); - $out .= $this->formatTable($tblLines, array('nowrap', 'nowrap'), 0, array(1, 1), 'border="0" cellpadding="0" cellspacing="0" class="table table-striped table-hover"'); - $out .= ''; - unset($tblLines); + $output['subtitle'] = $this->getLanguageService()->getLL('mailgroup_import_mapping_charset'); - // show mapping form - $out .= '

' . $this->getLanguageService()->getLL('mailgroup_import_mapping_conf') . '

'; + $output['mapping']['charset'] = $charSets; + $output['mapping']['charsetSelected'] = $this->indata['charset']; + $csv_firstRow = []; + // show mapping form if ($this->indata['first_fieldname']) { // read csv $csvData = $this->readExampleCSV(4); $csv_firstRow = $csvData[0]; $csvData = array_slice($csvData, 1); - } else { + } + else { // read csv $csvData = $this->readExampleCSV(3); - $fieldsAmount = count($csvData[0]); - $csv_firstRow = array(); - for ($i=0; $i<$fieldsAmount; $i++) { + $fieldsAmount = count($csvData[0] ?? []); + for ($i = 0; $i < $fieldsAmount; $i++) { $csv_firstRow[] = 'field_' . $i; } } @@ -321,257 +364,183 @@ public function cmd_displayImport() foreach ($no_map as $v) { $ttAddressFields = ArrayUtility::removeArrayEntryByValue($ttAddressFields, $v); } - $mapFields = array(); + $mapFields = []; foreach ($ttAddressFields as $map) { - $mapFields[] = array($map, str_replace(':', '', $this->getLanguageService()->sL($GLOBALS['TCA']['tt_address']['columns'][$map]['label']))); + $mapFields[] = [ + $map, + str_replace(':', '', $this->getLanguageService()->sL($GLOBALS['TCA']['tt_address']['columns'][$map]['label'])) + ]; } // add 'no value' - array_unshift($mapFields, array('noMap', $this->getLanguageService()->getLL('mailgroup_import_mapping_mapTo'))); - $mapFields[] = array('cats',$this->getLanguageService()->getLL('mailgroup_import_mapping_categories')); + array_unshift($mapFields, ['noMap', $this->getLanguageService()->getLL('mailgroup_import_mapping_mapTo')]); + $mapFields[] = [ + 'cats', + $this->getLanguageService()->getLL('mailgroup_import_mapping_categories') + ]; reset($csv_firstRow); reset($csvData); - $tblLines = array(); - $tblLines[] = array($this->getLanguageService()->getLL('mailgroup_import_mapping_number'),$this->getLanguageService()->getLL('mailgroup_import_mapping_description'),$this->getLanguageService()->getLL('mailgroup_import_mapping_mapping'),$this->getLanguageService()->getLL('mailgroup_import_mapping_value')); - for ($i=0; $i<(count($csv_firstRow)); $i++) { + $output['mapping']['fields'] = $mapFields; + for ($i = 0; $i < (count($csv_firstRow)); $i++) { // example CSV - $exampleLines = array(); - for ($j=0;$j<(count($csvData));$j++) { - $exampleLines[] = array($csvData[$j][$i]); - } - $tblLines[] = array($i+1,$csv_firstRow[$i],$this->makeDropdown('CSV_IMPORT[map][' . ($i) . ']', $mapFields, $this->indata['map'][$i]), $this->formatTable($exampleLines, array('nowrap'), 0, array(0), 'border="0" cellpadding="0" cellspacing="0" class="table table-striped table-hover" style="width:100%; border:0px; margin:0px;"')); - } - - if ($error) { - $out .= '

' . $this->getLanguageService()->getLL('mailgroup_import_mapping_error') . '

'; - $out .= $this->getLanguageService()->getLL('mailgroup_import_mapping_error_detail') . '
    '; - foreach ($error as $errorDetail) { - $out .= '
  • ' . $this->getLanguageService()->getLL('mailgroup_import_mapping_error_' . $errorDetail) . '
  • '; + $exampleLines = []; + for ($j = 0; $j < (count($csvData)); $j++) { + $exampleLines[] = $csvData[$j][$i]; } - $out.= '
'; + $output['mapping']['table'][] = [ + 'mapping_description' => $csv_firstRow[$i], + 'mapping_i' => $i, + 'mapping_mappingSelected' => $this->indata['map'][$i], + 'mapping_value' => $exampleLines + ]; } - - // additional options - $tblLinesAdd = array(); - - // header - $tblLinesAdd[] = array($this->getLanguageService()->getLL('mailgroup_import_mapping_all_html'), 'indata['all_html']?'':' checked="checked"') . '/> '); + // get categories - $temp['value'] = BackendUtility::getPagesTSconfig($this->parent->id)['TCEFORM.']['sys_dmail_group.']['select_categories.']['PAGE_TSCONFIG_IDLIST'] ?? null; + $temp['value'] = BackendUtility::getPagesTSconfig($this->parent->getId())['TCEFORM.']['sys_dmail_group.']['select_categories.']['PAGE_TSCONFIG_IDLIST'] ?? null; if (is_numeric($temp['value'])) { - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_dmail_category'); - $rowCat = $queryBuilder - ->select('*') - ->from('sys_dmail_category') - ->where( - $queryBuilder->expr()->in( - 'pid', - $temp - ) - ) - ->execute() - ->fetchAll(); - + $rowCat = GeneralUtility::makeInstance(SysDmailCategoryRepository::class)->selectSysDmailCategoryByPid((int)$temp['value']); if (!empty($rowCat)) { - $tblLinesAdd[] = array($this->getLanguageService()->getLL('mailgroup_import_mapping_cats'), ''); - if ($this->indata['update_unique']) { - $tblLinesAdd[] = array($this->getLanguageService()->getLL('mailgroup_import_mapping_cats_add'), 'indata['add_cat']?' checked="checked"':'') . '/> '); + // additional options + if ($output['mapping']['update_unique']) { + $output['mapping']['show_add_cat'] = true; + $output['mapping']['add_cat'] = $this->indata['add_cat'] ? true : false; } foreach ($rowCat as $k => $v) { - $tblLinesAdd[] = array('   ' . htmlspecialchars($v['category']), 'indata['cat'][$k]!=$v['uid'])?'':' checked="checked"') . '/> '); + $output['mapping']['mapping_cats'][] = [ + 'cat' => htmlspecialchars($v['category']), + 'k' => $k, + 'vUid' => $v['uid'], + 'checked' => $this->indata['cat'][$k] != $v['uid'] ? false : true + ]; } } } - - $out .= $this->formatTable($tblLines, array('nowrap', 'nowrap', 'nowrap', 'nowrap'), 1, array(0, 0, 1, 1), 'border="0" cellpadding="0" cellspacing="0" class="table table-striped table-hover"'); - $out .= '

'; - // additional options - $out .= '

' . $this->getLanguageService()->getLL('mailgroup_import_mapping_conf_add') . '

'; - $out .= $this->formatTable($tblLinesAdd, array('nowrap', 'nowrap'), 0, array(1, 1), 'border="0" cellpadding="0" cellspacing="0" class="table table-striped table-hover"'); - $out .= '

'; - $out .= ' - ' . - $this->makeHidden(array( - 'CMD' => 'displayImport', - 'importStep[next]' => 'import', - 'importStep[back]' => 'conf', - 'CSV_IMPORT[newFile]' => $this->indata['newFile'], - 'CSV_IMPORT[storage]' => $this->indata['storage'], - 'CSV_IMPORT[remove_existing]' => $this->indata['remove_existing'], - 'CSV_IMPORT[first_fieldname]' => $this->indata['first_fieldname'], - 'CSV_IMPORT[delimiter]' => $this->indata['delimiter'], - 'CSV_IMPORT[encapsulation]' => $this->indata['encapsulation'], - 'CSV_IMPORT[valid_email]' => $this->indata['valid_email'], - 'CSV_IMPORT[remove_dublette]' => $this->indata['remove_dublette'], - 'CSV_IMPORT[update_unique]' => $this->indata['update_unique'], - 'CSV_IMPORT[record_unique]' => $this->indata['record_unique'], - )); break; - - case 'import': - // show import messages - $out .= '

' . $this->getLanguageService()->getLL('mailgroup_import_ready_import') . '

'; - $out .= $this->getLanguageService()->getLL('mailgroup_import_ready_import_label') . '

'; - - $out .= ' - ' . - $this->makeHidden(array( - 'CMD' => 'displayImport', - 'importStep[next]' => 'startImport', - 'importStep[back]' => 'mapping', - 'CSV_IMPORT[newFile]' => $this->indata['newFile'], - 'CSV_IMPORT[storage]' => $this->indata['storage'], - 'CSV_IMPORT[remove_existing]' => $this->indata['remove_existing'], - 'CSV_IMPORT[first_fieldname]' => $this->indata['first_fieldname'], - 'CSV_IMPORT[delimiter]' => $this->indata['delimiter'], - 'CSV_IMPORT[encapsulation]' => $this->indata['encapsulation'], - 'CSV_IMPORT[valid_email]' => $this->indata['valid_email'], - 'CSV_IMPORT[remove_dublette]' => $this->indata['remove_dublette'], - 'CSV_IMPORT[update_unique]' => $this->indata['update_unique'], - 'CSV_IMPORT[record_unique]' => $this->indata['record_unique'], - 'CSV_IMPORT[all_html]' => $this->indata['all_html'], - 'CSV_IMPORT[add_cat]' => $this->indata['add_cat'], - 'CSV_IMPORT[charset]' => $this->indata['charset'], - )); - $hiddenMapped = array(); - foreach ($this->indata['map'] as $fieldNr => $fieldMapped) { - $hiddenMapped[] = $this->makeHidden('CSV_IMPORT[map][' . $fieldNr . ']', $fieldMapped); - } - if (is_array($this->indata['cat'])) { - foreach ($this->indata['cat'] as $k => $catUid) { - $hiddenMapped[] = $this->makeHidden('CSV_IMPORT[cat][' . $k . ']', $catUid); - } - } - $out.=implode('', $hiddenMapped); - break; - case 'startImport': + $output['startImport']['show'] = true; + + $output['startImport']['charsetSelected'] = $this->indata['charset']; + $output['startImport']['newFile'] = $this->indata['newFile']; + $output['startImport']['newFileUid'] = $this->indata['newFileUid']; + $output['startImport']['storage'] = $this->indata['storage']; + $output['startImport']['remove_existing'] = $this->indata['remove_existing']; + $output['startImport']['first_fieldname'] = $this->indata['first_fieldname']; + $output['startImport']['delimiter'] = $this->indata['delimiter']; + $output['startImport']['encapsulation'] = $this->indata['encapsulation']; + $output['startImport']['valid_email'] = $this->indata['valid_email']; + $output['startImport']['remove_dublette'] = $this->indata['remove_dublette']; + $output['startImport']['update_unique'] = $this->indata['update_unique']; + $output['startImport']['record_unique'] = $this->indata['record_unique']; + $output['startImport']['all_html'] = !$this->indata['all_html'] ? false : true; + $output['startImport']['add_cat'] = $this->indata['add_cat'] ? true : false; + + $output['startImport']['error'] = $error; + // starting import & show errors // read csv + $csvData = $this->readCSV(); if ($this->indata['first_fieldname']) { - // read csv - $csvData = $this->readCSV(); $csvData = array_slice($csvData, 1); - } else { - // read csv - $csvData = $this->readCSV(); } // show not imported record and reasons, $result = $this->doImport($csvData); - $out = '

' . $this->getLanguageService()->getLL('mailgroup_import_done') . '

'; - - $defaultOrder = array('new','update','invalid_email','double'); + $output['subtitle'] = $this->getLanguageService()->getLL('mailgroup_import_done'); + $resultOrder = []; if (!empty($this->params['resultOrder'])) { $resultOrder = GeneralUtility::trimExplode(',', $this->params['resultOrder']); - } else { - $resultOrder = array(); } + $defaultOrder = ['new', 'update', 'invalid_email', 'double']; $diffOrder = array_diff($defaultOrder, $resultOrder); $endOrder = array_merge($resultOrder, $diffOrder); foreach ($endOrder as $order) { - $tblLines = array(); - $tblLines[] = array($this->getLanguageService()->getLL('mailgroup_import_report_' . $order)); + $rowsTable = []; if (is_array($result[$order])) { - foreach ($result[$order] as $k => $v) { + foreach ($result[$order] as $v) { $mapKeys = array_keys($v); - $tblLines[]= array($k+1, $v[$mapKeys[0]], $v['email']); + $rowsTable[] = [ + 'val' => $v[$mapKeys[0]], + 'email' => $v['email'] + ]; } } - $out .= $this->formatTable($tblLines, array('nowrap', 'first' => 'colspan="3"'), 1, array(1)); + + $output['startImport']['tables'][] = [ + 'header' => $this->getLanguageService()->getLL('mailgroup_import_report_' . $order), + 'rows' => $rowsTable + ]; } // back button - $out .= $this->makeHidden(array( - 'CMD' => 'displayImport', - 'importStep[back]' => 'import', - 'CSV_IMPORT[newFile]' => $this->indata['newFile'], - 'CSV_IMPORT[storage]' => $this->indata['storage'], - 'CSV_IMPORT[remove_existing]' => $this->indata['remove_existing'], - 'CSV_IMPORT[first_fieldname]' => $this->indata['first_fieldname'], - 'CSV_IMPORT[delimiter]' => $this->indata['delimiter'], - 'CSV_IMPORT[encapsulation]' => $this->indata['encapsulation'], - 'CSV_IMPORT[valid_email]' => $this->indata['valid_email'], - 'CSV_IMPORT[remove_dublette]' => $this->indata['remove_dublette'], - 'CSV_IMPORT[update_unique]' => $this->indata['update_unique'], - 'CSV_IMPORT[record_unique]' => $this->indata['record_unique'], - 'CSV_IMPORT[all_html]' => $this->indata['all_html'], - 'CSV_IMPORT[charset]' => $this->indata['charset'], - )); - $hiddenMapped = array(); - foreach ($this->indata['map'] as $fieldNr => $fieldMapped) { - $hiddenMapped[] = $this->makeHidden('CSV_IMPORT[map][' . $fieldNr . ']', $fieldMapped); + if (is_array($this->indata['map'])) { + foreach ($this->indata['map'] as $fieldNr => $fieldMapped) { + $output['startImport']['hiddenMap'][] = ['name' => htmlspecialchars('CSV_IMPORT[map][' . $fieldNr . ']'), 'value' => htmlspecialchars($fieldMapped)]; + } } if (is_array($this->indata['cat'])) { foreach ($this->indata['cat'] as $k => $catUid) { - $hiddenMapped[] = $this->makeHidden('CSV_IMPORT[cat][' . $k . ']', $catUid); + $output['startImport']['hiddenCat'][] = ['name' => htmlspecialchars('CSV_IMPORT[cat][' . $k . ']'), 'value' => htmlspecialchars($catUid)]; } } - $out .=implode('', $hiddenMapped); break; case 'upload': default: // show upload file form - $out = '

' . $this->getLanguageService()->getLL('mailgroup_import_header_upload') . '

'; - $tempDir = $this->userTempFolder(); - - $tblLines[] = $this->getLanguageService()->getLL('mailgroup_import_upload_file') . ''; - if (($this->indata['mode'] === 'file') && !(((strpos($currentFileInfo['file'], 'import')=== false)?0:1) && ($currentFileInfo['realFileext'] === 'txt'))) { - $currentFileMessage = ''; - $tblLines[] = $this->getLanguageService()->getLL('mailgroup_import_current_file') . '' . $currentFileMessage . ''; + $output['subtitle'] = $this->getLanguageService()->getLL('mailgroup_import_header_upload'); + + if (($this->indata['mode'] === 'file') && !(((strpos($currentFileInfo['file'], 'import') === false) ? 0 : 1) && ($currentFileInfo['realFileext'] === 'txt'))) { + $output['upload']['current'] = true; + $file = $this->getFileById((int)$this->indata['newFileUid']); + if(is_object($file)) { + $output['upload']['fileInfo'] = [ + 'name' => $file->getName(), + 'extension' => $file->getProperty('extension'), + 'size' => GeneralUtility::formatSize($file->getProperty('size')) + ]; + } } - if (((strpos($currentFileInfo['file'], 'import')=== false)?0:1) && ($currentFileInfo['realFileext'] === 'txt')) { + if (((strpos(($currentFileInfo['file'] ?? ''), 'import') === false) ? 0 : 1) && (($currentFileInfo['realFileext'] ?? '') === 'txt')) { $handleCsv = fopen($this->indata['newFile'], 'r'); $this->indata['csv'] = fread($handleCsv, filesize($this->indata['newFile'])); fclose($handleCsv); } - - $tblLines[] = ''; - $tblLines[] = '' . $this->getLanguageService()->getLL('mailgroup_import_or') . ''; - $tblLines[] = ''; - $tblLines[] = $this->getLanguageService()->getLL('mailgroup_import_paste_csv'); - $tblLines[] = ''; - $tblLines[] = ''; - - $out .= implode('
', $tblLines); - - $out .= ' - - - - '; + + $output['upload']['show'] = true; + $output['upload']['csv'] = htmlspecialchars($this->indata['csv'] ?? ''); + $output['upload']['target'] = htmlspecialchars($this->userTempFolder()); + $output['upload']['target_disabled'] = GeneralUtility::_POST('importNow') ? 'disabled' : ''; + $output['upload']['newFile'] = $this->indata['newFile']; + $output['upload']['newFileUid'] = $this->indata['newFileUid']; } - $theOutput = sprintf( - '

%s

%s
', - $this->getLanguageService()->getLL('mailgroup_import') . BackendUtility::cshItem($this->cshTable, 'mailgroup_import', $GLOBALS['BACK_PATH']), - $out - ); + $output['title'] = $this->getLanguageService()->getLL('mailgroup_import') . BackendUtility::cshItem($this->cshTable ?? '', 'mailgroup_import'); + $theOutput = sprintf('%s', $out); /** - * Hook for cmd_displayImport + * Hook for displayImport * use it to manipulate the steps in the import process */ - if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['direct_mail/mod3/class.tx_directmail_recipient_list.php']['cmd_displayImport'])) { - $hookObjectsArr = array(); - foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['direct_mail/mod3/class.tx_directmail_recipient_list.php']['cmd_displayImport'] as $classRef) { + $hookObjectsArr = []; + if (isset($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['direct_mail/mod3/class.tx_directmail_recipient_list.php']['displayImport']) && + is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['direct_mail/mod3/class.tx_directmail_recipient_list.php']['displayImport'])) { + foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['direct_mail/mod3/class.tx_directmail_recipient_list.php']['displayImport'] as $classRef) { $hookObjectsArr[] = GeneralUtility::makeInstance($classRef); } } - if (is_array($hookObjectsArr)) { + if (count($hookObjectsArr)) { foreach ($hookObjectsArr as $hookObj) { - if (method_exists($hookObj, 'cmd_displayImport')) { - $theOutput = $hookObj->cmd_displayImport($this); + if (method_exists($hookObj, 'displayImport')) { + $theOutput = $hookObj->displayImport($this); } } } - return $theOutput; + return ['output' => $output, 'theOutput' => $theOutput]; } /***** @@ -585,16 +554,16 @@ public function cmd_displayImport() * * @return array Filtered csv and double csv */ - public function filterCSV(array $mappedCsv) + public function filterCSV(array $mappedCsv): array { $cmpCsv = $mappedCsv; - $remove = array(); - $filtered = array(); - $double = array(); + $remove = []; + $filtered = []; + $double = []; foreach ($mappedCsv as $k => $csvData) { if (!in_array($k, $remove)) { - $found=0; + $found = 0; foreach ($cmpCsv as $kk =>$cmpData) { if ($k != $kk) { if ($csvData[$this->indata['record_unique']] == $cmpData[$this->indata['record_unique']]) { @@ -602,8 +571,8 @@ public function filterCSV(array $mappedCsv) if (!$found) { $filtered[] = $csvData; } - $remove[]=$kk; - $found=1; + $remove[] = $kk; + $found = 1; } } } @@ -627,37 +596,30 @@ public function filterCSV(array $mappedCsv) */ public function doImport(array $csvData) { - $resultImport = array(); - $filteredCSV = array(); + $resultImport = []; + $filteredCSV = []; //empty table if flag is set if ($this->indata['remove_existing']) { - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tt_address'); - $queryBuilder - ->delete('tt_address') - ->where( - $queryBuilder->expr()->eq( - 'pid', - $queryBuilder->createNamedParameter($this->indata['storage']) - ) - ) - ->execute(); + GeneralUtility::makeInstance(TtAddressRepository::class)->deleteRowsByPid((int)$this->indata['storage']); } - $mappedCSV = array(); - $invalidEmailCSV = array(); + $mappedCSV = []; + $invalidEmailCSV = []; foreach ($csvData as $dataArray) { - $tempData = array(); + $tempData = []; $invalidEmail = 0; foreach ($dataArray as $kk => $fieldData) { if ($this->indata['map'][$kk] !== 'noMap') { if (($this->indata['valid_email']) && ($this->indata['map'][$kk] === 'email')) { - $invalidEmail = GeneralUtility::validEmail(trim($fieldData))?0:1; + $invalidEmail = GeneralUtility::validEmail(trim($fieldData)) ? 0 : 1; $tempData[$this->indata['map'][$kk]] = trim($fieldData); - } else { + } + else { if ($this->indata['map'][$kk] !== 'cats') { $tempData[$this->indata['map'][$kk]] = $fieldData; - } else { + } + else { $tempCats = explode(',', $fieldData); foreach ($tempCats as $catC => $tempCat) { $tempData['module_sys_dmail_category'][$catC] = $tempCat; @@ -668,8 +630,9 @@ public function doImport(array $csvData) } if ($invalidEmail) { $invalidEmailCSV[] = $tempData; - } else { - $mappedCSV[]=$tempData; + } + else { + $mappedCSV[] = $tempData; } } @@ -681,35 +644,18 @@ public function doImport(array $csvData) } // array for the process_datamap(); - $data = array(); + $data = []; if ($this->indata['update_unique']) { - $user = array(); - $userID = array(); - - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tt_address'); - // only add deleteClause - $queryBuilder - ->getRestrictions() - ->removeAll() - ->add(GeneralUtility::makeInstance(DeletedRestriction::class)); - - $statement = $queryBuilder - ->select( - 'uid', - $this->indata['record_unique'] - ) - ->from('tt_address') - ->where( - $queryBuilder->expr()->eq( - 'pid', - $this->indata['storage'] - ) - ) - ->execute(); - - while (($row = $statement->fetch())) { - $user[] = $row[1]; - $userID[] = $row[0]; + $user = []; + $userID = []; + + $rows = GeneralUtility::makeInstance(TtAddressRepository::class)->selectTtAddressByPid((int)$this->indata['storage'], $this->indata['record_unique']); + + if(is_array($rows)) { + foreach ($rows as $row) { + $user[] = $row['email']; + $userID[] = $row['uid']; + } } // check user one by one, new or update @@ -725,25 +671,11 @@ public function doImport(array $csvData) } if (is_array($this->indata['cat']) && !in_array('cats', $this->indata['map'])) { if ($this->indata['add_cat']) { - // Load already assigned categories - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_dmail_ttaddress_category_mm'); - $statement = $queryBuilder - ->select( - 'uid_local', - 'uid_foreign' - ) - ->from('sys_dmail_ttaddress_category_mm') - ->where( - $queryBuilder->expr()->eq( - 'uid_local', - $userID[$foundUser[0]] - ) - ) - ->orderBy('sorting') - ->execute(); - - while (($row = $statement->fetch())) { - $data['tt_address'][$userID[$foundUser[0]]]['module_sys_dmail_category'][] = $row[1]; + $rows = GeneralUtility::makeInstance(SysDmailTtAddressCategoryMmRepository::class)->selectUidsByUidLocal((int)$userID[$foundUser[0]]); + if(is_array($rows)) { + foreach($rows as $row) { + $data['tt_address'][$userID[$foundUser[0]]]['module_sys_dmail_category'][] = $row['uid_foreign']; + } } } // Add categories @@ -751,16 +683,18 @@ public function doImport(array $csvData) $data['tt_address'][$userID[$foundUser[0]]]['module_sys_dmail_category'][] = $v; } } - $resultImport['update'][]=$dataArray; - } else { + $resultImport['update'][] = $dataArray; + } + else { // which one to update? all? foreach ($foundUser as $kk => $_) { - $data['tt_address'][$userID[$foundUser[$kk]]]= $dataArray; + $data['tt_address'][$userID[$foundUser[$kk]]] = $dataArray; $data['tt_address'][$userID[$foundUser[$kk]]]['pid'] = $this->indata['storage']; } - $resultImport['update'][]=$dataArray; + $resultImport['update'][] = $dataArray; } - } else { + } + else { // write new user $this->addDataArray($data, 'NEW' . $c, $dataArray); $resultImport['new'][] = $dataArray; @@ -768,7 +702,8 @@ public function doImport(array $csvData) $c++; } } - } else { + } + else { // no update, import all $c = 1; foreach ($mappedCSV as $dataArray) { @@ -779,22 +714,22 @@ public function doImport(array $csvData) } $resultImport['invalid_email'] = $invalidEmailCSV; - $resultImport['double'] = (is_array($filteredCSV['double']))?$filteredCSV['double']: array(); + $resultImport['double'] = is_array($filteredCSV['double']) ? $filteredCSV['double'] : []; // start importing - /* @var $tce DataHandler */ - $tce = GeneralUtility::makeInstance(DataHandler::class); - $tce->stripslashes_values = 0; - $tce->enableLogging = 0; - $tce->start($data, array()); - $tce->process_datamap(); + /* @var $dataHandler DataHandler */ + $dataHandler = GeneralUtility::makeInstance(DataHandler::class); + $dataHandler->stripslashes_values = 0; + $dataHandler->enableLogging = 0; + $dataHandler->start($data, []); + $dataHandler->process_datamap(); /** * Hook for doImport Mail * will be called every time a record is inserted */ if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['direct_mail/mod3/class.tx_directmail_recipient_list.php']['doImport'])) { - $hookObjectsArr = array(); + $hookObjectsArr = []; foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['direct_mail/mod3/class.tx_directmail_recipient_list.php']['doImport'] as $classRef) { $hookObjectsArr[] = GeneralUtility::makeInstance($classRef); } @@ -831,54 +766,7 @@ public function addDataArray(array &$data, $id, array $dataArray) } } } - - /** - * Make dropdown menu - * - * @param string $name Name of the dropdown - * @param array $option Array of array (v,k) - * @param string $selected Set selected flag - * @param string $disableInput Flag to disable the input field - * - * @return string HTML code of the dropdown - */ - public function makeDropdown($name, array $option, $selected, $disableInput='') - { - $opt = array(); - foreach ($option as $v) { - if (is_array($v)) { - $opt[] = ''; - } - } - - return ''; - } - - /** - * Make hidden field - * - * @param mixed $name Name of the hidden field (string) or name => value (array) - * @param string $value Value of the hidden field - * - * @return string HTML code - */ - public function makeHidden($name, $value='') - { - if (is_array($name)) { - $hiddenFields = array(); - foreach ($name as $n=>$v) { - $hiddenFields[] = ''; - } - $inputFields = implode('', $hiddenFields); - } else { - $inputFields = ''; - } - - return $inputFields; - } - + /** * Read in the given CSV file. The function is used during the final file import. * Removes first the first data row if the CSV has fieldnames. @@ -887,20 +775,29 @@ public function makeHidden($name, $value='') */ public function readCSV() { - ini_set('auto_detect_line_endings', true); - $mydata = array(); - $handle = fopen($this->indata['newFile'], 'r'); - if($handle === false) { + $mydata = []; + + if((int)$this->indata['newFileUid'] < 1) { return $mydata; } - $delimiter = $this->indata['delimiter']; - $encaps = $this->indata['encapsulation']; + + $fileAbsolutePath = $this->getFileAbsolutePath((int)$this->indata['newFileUid']); + + $delimiter = $this->indata['delimiter'] ?: 'comma'; + $encaps = $this->indata['encapsulation'] ?: 'doubleQuote'; $delimiter = ($delimiter === 'comma') ? ',' : $delimiter; $delimiter = ($delimiter === 'semicolon') ? ';' : $delimiter; $delimiter = ($delimiter === 'colon') ? ':' : $delimiter; $delimiter = ($delimiter === 'tab') ? "\t" : $delimiter; $encaps = ($encaps === 'singleQuote') ? "'" : $encaps; $encaps = ($encaps === 'doubleQuote') ? '"' : $encaps; + + ini_set('auto_detect_line_endings', true); + $handle = fopen($fileAbsolutePath, 'r'); + if($handle === false) { + return $mydata; + } + while (($data = fgetcsv($handle, 10000, $delimiter, $encaps)) !== false) { // remove empty line in csv if ((count($data) >= 1)) { @@ -922,34 +819,38 @@ public function readCSV() * * @return array File content in array */ - public function readExampleCSV($records=3) + public function readExampleCSV($records = 3) { - ini_set('auto_detect_line_endings', true); - - $mydata = array(); - // TYPO3 6.0 works with relative path, we need absolute here - if (!is_file($this->indata['newFile']) && (strpos($this->indata['newFile'], Environment::getPublicPath() . '/') === false)) { - $this->indata['newFile'] = Environment::getPublicPath() . '/' . $this->indata['newFile']; - } - $handle = fopen($this->indata['newFile'], 'r'); - if($handle === false) { + $mydata = []; + + if((int)$this->indata['newFileUid'] < 1) { return $mydata; } + + $fileAbsolutePath = $this->getFileAbsolutePath((int)$this->indata['newFileUid']); + $i = 0; - $delimiter = $this->indata['delimiter']; - $encaps = $this->indata['encapsulation']; + $delimiter = $this->indata['delimiter'] ?: 'comma'; + $encaps = $this->indata['encapsulation'] ?: 'doubleQuote'; $delimiter = ($delimiter === 'comma') ? ',' : $delimiter; $delimiter = ($delimiter === 'semicolon') ? ';' : $delimiter; $delimiter = ($delimiter === 'colon') ? ':' : $delimiter; $delimiter = ($delimiter === 'tab') ? "\t" : $delimiter; $encaps = ($encaps === 'singleQuote') ? "'" : $encaps; $encaps = ($encaps === 'doubleQuote') ? '"' : $encaps; + + ini_set('auto_detect_line_endings', true); + $handle = fopen($fileAbsolutePath, 'r'); + if($handle === false) { + return $mydata; + } + while ((($data = fgetcsv($handle, 10000, $delimiter, $encaps)) !== false)) { // remove empty line in csv if ((count($data) >= 1)) { $mydata[] = $data; $i++; - if ($i>=$records) { + if ($i >= $records) { break; } } @@ -967,7 +868,7 @@ public function readExampleCSV($records=3) * @param array $data Contains values to convert * * @return array array of charset-converted values - * @see \TYPO3\CMS\Core\Charset\CharsetConverter::convArray() + * @see \TYPO3\CMS\Core\Charset\CharsetConverter::conv[] */ public function convCharset(array $data) { @@ -981,129 +882,54 @@ public function convCharset(array $data) return $data; } - - /** - * Formating the given array in to HTML table - * - * @param array $tableLines Array of table row -> array of cells - * @param array $cellParams Cells' parameter - * @param bool $header First tableLines is table header - * @param array $cellcmd Escaped cells' value - * @param string $tableParams Table's parameter - * - * @return string HTML the table - */ - public function formatTable(array $tableLines, array $cellParams, $header, array $cellcmd = array(), $tableParams='border="0" cellpadding="0" cellspacing="0" class="table table-striped table-hover"') - { - $lines = array(); - $first = $header?1:0; - $c = 0; - - reset($tableLines); - foreach ($tableLines as $r) { - $rowA = array(); - for ($k = 0, $kMax = count($r); $k < $kMax; $k++) { - $v = $r[$k]; - $v = strlen($v) ? ($cellcmd[$k]?$v:htmlspecialchars($v)) : ' '; - if ($first) { - $v = '' . $v . ''; - } - - $cellParam = array(); - if ($cellParams[$k]) { - $cellParam[] = $cellParams[$k]; - } - - if ($first && isset($cellParams['first'])) { - $cellParam[] = $cellParams['first']; - } - $rowA[] = '' . $v . ''; - } - - $lines[] = '' . implode('', $rowA) . ''; - $first = 0; - $c++; - } - return '' . implode('', $lines) . '
'; - } - - /** - * Returns first temporary folder of the user account (from $FILEMOUNTS) - * - * @return string Absolute path to first "_temp_" folder of the current user, otherwise blank. - */ - public function userTempFolder() - { - /** @var \TYPO3\CMS\Core\Resource\Folder $folder */ - $folder = $GLOBALS['BE_USER']->getDefaultUploadTemporaryFolder(); - return $folder->getPublicUrl(); - } - /** * Write CSV Data to a temporary file and will be used for the import * - * @return string path of the temp file + * @return array path and uid of the temp file */ - public function writeTempFile() + public function writeTempFile(string $csv, string $newFile, int $newFileUid) { - $newfile = ''; - $userPermissions = $GLOBALS['BE_USER']->getFilePermissions(); - - unset($this->fileProcessor); - - // add uploads/tx_directmail to user filemounts - $GLOBALS['FILEMOUNTS']['tx_directmail'] = array( - 'name' => 'direct_mail', - 'path' => GeneralUtility::getFileAbsFileName('uploads/tx_directmail/'), - 'type' - ); + $newfile = ['newFile' => '', 'newFileUid' => 0]; + $userPermissions = $this->getBeUser()->getFilePermissions(); // Initializing: - /* @var $fileProcessor ExtendedFileUtility */ - $this->fileProcessor = GeneralUtility::makeInstance(ExtendedFileUtility::class); - $this->fileProcessor->setActionPermissions($userPermissions); - $this->fileProcessor->dontCheckForUnique = 1; - - if (is_array($GLOBALS['FILEMOUNTS']) && !empty($GLOBALS['FILEMOUNTS'])) { - // we have a filemount - // do something here - } else { - // we don't have a valid file mount - // should be fixed - - // this throws a error message because we have no rights to upload files - // to our extension's own upload folder - // further investigation needed - $file['upload']['1']['target'] = GeneralUtility::getFileAbsFileName('uploads/tx_directmail/'); - } - - // Checking referer / executing: - $refInfo = parse_url(GeneralUtility::getIndpEnv('HTTP_REFERER')); - $httpHost = GeneralUtility::getIndpEnv('TYPO3_HOST_ONLY'); + /* @var $extendedFileUtility ExtendedFileUtility */ + $extendedFileUtility = GeneralUtility::makeInstance(ExtendedFileUtility::class); + $extendedFileUtility->setActionPermissions($userPermissions); + //https://docs.typo3.org/c/typo3/cms-core/11.5/en-us/Changelog/7.4/Deprecation-63603-ExtendedFileUtilitydontCheckForUniqueIsDeprecated.html + $extendedFileUtility->setExistingFilesConflictMode(DuplicationBehavior::REPLACE); if (empty($this->indata['newFile'])) { - // new file - $file['newfile']['1']['target']=$this->userTempFolder(); - $file['newfile']['1']['data']='import_' . $GLOBALS['EXEC_TIME'] . '.txt'; + // Checking referer / executing: + $refInfo = parse_url($this->parent->getHttpReferer()); + $httpHost = $this->parent->getRequestHostOnly(); + if ($httpHost != $refInfo['host'] && !$GLOBALS['TYPO3_CONF_VARS']['SYS']['doNotCheckReferer']) { - $this->fileProcessor->writeLog(0, 2, 1, 'Referer host "%s" and server host "%s" did not match!', array($refInfo['host'], $httpHost)); - } else { - $this->fileProcessor->start($file); - $newfileObj = $this->fileProcessor->func_newfile($file['newfile']['1']); - // in TYPO3 6.0 func_newfile returns an object, but we need the path to the new file name later on! + $extendedFileUtility->writeLog(0, 2, 1, 'Referer host "%s" and server host "%s" did not match!', [$refInfo['host'], $httpHost]); + } + else { + // new file + $file['newfile']['target'] = $this->userTempFolder(); + $file['newfile']['data'] = 'import_' . $this->getTimestampFromAspect() . '.txt'; + $extendedFileUtility->start($file); + $newfileObj = $extendedFileUtility->func_newfile($file['newfile']); if (is_object($newfileObj)) { $storageConfig = $newfileObj->getStorage()->getConfiguration(); - $newfile = $storageConfig['basePath'] . ltrim($newfileObj->getIdentifier(), '/'); + $newfile['newFile'] = $storageConfig['basePath'] . ltrim($newfileObj->getIdentifier(), '/'); + $newfile['newFileUid'] = $newfileObj->getUid(); } } - } else { - $newfile = $this->indata['newFile']; + } + else { + $newfile = ['newFile' => $newFile, 'newFileUid' => $newFileUid]; } - if ($newfile) { - $csvFile['data'] = $this->indata['csv'] ?? ''; - $csvFile['target'] = $newfile; - $write = $this->fileProcessor->func_edit($csvFile); + if ($newfile['newFile']) { + $csvFile = [ + 'data' => $csv, + 'target' => $newfile['newFile'] + ]; + $write = $extendedFileUtility->func_edit($csvFile); } return $newfile; } @@ -1111,43 +937,96 @@ public function writeTempFile() /** * Checks if a file has been uploaded and returns the complete physical fileinfo if so. * - * @return string the complete physical file name, including path info. + * @return array \TYPO3\CMS\Core\Resource\File the complete physical file name, including path info. * @throws \Exception */ public function checkUpload() { - $file = GeneralUtility::_GP('file'); - $fm = array(); - - $tempFolder = $this->userTempFolder(); - $array = explode('/', trim($tempFolder, '/')); - $fm = array( - $GLOBALS['EXEC_TIME'] => array( - 'path' => $tempFolder, - 'name' => array_pop($array) . '/', - ) - ); - + $newfile = ['newFile' => '', 'newFileUid' => 0]; + // Initializing: - /* @var $fileProcessor ExtendedFileUtility */ - $this->fileProcessor = GeneralUtility::makeInstance(ExtendedFileUtility::class); - $this->fileProcessor->setActionPermissions(); - $this->fileProcessor->dontCheckForUnique = 1; - + /* @var $extendedFileUtility ExtendedFileUtility */ + $extendedFileUtility = GeneralUtility::makeInstance(ExtendedFileUtility::class); + $extendedFileUtility->setActionPermissions(); + $extendedFileUtility->setExistingFilesConflictMode(DuplicationBehavior::REPLACE); + // Checking referer / executing: - $refInfo = parse_url(GeneralUtility::getIndpEnv('HTTP_REFERER')); - $httpHost = GeneralUtility::getIndpEnv('TYPO3_HOST_ONLY'); + $refInfo = parse_url($this->parent->getHttpReferer()); + $httpHost = $this->parent->getRequestHostOnly(); if ($httpHost != $refInfo['host'] && !$GLOBALS['TYPO3_CONF_VARS']['SYS']['doNotCheckReferer']) { - $this->fileProcessor->writeLog(0, 2, 1, 'Referer host "%s" and server host "%s" did not match!', array($refInfo['host'], $httpHost)); - } else { - $this->fileProcessor->start($file); - $this->fileProcessor->setExistingFilesConflictMode(DuplicationBehavior::cast(DuplicationBehavior::REPLACE)); - $newfile = $this->fileProcessor->func_upload($file['upload']['1']); + $extendedFileUtility->writeLog(0, 2, 1, 'Referer host "%s" and server host "%s" did not match!', [$refInfo['host'], $httpHost]); + } + else { + $file = GeneralUtility::_GP('file'); + $extendedFileUtility->start($file); + $extendedFileUtility->setExistingFilesConflictMode(DuplicationBehavior::cast(DuplicationBehavior::REPLACE)); + $tempFile = $extendedFileUtility->func_upload($file['upload']['1']); + + if (is_object($tempFile[0])) { + $storageConfig = $tempFile[0]->getStorage()->getConfiguration(); + $newfile = [ + 'newFile' => rtrim($storageConfig['basePath'], '/') . '/' . ltrim($tempFile[0]->getIdentifier(), '/'), + 'newFileUid' => $tempFile[0]->getUid() + ]; + } } + return $newfile; } + /** + * + * @param int $fileUid + * @return \TYPO3\CMS\Core\Resource\File|bool + */ + private function getFileById(int $fileUid) //: \TYPO3\CMS\Core\Resource\File|bool + { + $resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class); + try { + return $resourceFactory->getFileObject($fileUid); + } + catch(\TYPO3\CMS\Core\Resource\Exception\FileDoesNotExistException $e) { + + } + return false; + } + + /** + * + * @param int $fileUid + * @return string + */ + private function getFileAbsolutePath(int $fileUid): string + { + $file = $this->getFileById($fileUid); + if(!is_object($file)) { + return ''; + } + return Environment::getPublicPath() . '/' . str_replace('//', '/', $file->getStorage()->getConfiguration()['basePath'] . $file->getProperty('identifier')); + } + + /** + * Returns first temporary folder of the user account + * + * @return string Absolute path to first "_temp_" folder of the current user, otherwise blank. + */ + public function userTempFolder() + { + /** @var \TYPO3\CMS\Core\Resource\Folder $folder */ + $folder = $this->getBeUser()->getDefaultUploadTemporaryFolder(); + return $folder->getPublicUrl(); + } + + /** + * + * @return int + */ + private function getTimestampFromAspect(): int { + $context = GeneralUtility::makeInstance(Context::class); + return $context->getPropertyFromAspect('date', 'timestamp'); + } + /** * Returns LanguageService * @@ -1157,4 +1036,13 @@ protected function getLanguageService() { return $GLOBALS['LANG']; } + + /** + * + * @return BackendUserAuthentication + */ + protected function getBeUser() + { + return $GLOBALS['BE_USER']; + } } diff --git a/Classes/MailSelect.php b/Classes/MailSelect.php index 51fe4e220..ff5562e8f 100644 --- a/Classes/MailSelect.php +++ b/Classes/MailSelect.php @@ -14,12 +14,17 @@ * The TYPO3 project - inspiring people to share! */ +/* + * https://docs.typo3.org/c/typo3/cms-core/main/en-us/Changelog/11.0/Deprecation-92080-DeprecatedQueryGeneratorAndQueryView.html + * https://api.typo3.org/11.5/class_t_y_p_o3_1_1_c_m_s_1_1_core_1_1_database_1_1_query_generator.html + */ + use TYPO3\CMS\Core\Database\QueryGenerator; /** * Used to generate queries for selecting users in the database * - * @author Kasper Sk�rh�j + * @author Kasper Skårhøj * @author Stanislas Rolland * * @package TYPO3 @@ -27,7 +32,7 @@ */ class MailSelect extends QueryGenerator { - public $allowedTables = array('tt_address','fe_users'); + public $allowedTables = ['tt_address','fe_users']; /** * Build a dropdown box. override function from parent class. Limit only to 2 tables. @@ -36,21 +41,19 @@ class MailSelect extends QueryGenerator * @param string $cur Table name, which is currently selected * * @return string HTML select-field - * @see t3lib_queryGenerator::mkTableSelect() + * @see QueryGenerator::mkTableSelect() */ public function mkTableSelect($name, $cur) { - $out = ''; + $out[] = ''; + foreach ($GLOBALS['TCA'] as $tN => $value) { + if ($this->‪getBackendUserAuthentication()->check('tables_select', $tN) && in_array($tN, $this->allowedTables)) { + $out[] = ''; } } - $out.=''; - return $out; + $out[] = ''; + return implode(LF, $out); } } diff --git a/Classes/Middleware/JumpurlController.php b/Classes/Middleware/JumpurlController.php index 27c5ed1c2..27bf6bfeb 100644 --- a/Classes/Middleware/JumpurlController.php +++ b/Classes/Middleware/JumpurlController.php @@ -216,7 +216,8 @@ public function getRawRecord($table, $uid, $fields = '*') */ protected function shouldProcess(): bool { - return ($this->request->getQueryParams()['mid'] !== null); + $mid = $this->request->getQueryParams()['mid'] ?? null; + return ($mid !== null); } /** @@ -311,7 +312,8 @@ protected function initRecipientRecord($combinedRecipient): void */ protected function validateAuthCode($submittedAuthCode): void { - $authCodeToMatch = GeneralUtility::stdAuthCode( + // https://docs.typo3.org/c/typo3/cms-core/main/en-us/Changelog/11.3/Deprecation-94309-DeprecatedGeneralUtilitystdAuthCode.html + $authCodeToMatch = GeneralUtility::stdAuthCode( //@TODO $this->recipientRecord, ($this->directMailRecord['authcode_fieldList'] ?: 'uid') ); diff --git a/Classes/Module/Configuration.php b/Classes/Module/Configuration.php index f17917299..742058ca7 100644 --- a/Classes/Module/Configuration.php +++ b/Classes/Module/Configuration.php @@ -29,7 +29,7 @@ /** * Module Configuration for tx_directmail extension * - * @author Kasper Sk�rh�j + * @author Kasper Skårhøj * @author Jan-Erik Revsbech * @author Stanislas Rolland * @author Ivan-Dharma Kartolo @@ -41,7 +41,7 @@ class Configuration extends BaseScriptClass { public $TSconfPrefix = 'mod.web_modules.dmail.'; // Internal - public $params = array(); + public $params = []; public $perms_clause = ''; public $pageinfo = ''; public $sys_dmail_uid; @@ -49,11 +49,11 @@ class Configuration extends BaseScriptClass public $pages_uid; public $categories; public $id; - public $implodedParams = array(); + public $implodedParams = []; // If set a valid user table is around public $userTable; public $sys_language_uid = 0; - public $allowedTables = array('tt_address','fe_users'); + public $allowedTables = ['tt_address','fe_users']; public $MCONF; public $cshTable; public $formname = 'dmailform'; @@ -223,18 +223,17 @@ function toggleDisplay(toggleId, e, countBox) { // '; - - $markers = array( + $markers = [ 'FLASHMESSAGES' => '', 'CONTENT' => '', - ); + ]; - $docHeaderButtons = array( + $docHeaderButtons = [ 'PAGEPATH' => $this->getLanguageService()->getLL('labels.path') . ': ' . GeneralUtility::fixed_lgd_cs($this->pageinfo['_thePath'], 50), 'SHORTCUT' => '', 'CSH' => BackendUtility::cshItem($this->cshTable, '', $GLOBALS['BACK_PATH']) - ); + ]; // shortcut icon if ($GLOBALS['BE_USER']->mayMakeShortcut()) { $docHeaderButtons['SHORTCUT'] = $this->doc->makeShortcutIcon('id', implode(',', array_keys($this->MOD_MENU)), $this->MCONF['name']); @@ -242,8 +241,8 @@ function toggleDisplay(toggleId, e, countBox) { // $module = $this->pageinfo['module']; if (!$module) { - $pidrec=BackendUtility::getRecord('pages', intval($this->pageinfo['pid'])); - $module=$pidrec['module']; + $pidrec = BackendUtility::getRecord('pages', intval($this->pageinfo['pid'])); + $module = $pidrec['module']; } if ($module == 'dmail') { @@ -276,9 +275,8 @@ function toggleDisplay(toggleId, e, countBox) { // ]); } - $this->content = $this->doc->startPage($this->getLanguageService()->getLL('title')); - $this->content.= $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers, array()); + $this->content.= $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers, []); } else { // If no access or if ID == zero @@ -309,7 +307,7 @@ public function printContent() */ protected function moduleContent() { - $configArray[1] = array( + $configArray[1] = [ 'box-1' => $this->getLanguageService()->getLL('configure_default_headers'), 'from_email' => array('string', DirectMailUtility::fName('from_email'), $this->getLanguageService()->getLL('from_email.description') . '
' . $this->getLanguageService()->getLL('from_email.details')), 'from_name' => array('string', DirectMailUtility::fName('from_name'), $this->getLanguageService()->getLL('from_name.description') . '
' . $this->getLanguageService()->getLL('from_name.details')), @@ -318,7 +316,7 @@ protected function moduleContent() 'return_path' => array('string', DirectMailUtility::fName('return_path'), $this->getLanguageService()->getLL('return_path.description') . '
' . $this->getLanguageService()->getLL('return_path.details')), 'organisation' => array('string', DirectMailUtility::fName('organisation'), $this->getLanguageService()->getLL('organisation.description') . '
' . $this->getLanguageService()->getLL('organisation.details')), 'priority' => array('select', DirectMailUtility::fName('priority'), $this->getLanguageService()->getLL('priority.description') . '
' . $this->getLanguageService()->getLL('priority.details'), array(3 => $this->getLanguageService()->getLL('configure_priority_normal'), 1 => $this->getLanguageService()->getLL('configure_priority_high'), 5 => $this->getLanguageService()->getLL('configure_priority_low'))), - ); + ]; $configArray[2] = array( 'box-2' => $this->getLanguageService()->getLL('configure_default_content'), 'sendOptions' => array('select', DirectMailUtility::fName('sendOptions'), $this->getLanguageService()->getLL('sendOptions.description') . '
' . $this->getLanguageService()->getLL('sendOptions.details'), array(3 => $this->getLanguageService()->getLL('configure_plain_and_html') ,1 => $this->getLanguageService()->getLL('configure_plain_only') ,2 => $this->getLanguageService()->getLL('configure_html_only'))), @@ -387,7 +385,7 @@ protected function moduleContent() * * @return string The compiled input form */ - public function makeConfigForm(array $configArray, array$params, $dataPrefix) + public function makeConfigForm(array $configArray, array $params, $dataPrefix) { $boxFlag = 0; @@ -396,7 +394,7 @@ public function makeConfigForm(array $configArray, array$params, $dataPrefix) ' '; $wrapHelp2 = ''; - $lines = array(); + $lines = []; if (is_array($configArray)) { foreach ($configArray as $fname => $config) { if (is_array($config)) { @@ -416,7 +414,7 @@ public function makeConfigForm(array $configArray, array$params, $dataPrefix) $formEl = ''; break; case 'select': - $opt = array(); + $opt = []; foreach ($config[3] as $k => $v) { $opt[]=''; } @@ -465,7 +463,7 @@ public function makeConfigForm(array $configArray, array$params, $dataPrefix) public function updatePageTS() { if ($GLOBALS['BE_USER']->doesUserHaveAccess(BackendUtility::getRecord('pages', $this->id), 2)) { - $pageTypoScript= GeneralUtility::_GP('pageTS'); + $pageTypoScript = GeneralUtility::_GP('pageTS'); if (is_array($pageTypoScript)) { DirectMailUtility::updatePagesTSconfig($this->id, $pageTypoScript, $this->TSconfPrefix); header('Location: ' . GeneralUtility::locationHeaderUrl(GeneralUtility::getIndpEnv('REQUEST_URI'))); diff --git a/Classes/Module/ConfigurationController.php b/Classes/Module/ConfigurationController.php new file mode 100644 index 000000000..cf51c12fa --- /dev/null +++ b/Classes/Module/ConfigurationController.php @@ -0,0 +1,105 @@ +view = $this->configureTemplatePaths($currentModule); + + $this->init($request); + $this->initConfiguration($request); + $this->updatePageTS(); + + if (($this->id && $this->access) || ($this->isAdmin() && !$this->id)) { + $this->moduleTemplate->addJavaScriptCode($this->getJS($this->sys_dmail_uid)); + + $module = $this->getModulName(); + + if ($module == 'dmail') { + // Direct mail module + if (($this->pageinfo['doktype'] ?? 0) == 254) { + $this->setDefaultValues(); + $this->view->assignMultiple([ + 'implodedParams' => $this->implodedParams + ]); + } + elseif ($this->id != 0) { + $message = $this->createFlashMessage($this->getLanguageService()->getLL('dmail_noRegular'), $this->getLanguageService()->getLL('dmail_newsletters'), 1, false); + $this->messageQueue->addMessage($message); + } + } + else { + $message = $this->createFlashMessage($this->getLanguageService()->getLL('select_folder'), $this->getLanguageService()->getLL('header_conf'), 1, false); + $this->messageQueue->addMessage($message); + } + } + else { + // If no access or if ID == zero + $this->view = $this->configureTemplatePaths('NoAccess'); + $message = $this->createFlashMessage('If no access or if ID == zero', 'No Access', 1, false); + $this->messageQueue->addMessage($message); + } + + /** + * Render template and return html content + */ + $this->moduleTemplate->setContent($this->view->render()); + return new HtmlResponse($this->moduleTemplate->renderContent()); + } + + protected function initConfiguration(ServerRequestInterface $request): void { + $queryParams = $request->getQueryParams(); + $parsedBody = $request->getParsedBody(); + + $normalizedParams = $request->getAttribute('normalizedParams'); + $this->requestUri = $normalizedParams->getRequestUri(); + + $this->pageTS = $parsedBody['pageTS'] ?? $queryParams['pageTS'] ?? []; + } + + protected function setDefaultValues() + { + if (!isset($this->implodedParams['plainParams'])) { + $this->implodedParams['plainParams'] = '&type=99'; + } + if (!isset($this->implodedParams['quick_mail_charset'])) { + $this->implodedParams['quick_mail_charset'] = 'utf-8'; + } + if (!isset($this->implodedParams['direct_mail_charset'])) { + $this->implodedParams['direct_mail_charset'] = 'iso-8859-1'; + } + } + + /** + * Update the pageTS + * No return value: sent header to the same page + * + * @return void + */ + protected function updatePageTS() + { + if ($this->getBackendUser()->doesUserHaveAccess(BackendUtility::getRecord('pages', $this->id), 2)) { + if (is_array($this->pageTS) && count($this->pageTS)) { + GeneralUtility::makeInstance(TsUtility::class)->updatePagesTSconfig($this->id, $this->pageTS, $this->TSconfPrefix); + header('Location: ' . GeneralUtility::locationHeaderUrl($this->requestUri)); + } + } + } +} diff --git a/Classes/Module/Dmail.php b/Classes/Module/Dmail.php index cf490e429..53e7eb8c8 100644 --- a/Classes/Module/Dmail.php +++ b/Classes/Module/Dmail.php @@ -54,7 +54,7 @@ class Dmail extends BaseScriptClass public $TSconfPrefix = 'mod.web_modules.dmail.'; public $fieldList = 'uid,name,title,email,phone,www,address,company,city,zip,country,fax,module_sys_dmail_category,module_sys_dmail_html'; // Internal - public $params = array(); + public $params = []; public $perms_clause = ''; public $pageinfo = ''; public $sys_dmail_uid; @@ -66,18 +66,17 @@ class Dmail extends BaseScriptClass public $back; public $noView; public $mode; - public $implodedParams = array(); + public $implodedParams = []; // If set a valid user table is around public $userTable; public $sys_language_uid = 0; public $error=''; - public $allowedTables = array('tt_address','fe_users'); + public $allowedTables = ['tt_address', 'fe_users']; public $MCONF; public $cshTable; public $formname = 'dmailform'; - /** * IconFactory for skinning * @var \TYPO3\CMS\Core\Imaging\IconFactory @@ -175,11 +174,11 @@ public function main() $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/DateTimePicker'); // Define settings for Date Picker - $typo3Settings = array( + $typo3Settings = [ 'datePickerUSmode' => $GLOBALS['TYPO3_CONF_VARS']['SYS']['USdateFormat'] ? 1 : 0, - 'dateFormat' => array('j-n-Y', 'G:i j-n-Y'), - 'dateFormatUS' => array('n-j-Y', 'G:i n-j-Y'), - ); + 'dateFormat' => ['j-n-Y', 'G:i j-n-Y'], + 'dateFormatUS' => ['n-j-Y', 'G:i n-j-Y'], + ]; $this->getPageRenderer()->addInlineSettingArray('', $typo3Settings); } @@ -251,18 +250,18 @@ function toggleDisplay(toggleId, e, countBox) { // '; - $markers = array( + $markers = [ 'TITLE' => '', 'FLASHMESSAGES' => '', 'CONTENT' => '', 'WIZARDSTEPS' => '', 'NAVIGATION' => '' - ); + ]; - $docHeaderButtons = array( + $docHeaderButtons = [ 'PAGEPATH' => $this->getLanguageService()->getLL('labels.path') . ': ' . GeneralUtility::fixed_lgd_cs($this->pageinfo['_thePath'], 50), 'SHORTCUT' => '' - ); + ]; // shortcut icon if ($BE_USER->mayMakeShortcut()) { $docHeaderButtons['SHORTCUT'] = $this->doc->makeShortcutIcon('id', implode(',', array_keys($this->MOD_MENU)), $this->MCONF['name'], 1, 'btn btn-default btn-sm'); @@ -304,7 +303,7 @@ function toggleDisplay(toggleId, e, countBox) { // } $this->content = $this->doc->startPage($this->getLanguageService()->getLL('title')); - $this->content.= $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers, array()); + $this->content.= $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers, []); } else { // If no access or if ID == zero @@ -329,8 +328,8 @@ public function createDMail_quick(array $indata) { $theOutput = ''; // Set default values: - $dmail = array(); - $dmail['sys_dmail']['NEW'] = array( + $dmail = []; + $dmail['sys_dmail']['NEW'] = [ 'from_email' => $indata['senderEmail'], 'from_name' => $indata['senderName'], 'replyto_email' => $this->params['replyto_email'], @@ -342,7 +341,7 @@ public function createDMail_quick(array $indata) 'organisation' => $this->params['organisation'], 'authcode_fieldList'=> $this->params['authcode_fieldList'], 'plainParams' => '' - ); + ]; // always plaintext $dmail['sys_dmail']['NEW']['sendOptions'] = 1; @@ -368,7 +367,7 @@ public function createDMail_quick(array $indata) /* @var $tce \TYPO3\CMS\Core\DataHandling\DataHandler */ $tce = GeneralUtility::makeInstance(DataHandler::class); $tce->stripslashes_values = 0; - $tce->start($dmail, array()); + $tce->start($dmail, []); $tce->process_datamap(); $this->sys_dmail_uid = $tce->substNEWwithIDs['NEW']; @@ -483,18 +482,18 @@ public function moduleContent() $theOutput = ''; $isExternalDirectMailRecord = false; - $markers = array( + $markers = [ 'WIZARDSTEPS' => '', 'FLASHMESSAGES' => '', 'NAVIGATION' => '', 'TITLE' => '' - ); + ]; if ($this->CMD == 'delete') { $this->deleteDMail(intval(GeneralUtility::_GP('uid'))); } - $row = array(); + $row = []; if (intval($this->sys_dmail_uid)) { $row = BackendUtility::getRecord('sys_dmail', intval($this->sys_dmail_uid)); $isExternalDirectMailRecord = (is_array($row) && $row['type'] == 1); @@ -814,7 +813,7 @@ public function cmd_finalmail($direct_mail_row) $hookSelectDisabled = ''; $hookContents = ''; if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['direct_mail']['mod2']['cmd_finalmail'])) { - $hookObjectsArr = array(); + $hookObjectsArr = []; foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['direct_mail']['mod2']['cmd_finalmail'] as $classRef) { $hookObjectsArr[] = GeneralUtility::makeInstance($classRef); } @@ -852,7 +851,7 @@ public function cmd_finalmail($direct_mail_row) ->execute(); - $opt = array(); + $opt = []; $lastGroup = null; while (($group = $statement->fetch())) { $result = $this->cmd_compileMailGroup(array($group['uid'])); @@ -1193,7 +1192,7 @@ public function cmd_testmail() $msg = $this->getLanguageService()->getLL('testmail_individual_msg') . '

'; - $ids = array(); + $ids = []; foreach ($res as $row) { $ids[] = $row['uid']; @@ -1322,7 +1321,7 @@ public function cmd_displayMailGroup_test($result) public function getRecordList(array $listArr, $table, $editLinkFlag=1, $testMailLink=0) { $count = 0; - $lines = array(); + $lines = []; $out = ''; if (is_array($listArr)) { $count = count($listArr); @@ -1396,11 +1395,11 @@ public function cmd_compileMailGroup(array $groups) { // If supplied with an empty array, quit instantly as there is nothing to do if (!count($groups)) { - return array(); + return []; } // Looping through the selected array, in order to fetch recipient details - $idLists = array(); + $idLists = []; foreach ($groups as $group) { // Testing to see if group ID is a valid integer, if not - skip to next group ID $group = MathUtility::convertToPositiveInteger($group); @@ -1438,7 +1437,7 @@ public function cmd_compileMailGroup(array $groups) * manipulate the generated id_lists */ if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['direct_mail']['mod2']['cmd_compileMailGroup'])) { - $hookObjectsArr = array(); + $hookObjectsArr = []; $temporaryList = ''; foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['direct_mail']['mod2']['cmd_compileMailGroup'] as $classRef) { @@ -1469,7 +1468,7 @@ public function cmd_compileMailGroup(array $groups) */ protected function getSingleMailGroup($groupUid) { - $idLists = array(); + $idLists = []; if ($groupUid) { $mailGroup = BackendUtility::getRecord('sys_dmail_group', $groupUid); @@ -1481,7 +1480,7 @@ protected function getSingleMailGroup($groupUid) $thePages = $mailGroup['pages'] ? $mailGroup['pages'] : $this->id; // Explode the pages $pages = GeneralUtility::intExplode(',', $thePages); - $pageIdArray = array(); + $pageIdArray = []; foreach ($pages as $pageUid) { if ($pageUid > 0) { @@ -1518,7 +1517,7 @@ protected function getSingleMailGroup($groupUid) if ($whichTables&8) { // fe_groups if (!is_array($idLists['fe_users'])) { - $idLists['fe_users'] = array(); + $idLists['fe_users'] = []; } $idLists['fe_users'] = array_unique(array_merge($idLists['fe_users'], DirectMailUtility::getIdList('fe_groups', $pidList, $groupUid, $mailGroup['select_categories']))); } @@ -1650,9 +1649,9 @@ public function makeCategoriesForm(array $row) { $indata = GeneralUtility::_GP('indata'); if (is_array($indata['categories'])) { - $data = array(); + $data = []; foreach ($indata['categories'] as $recUid => $recValues) { - $enabled = array(); + $enabled = []; foreach ($recValues as $k => $b) { if ($b) { $enabled[] = $k; @@ -1664,7 +1663,7 @@ public function makeCategoriesForm(array $row) /* @var $tce \TYPO3\CMS\Core\DataHandling\DataHandler */ $tce = GeneralUtility::makeInstance(DataHandler::class); $tce->stripslashes_values = 0; - $tce->start($data, array()); + $tce->start($data, []); $tce->process_datamap(); // remove cache @@ -1873,7 +1872,7 @@ public function makeListDMail($boxId, $totalBox, $open=false) ->execute() ->fetchAll(); - $tblLines = array(); + $tblLines = []; $tblLines[] = array( '', $this->getLanguageService()->getLL('nl_l_subject'), @@ -1905,7 +1904,7 @@ public function makeListDMail($boxId, $totalBox, $open=false) $output.= '' . $imgSrc . $this->getLanguageService()->getLL('dmail_wiz1_list_dmail') . ''; $output.= '
'; $output.= '

' . $this->getLanguageService()->getLL('dmail_wiz1_list_header') . '

'; - $output.= DirectMailUtility::formatTable($tblLines, array(), 1, array(1, 1, 1, 0, 0, 1, 0, 1)); + $output.= DirectMailUtility::formatTable($tblLines, [], 1, array(1, 1, 1, 0, 0, 1, 0, 1)); $output.= '
'; return $output; } @@ -1986,7 +1985,7 @@ public function cmd_news() if (empty($rows)) { $theOutput = '

' . $this->getLanguageService()->getLL('nl_select') . '

' . $this->getLanguageService()->getLL('nl_select_msg1'); } else { - $outLines = array(); + $outLines = []; foreach ($rows as $row) { $languages = $this->getAvailablePageLanguages($row['uid']); @@ -2065,7 +2064,7 @@ public function cmd_news() $previewLink ]; } - $out = DirectMailUtility::formatTable($outLines, array(), 0, array(1, 1, 1, 1)); + $out = DirectMailUtility::formatTable($outLines, [], 0, array(1, 1, 1, 1)); $theOutput = '

' . $this->getLanguageService()->getLL('dmail_dovsk_crFromNL') . BackendUtility::cshItem($this->cshTable, 'select_newsletter', $GLOBALS['BACK_PATH']) . '

' . diff --git a/Classes/Module/DmailController.php b/Classes/Module/DmailController.php new file mode 100644 index 000000000..f42c121de --- /dev/null +++ b/Classes/Module/DmailController.php @@ -0,0 +1,2140 @@ +moduleTemplate = $moduleTemplate ?? GeneralUtility::makeInstance(ModuleTemplate::class); +// $this->getLanguageService()->includeLLFile('EXT:direct_mail/Resources/Private/Language/locallang_mod2-6.xlf'); +// $this->getLanguageService()->includeLLFile('EXT:direct_mail/Resources/Private/Language/locallang_csh_sysdmail.xlf'); +// } + + protected function initDmail(ServerRequestInterface $request): void { + $queryParams = $request->getQueryParams(); + $parsedBody = $request->getParsedBody(); + + $normalizedParams = $request->getAttribute('normalizedParams'); + $this->requestUri = $normalizedParams->getRequestUri(); + + $this->uid = (int)($parsedBody['uid'] ?? $queryParams['uid'] ?? 0); + + $update_cats = $parsedBody['update_cats'] ?? $queryParams['update_cats'] ?? false; + if ($update_cats) { + $this->cmd = 'cats'; + } + + $this->mailingMode_simple = (bool)($parsedBody['mailingMode_simple'] ?? $queryParams['mailingMode_simple'] ?? false); + if ($this->mailingMode_simple) { + $this->cmd = 'send_mail_test'; + } + + $this->backButtonPressed = (bool)($parsedBody['back'] ?? $queryParams['back'] ?? false); + + $this->currentCMD = (string)($parsedBody['currentCMD'] ?? $queryParams['currentCMD'] ?? ''); + // Create DirectMail and fetch the data + $this->fetchAtOnce = (bool)($parsedBody['fetchAtOnce'] ?? $queryParams['fetchAtOnce'] ?? false); + + $this->quickmail = $parsedBody['quickmail'] ?? $queryParams['quickmail'] ?? []; + $this->createMailFrom_UID = (int)($parsedBody['createMailFrom_UID'] ?? $queryParams['createMailFrom_UID'] ?? 0); + $this->createMailFrom_URL = (string)($parsedBody['createMailFrom_URL'] ?? $queryParams['createMailFrom_URL'] ?? ''); + $this->createMailFrom_LANG = (int)($parsedBody['createMailFrom_LANG'] ?? $queryParams['createMailFrom_LANG'] ?? 0); + $this->createMailFrom_HTMLUrl = (string)($parsedBody['createMailFrom_HTMLUrl'] ?? $queryParams['createMailFrom_HTMLUrl'] ?? ''); + $this->createMailFrom_plainUrl = (string)($parsedBody['createMailFrom_plainUrl'] ?? $queryParams['createMailFrom_plainUrl'] ?? ''); + $this->mailgroup_uid = $parsedBody['mailgroup_uid'] ?? $queryParams['mailgroup_uid'] ?? []; + $this->tt_address_uid = (int)($parsedBody['tt_address_uid'] ?? $queryParams['tt_address_uid'] ?? 0); + } + + public function indexAction(ServerRequestInterface $request) : ResponseInterface + { + $currentModule = 'Dmail'; + $this->view = $this->configureTemplatePaths($currentModule); + + $this->init($request); + $this->initDmail($request); + + // get the config from pageTS + $this->params['pid'] = intval($this->id); + + $this->cshTable = '_MOD_' . $this->moduleName; + + if (($this->id && $this->access) || ($this->isAdmin() && !$this->id)) { + $module = $this->getModulName(); + + if ($module == 'dmail') { + // Direct mail module + if (($this->pageinfo['doktype'] ?? 0) == 254) { + $markers = $this->moduleContent(); + + $this->view->assignMultiple( + [ + 'flashmessages' => $markers['FLASHMESSAGES'], + 'data' => $markers['data'] + ] + ); + } + elseif ($this->id != 0) { + $message = $this->createFlashMessage($this->getLanguageService()->getLL('dmail_noRegular'), $this->getLanguageService()->getLL('dmail_newsletters'), 1, false); + $this->messageQueue->addMessage($message); + } + } + else { + $message = $this->createFlashMessage($this->getLanguageService()->getLL('select_folder'), $this->getLanguageService()->getLL('header_directmail'), 1, false); + $this->messageQueue->addMessage($message); + } + } + else { + // If no access or if ID == zero + $this->view = $this->configureTemplatePaths('NoAccess'); + $message = $this->createFlashMessage('If no access or if ID == zero', 'No Access', 1, false); + $this->messageQueue->addMessage($message); + } + + /** + * Render template and return html content + */ + $this->moduleTemplate->setContent($this->view->render()); + return new HtmlResponse($this->moduleTemplate->renderContent()); + } + + protected function moduleContent() + { + $isExternalDirectMailRecord = false; + + $markers = [ + 'FLASHMESSAGES' => '', + 'data' => [] + ]; + + if ($this->cmd == 'delete') { + $this->deleteDMail($this->uid); + } + + $row = []; + if (intval($this->sys_dmail_uid)) { + $row = BackendUtility::getRecord('sys_dmail', $this->sys_dmail_uid); + $isExternalDirectMailRecord = (is_array($row) && $row['type'] == 1); + } + + $hideCategoryStep = false; + $tsconfig = $this->getTSConfig(); + + if ((isset($tsconfig['tx_directmail.']['hideSteps']) && + $tsconfig['tx_directmail.']['hideSteps'] === 'cat') || $isExternalDirectMailRecord) { + $hideCategoryStep = true; + } + + if ($this->backButtonPressed) { + // CMD move 1 step back + switch ($this->currentCMD) { + case 'info': + $this->cmd = ''; + break; + case 'cats': + $this->cmd = 'info'; + break; + case 'send_test': + // Same as send_mail_test + case 'send_mail_test': + if (($this->cmd == 'send_mass') && $hideCategoryStep) { + $this->cmd = 'info'; + } else { + $this->cmd = 'cats'; + } + break; + case 'send_mail_final': + // The same as send_mass + case 'send_mass': + $this->cmd = 'send_test'; + break; + default: + // Do nothing + } + } + + $nextCmd = ''; + if ($hideCategoryStep) { + $totalSteps = 4; + if ($this->cmd == 'info') { + $nextCmd = 'send_test'; + } + } else { + $totalSteps = 5; + if ($this->cmd == 'info') { + $nextCmd = 'cats'; + } + } + + $data = [ + 'navigation' => [ + 'back' => false, + 'next' => false, + 'next_error' => false, + 'totalSteps' => $totalSteps, + 'currentStep' => 1, + 'steps' => array_fill(1, $totalSteps, '') + ] + ]; + + switch ($this->cmd) { + case 'info': + // step 2: create the Direct Mail record, or use existing + $this->currentStep = 2; + $data['navigation']['currentStep'] = $this->currentStep; + $data['info'] = [ + 'currentStep' => $this->currentStep + ]; + + $fetchMessage = ''; + + // greyed out next-button if fetching is not successful (on error) + $fetchError = true; + + $quickmail = $this->quickmail; + $quickmail['send'] = $quickmail['send'] ?? false; + + // internal page + if ($this->createMailFrom_UID && !$quickmail['send']) { + $newUid = $this->createDirectMailRecordFromPage($this->createMailFrom_UID, $this->params, $this->createMailFrom_LANG); + if (is_numeric($newUid)) { + $this->sys_dmail_uid = $newUid; + // Read new record (necessary because TCEmain sets default field values) + $row = BackendUtility::getRecord('sys_dmail', $newUid); + // fetch the data + if ($this->fetchAtOnce) { + $fetchMessage = DirectMailUtility::fetchUrlContentsForDirectMailRecord($row, $this->params); + $fetchError = ((strstr($fetchMessage, $this->getLanguageService()->getLL('dmail_error')) === false) ? false : true); + } + + $data['info']['internal']['cmd'] = $nextCmd ? $nextCmd : 'cats'; + } else { + // TODO: Error message - Error while adding the DB set + } + } + // external URL + // $this->createMailFrom_URL is the External URL subject + elseif ($this->createMailFrom_URL != '' && !$quickmail['send']) { + $newUid = $this->createDirectMailRecordFromExternalURL( + $this->createMailFrom_URL, + $this->createMailFrom_HTMLUrl, + $this->createMailFrom_plainUrl, + $this->params + ); + if (is_numeric($newUid)) { + $this->sys_dmail_uid = $newUid; + // Read new record (necessary because TCEmain sets default field values) + $row = BackendUtility::getRecord('sys_dmail', $newUid); + // fetch the data + if ($this->fetchAtOnce) { + $fetchMessage = DirectMailUtility::fetchUrlContentsForDirectMailRecord($row, $this->params); + $fetchError = ((strstr($fetchMessage, $this->getLanguageService()->getLL('dmail_error')) === false) ? false : true); + } + + $data['info']['external']['cmd'] = 'send_test'; + } else { + // TODO: Error message - Error while adding the DB set + $this->error = 'no_valid_url'; + } + } + // Quickmail + elseif ($quickmail['send']) { + $temp = $this->createDMailQuick($quickmail); + if(!$temp['errorTitle']) { + $fetchError = false; + } + if($temp['errorTitle']) { + $this->messageQueue->addMessage($this->createFlashMessage($temp['errorText'], $temp['errorTitle'], 2, false)); + } + if($temp['warningTitle']) { + $this->messageQueue->addMessage($this->createFlashMessage($temp['warningText'], $temp['warningTitle'], 1, false)); + } + + $row = BackendUtility::getRecord('sys_dmail', $this->sys_dmail_uid); + + $data['info']['quickmail']['cmd'] = 'send_test'; + $data['info']['quickmail']['senderName'] = htmlspecialchars($quickmail['senderName'] ?? ''); + $data['info']['quickmail']['senderEmail'] = htmlspecialchars($quickmail['senderEmail'] ?? ''); + $data['info']['quickmail']['subject'] = htmlspecialchars($quickmail['subject'] ?? ''); + $data['info']['quickmail']['message'] = htmlspecialchars($quickmail['message'] ?? ''); + $data['info']['quickmail']['breakLines'] = ($quickmail['breakLines'] ?? false) ? (int)$quickmail['breakLines'] : 0; + } + // existing dmail + elseif ($row) { + if ($row['type'] == '1' && (empty($row['HTMLParams']) || empty($row['plainParams']))) { + // it's a quickmail + $fetchError = false; + + $data['info']['dmail']['cmd'] = 'send_test'; + + // add attachment here, since attachment added in 2nd step + $unserializedMailContent = unserialize(base64_decode($row['mailContent'])); + $temp = $this->compileQuickMail($row, $unserializedMailContent['plain']['content'] ?? '', false); + if($temp['errorTitle']) { + $this->messageQueue->addMessage($this->createFlashMessage($temp['errorText'], $temp['errorTitle'], 2, false)); + } + if($temp['warningTitle']) { + $this->messageQueue->addMessage($this->createFlashMessage($temp['warningText'], $temp['warningTitle'], 1, false)); + } + } + else { + if ($this->fetchAtOnce) { + $fetchMessage = DirectMailUtility::fetchUrlContentsForDirectMailRecord($row, $this->params); + $fetchError = ((strstr($fetchMessage, $this->getLanguageService()->getLL('dmail_error')) === false) ? false : true); + } + + $data['info']['dmail']['cmd'] = ($row['type'] == 0) ? $nextCmd : 'send_test'; + } + } + + $data['navigation']['back'] = true; + $data['navigation']['next'] = true; + $data['navigation']['next_error'] = $fetchError; + + if ($fetchMessage) { + $markers['FLASHMESSAGES'] = $fetchMessage; + } + elseif (!$fetchError && $this->fetchAtOnce) { + $message = $this->createFlashMessage( + '', + $this->getLanguageService()->getLL('dmail_wiz2_fetch_success'), + 0, + false + ); + $this->messageQueue->addMessage($message); + } + $data['info']['table'] = is_array($row) ? $this->renderRecordDetailsTable($row) : ''; + $data['info']['sys_dmail_uid'] = $this->sys_dmail_uid; + $data['info']['pages_uid'] = $row['page'] ?: ''; + $data['info']['currentCMD'] = $this->cmd; + break; + + case 'cats': + // shows category if content-based cat + $this->currentStep = 3; + $data['navigation']['currentStep'] = $this->currentStep; + $data['cats'] = [ + 'currentStep' => $this->currentStep + ]; + + $data['navigation']['back'] = true; + $data['navigation']['next'] = true; + + $indata = GeneralUtility::_GP('indata'); + $temp = $this->makeCategoriesForm($row, $indata); + $data['cats']['output'] = $temp['output'];; + $data['cats']['catsForm'] = $temp['theOutput']; + + $data['cats']['cmd'] = 'send_test'; + $data['cats']['sys_dmail_uid'] = $this->sys_dmail_uid; + $data['cats']['pages_uid'] = $this->pages_uid; + $data['cats']['currentCMD'] = $this->cmd; + break; + + case 'send_test': + // Same as send_mail_test + case 'send_mail_test': + // send test mail + $this->currentStep = (4 - (5 - $totalSteps)); + $data['navigation']['currentStep'] = $this->currentStep; + $data['test'] = [ + 'currentStep' => $this->currentStep + ]; + + $data['navigation']['back'] = true; + $data['navigation']['next'] = true; + + if ($this->cmd == 'send_mail_test') { + $this->sendMail($row); + } + $data['test']['testFormData'] = $this->getTestMailConfig(); + $data['test']['cmd'] = 'send_mass'; + $data['test']['sys_dmail_uid'] = $this->sys_dmail_uid; + $data['test']['pages_uid'] = $this->pages_uid; + $data['test']['currentCMD'] = $this->cmd; + break; + + case 'send_mail_final': + // same as send_mass + case 'send_mass': + $this->currentStep = (5 - (5 - $totalSteps)); + $data['navigation']['currentStep'] = $this->currentStep; + $data['final'] = [ + 'currentStep' => $this->currentStep + ]; + + if ($this->cmd == 'send_mass') { + $data['navigation']['back'] = true; + } + + if ($this->cmd == 'send_mail_final') { + if (is_array($this->mailgroup_uid) && count($this->mailgroup_uid)) { + $this->sendMail($row); + break; + } + else { + $message = $this->createFlashMessage( + $this->getLanguageService()->getLL('mod.no_recipients'), + '', + 1, + false + ); + $this->messageQueue->addMessage($message); + } + } + // send mass, show calendar + $data['final']['finalForm'] = $this->cmd_finalmail($row); + $data['final']['cmd'] = 'send_mail_final'; + $data['final']['sys_dmail_uid'] = $this->sys_dmail_uid; + $data['final']['pages_uid'] = $this->pages_uid; + $data['final']['currentCMD'] = $this->cmd; + break; + + default: + // choose source newsletter + $this->currentStep = 1; + + $showTabs = ['int', 'ext', 'quick', 'dmail']; + if(isset($tsconfig['tx_directmail.']['hideTabs'])) { + $hideTabs = GeneralUtility::trimExplode(',', $tsconfig['tx_directmail.']['hideTabs']); + foreach ($hideTabs as $hideTab) { + $showTabs = ArrayUtility::removeArrayEntryByValue($showTabs, $hideTab); + } + } + if (!isset($tsconfig['tx_directmail.']['defaultTab'])) { + $tsconfig['tx_directmail.']['defaultTab'] = 'dmail'; + } + + foreach ($showTabs as $showTab) { + $open = ($tsconfig['tx_directmail.']['defaultTab'] == $showTab); + switch ($showTab) { + case 'int': + $temp = $this->getConfigFormInternal(); + $temp['open'] = $open; + $data['default']['internal'] = $temp; + break; + case 'ext': + $temp = $this->getConfigFormExternal(); + $temp['open'] = $open; + $data['default']['external'] = $temp; + break; + case 'quick': + $temp = $this->getConfigFormQuickMail(); + $temp['open'] = $open; + $data['default']['quick'] = $temp; + break; + case 'dmail': + $temp = $this->getConfigFormDMail(); + $temp['open'] = $open; + $data['default']['dmail'] = $temp; + break; + default: + } + } + } + + $markers['data'] = $data; + return $markers; + } + + /** + * Showing steps number on top of every page + * + * @param int $totalSteps Total step + * + * @return string HTML + */ +/** + protected function showSteps($totalSteps) + { + $content = ''; + for ($i = 1; $i <= $totalSteps; $i++) { + $cssClass = ($i == $this->currentStep) ? 't3-wizard-item-active' : ''; + $content .= ' ' . $i . ' '; + } + return $content; + } +*/ + /** + * Makes expandable section using TYPO3-typical markup. + * + * @param int $sectionId + * @param string $title + * @param string $content + * @return string + */ +/** + protected function makeSection(string $title, string $content, bool $isOpen): string + { + static $sectionId = 1; + + return sprintf( + '
+ +
+
+ %3$s +
+
+
+ ', + $sectionId++, + $this->getLanguageService()->getLL($title), + $content + ); + } +*/ + /** + * Makes box for internal page. (first step) + * + * @return array config for form list of internal pages + */ + protected function getConfigFormInternal() + { + return [ + 'title' => 'dmail_dovsk_crFromNL', + 'news' => $this->getNews(), + 'cshItem' => BackendUtility::cshItem($this->cshTable, 'select_newsletter'), + ]; + } + + /** + * The icon for the source tab + * + * @param bool $expand State of the tab + * + * @return string + */ + protected function getNewsletterTabIcon($expand = false) + { + // opened - closes + $icon = $expand ? 'apps-pagetree-expand' : 'apps-pagetree-collapse'; + return $this->iconFactory->getIcon($icon, Icon::SIZE_SMALL); + } + + /** + * Show the list of existing directmail records, which haven't been sent + * + * @return array + * @throws RouteNotFoundException If the named route doesn't exist + */ + protected function getNews(): array + { + $rows = GeneralUtility::makeInstance(PagesRepository::class)->selectPagesForDmail($this->id, $this->perms_clause); + $data = []; + $empty = false; + if (empty($rows)) { + $empty = true; + } + else { + $iconActionsOpen = $this->getIconActionsOpen(); + foreach ($rows as $row) { + $languages = $this->getAvailablePageLanguages($row['uid']); + $createDmailLink = $this->buildUriFromRoute( + $this->moduleName, + [ + 'id' => $this->id, + 'createMailFrom_UID' => $row['uid'], + 'fetchAtOnce' => 1, + 'cmd' => 'info' + ] + ); + + $previewHTMLLink = $previewTextLink = $createLink = ''; + foreach ($languages as $languageUid => $lang) { + $langParam = $this->getLanguageParam($languageUid, $this->params); + $createLangParam = ($languageUid ? '&createMailFrom_LANG=' . $languageUid : ''); + $langIconOverlay = (count($languages) > 1 ? $lang['flagIcon'] : null); + $langTitle = (count($languages) > 1 ? ' - ' . $lang['title'] : ''); + $plainParams = $this->implodedParams['plainParams'] ?? '' . $langParam; + $htmlParams = $this->implodedParams['HTMLParams'] ?? '' . $langParam; + $htmlIcon = $this->iconFactory->getIcon('directmail-dmail-preview-html', Icon::SIZE_SMALL, $langIconOverlay); + $plainIcon = $this->iconFactory->getIcon('directmail-dmail-preview-text', Icon::SIZE_SMALL, $langIconOverlay); + $createIcon = $this->iconFactory->getIcon('directmail-dmail-new', Icon::SIZE_SMALL, $langIconOverlay); + + $attributes = \TYPO3\CMS\Backend\Routing\PreviewUriBuilder::create($row['uid'], '') + ->withRootLine(BackendUtility::BEgetRootLine($row['uid'])) + //->withSection('') + ->withAdditionalQueryParameters($htmlParams) + ->buildDispatcherDataAttributes([]); + + $serializedAttributes = GeneralUtility::implodeAttributes([ + 'href' => '#', + 'data-dispatch-action' => $attributes['dispatch-action'], + 'data-dispatch-args' => $attributes['dispatch-args'], + 'title' => htmlentities($this->getLanguageService()->getLL('nl_viewPage_HTML') . $langTitle) + ], true); + + $previewHTMLLink .= '' . $htmlIcon . ''; + + $attributes = \TYPO3\CMS\Backend\Routing\PreviewUriBuilder::create($row['uid'], '') + ->withRootLine(BackendUtility::BEgetRootLine($row['uid'])) + //->withSection('') + ->withAdditionalQueryParameters($plainParams) + ->buildDispatcherDataAttributes([]); + + $serializedAttributes = GeneralUtility::implodeAttributes([ + 'href' => '#', + 'data-dispatch-action' => $attributes['dispatch-action'], + 'data-dispatch-args' => $attributes['dispatch-args'], + 'title' => htmlentities($this->getLanguageService()->getLL('nl_viewPage_TXT') . $langTitle) + ], true); + + $previewTextLink .= '' . $plainIcon . ''; + $createLink .= '' . $createIcon . ''; + } + + switch ($this->params['sendOptions'] ?? 0) { + case 1: + $previewLink = $previewTextLink; + break; + case 2: + $previewLink = $previewHTMLLink; + break; + case 3: + // also as default + default: + $previewLink = $previewHTMLLink . '  ' . $previewTextLink; + } + + $params = [ + 'edit' => [ + 'pages' => [ + $row['uid'] => 'edit', + ] + ], + 'returnUrl' => $this->requestUri, + ]; + + $data[] = [ + 'pageIcon' => $this->iconFactory->getIconForRecord('pages', $row, Icon::SIZE_SMALL), + 'title' => htmlspecialchars($row['title']), + 'createDmailLink' => $createDmailLink, + 'createLink' => $createLink, + 'editOnClickLink' => DirectMailUtility::getEditOnClickLink($params), + 'iconActionsOpen' => $iconActionsOpen, + 'previewLink' => $previewLink + ]; + } + } + + return ['empty' => $empty, 'rows' => $data]; + } + + /** + * Get available languages for a page + * + * @param $pageUid + * @return array + */ + protected function getAvailablePageLanguages($pageUid) + { + static $languages; + $languageUids = []; + + if ($languages === null) { + $languages = GeneralUtility::makeInstance(TranslationConfigurationProvider::class)->getSystemLanguages(); + } + + // loop trough all sys languages and check if there is matching page translation + foreach ($languages as $lang) { + // we skip -1 + if ((int)$lang['uid'] < 0) { + continue; + } + + // 0 is always present so only for > 0 + if ((int)$lang['uid'] > 0) { + $langRow = GeneralUtility::makeInstance(PagesRepository::class)->selectPageByL10nAndSysLanguageUid($pageUid, $lang['uid']); + + if (!$langRow || empty($langRow)) { + continue; + } + } + + $languageUids[(int)$lang['uid']] = $lang; + } + + return $languageUids; + } + + /** + * Makes config for form for external URL (first step) + * + * @return array config for form for inputing the external page information + */ + protected function getConfigFormExternal() + { + return [ + 'title' => 'dmail_dovsk_crFromUrl', + 'cshItem' => BackendUtility::cshItem($this->cshTable, 'create_directmail_from_url'), + 'no_valid_url' => (bool)($this->error == 'no_valid_url') + ]; + } + + /** + * Makes config for form for the quickmail (first step) + * + * @return array config for form for the quickmail + */ + protected function getConfigFormQuickMail() + { + return [ + 'id' => $this->id, + 'senderName' => htmlspecialchars($this->quickmail['senderName'] ?? $this->getBackendUser()->user['realName']), + 'senderMail' => htmlspecialchars($this->quickmail['senderEmail'] ?? $this->getBackendUser()->user['email']), + 'subject' => htmlspecialchars($this->quickmail['subject'] ?? ''), + 'message' => htmlspecialchars($this->quickmail['message'] ?? ''), + 'breakLines' => (bool)($this->quickmail['breakLines'] ?? false) + ]; + } + + /** + * List all direct mail, which have not been sent (first step) + * + * @return array config for form lists of all existing dmail records + */ + protected function getConfigFormDMail() + { + $sOrder = preg_replace( + '/^(?:ORDER[[:space:]]*BY[[:space:]]*)+/i', '', + trim($GLOBALS['TCA']['sys_dmail']['ctrl']['default_sortby']) + ); + if (!empty($sOrder)){ + if (substr_count($sOrder, 'ASC') > 0 ){ + $sOrder = trim(str_replace('ASC','',$sOrder)); + $ascDesc = 'ASC'; + } + else{ + $sOrder = trim(str_replace('DESC','',$sOrder)); + $ascDesc = 'DESC'; + } + } + $rows = GeneralUtility::makeInstance(SysDmailRepository::class)->selectForMkeListDMail($this->id, $sOrder, $ascDesc); + + $data = []; + foreach ($rows as $row) { + $data[] = [ + 'icon' => $this->iconFactory->getIconForRecord('sys_dmail', $row, Icon::SIZE_SMALL)->render(), + 'link' => $this->linkDMailRecord($row['uid']), + 'linkText' => htmlspecialchars($row['subject'] ?: '_'), + 'tstamp' => BackendUtility::date($row['tstamp']), + 'issent' => ($row['issent'] ? $this->getLanguageService()->getLL('dmail_yes') : $this->getLanguageService()->getLL('dmail_no')), + 'renderedsize' => ($row['renderedsize'] ? GeneralUtility::formatSize($row['renderedsize']) : ''), + 'attachment' => ($row['attachment'] ? $this->iconFactory->getIcon('directmail-attachment', Icon::SIZE_SMALL) : ''), + 'type' => ($row['type'] & 0x1 ? $this->getLanguageService()->getLL('nl_l_tUrl') : $this->getLanguageService()->getLL('nl_l_tPage')) . ($row['type'] & 0x2 ? ' (' . $this->getLanguageService()->getLL('nl_l_tDraft') . ')' : ''), + 'deleteLink' => $this->deleteLink($row['uid']) + ]; + } + + return $data; + } + + /** + * Creates a directmail entry in th DB. + * used only for quickmail. + * + * @param array $indata Quickmail data (quickmail content, etc.) + * + * @return array error or warning message produced during the process + */ + protected function createDMailQuick(array $indata) + { + $theOutput = []; + // Set default values: + $dmail = []; + $dmail['sys_dmail']['NEW'] = [ + 'from_email' => $indata['senderEmail'], + 'from_name' => $indata['senderName'], + 'replyto_email' => $this->params['replyto_email'] ?? '', + 'replyto_name' => $this->params['replyto_name'] ?? '', + 'return_path' => $this->params['return_path'] ?? '', + 'priority' => (int) $this->params['priority'], + 'use_rdct' => (int) $this->params['use_rdct'], + 'long_link_mode' => (int) $this->params['long_link_mode'], + 'organisation' => $this->params['organisation'] ?? '', + 'authcode_fieldList'=> $this->params['authcode_fieldList'] ?? '', + 'plainParams' => '' + ]; + + // always plaintext + $dmail['sys_dmail']['NEW']['sendOptions'] = 1; + $dmail['sys_dmail']['NEW']['long_link_rdct_url'] = $this->getUrlBase((int)$this->params['pid']); + $dmail['sys_dmail']['NEW']['subject'] = $indata['subject']; + $dmail['sys_dmail']['NEW']['type'] = 1; + $dmail['sys_dmail']['NEW']['pid'] = $this->pageinfo['uid']; + $dmail['sys_dmail']['NEW']['charset'] = isset($this->params['quick_mail_charset']) ? $this->params['quick_mail_charset'] : 'utf-8'; + + // If params set, set default values: + if (isset($this->params['includeMedia'])) { + $dmail['sys_dmail']['NEW']['includeMedia'] = $this->params['includeMedia']; + } + if (isset($this->params['flowedFormat'])) { + $dmail['sys_dmail']['NEW']['flowedFormat'] = $this->params['flowedFormat']; + } + if (isset($this->params['direct_mail_encoding'])) { + $dmail['sys_dmail']['NEW']['encoding'] = $this->params['direct_mail_encoding']; + } + + if ($dmail['sys_dmail']['NEW']['pid'] && $dmail['sys_dmail']['NEW']['sendOptions']) { + /* @var $dataHandler \TYPO3\CMS\Core\DataHandling\DataHandler */ + $dataHandler = $this->getDataHandler(); + $dataHandler->stripslashes_values = 0; + $dataHandler->start($dmail, []); + $dataHandler->process_datamap(); + $this->sys_dmail_uid = $dataHandler->substNEWwithIDs['NEW']; + + $row = BackendUtility::getRecord('sys_dmail', intval($this->sys_dmail_uid)); + // link in the mail + $message = '' . $indata['message'] . ''; + if (trim($this->params['use_rdct'])) { + $message = DirectMailUtility::substUrlsInPlainText( + $message, + $this->params['long_link_mode'] ? 'all' : '76', + $this->getUrlBase((int)$this->params['pid']) + ); + } + if ($indata['breakLines'] ?? false) { + $message = wordwrap($message, 76, "\n"); + } + // fetch functions + $theOutput = $this->compileQuickMail($row, $message); + // end fetch function + } + else { + if (!$dmail['sys_dmail']['NEW']['sendOptions']) { + $this->error = 'no_valid_url'; + } + } + + return $theOutput; + } + + /** + * Wrap a string as a link + * + * @param int $uid UID of the directmail record + * + * @return string the link + * @throws RouteNotFoundException If the named route doesn't exist + */ + protected function linkDMailRecord($uid) + { + return $this->buildUriFromRoute( + $this->moduleName, + [ + 'id' => $this->id, + 'sys_dmail_uid' => $uid, + 'fetchAtOnce' => 1, + 'cmd' => 'info' + ] + ); + } + + /** + * Create delete link with trash icon + * + * @param int $uid Uid of the record + * + * @return string link with the trash icon + * @throws RouteNotFoundException If the named route doesn't exist + */ + protected function deleteLink($uid) + { + $dmail = BackendUtility::getRecord('sys_dmail', $uid); + + if (!$dmail['scheduled_begin']) { + return $this->buildUriFromRoute( + $this->moduleName, + [ + 'id' => $this->id, + 'uid' => $uid, + 'cmd' => 'delete' + ] + ); + } + + return ''; + } + + /** + * Delete existing dmail record + * + * @param int $uid record uid to be deleted + * + * @return void + */ + protected function deleteDMail($uid) + { + $table = 'sys_dmail'; + if ($GLOBALS['TCA'][$table]['ctrl']['delete']) { + + $connection = $this->getConnection($table); + $connection->update( + $table, // table + [ $GLOBALS['TCA'][$table]['ctrl']['delete'] => 1 ], + [ 'uid' => $uid ] // where + ); + } + + return; + } + + /** + * Compiling the quickmail content and save to DB + * + * @param array $row The sys_dmail record + * @param string $message Body of the mail + * + * @return string + * @TODO: remove htmlmail, compiling mail + */ + protected function compileQuickMail(array $row, $message) + { + $erg = ['errorTitle' => '', 'errorText' => '', 'warningTitle' => '', 'warningText' => '']; + + // Compile the mail + /* @var $htmlmail Dmailer */ + $htmlmail = GeneralUtility::makeInstance(Dmailer::class); + $htmlmail->nonCron = 1; + $htmlmail->start(); + $htmlmail->charset = $row['charset']; + $htmlmail->addPlain($message); + + if (!$message || !$htmlmail->theParts['plain']['content']) { + $erg['errorTitle'] = $this->getLanguageService()->getLL('dmail_error'); + $erg['errorText'] = $this->getLanguageService()->getLL('dmail_no_plain_content'); + } + elseif (!strstr(base64_decode($htmlmail->theParts['plain']['content']), ' + +
+ +
+
+ +
+
+
+
+ + +  + + + + + + + + + + + +

+ +
+ + +

+ +
+ + +

+ +
+ + +

+ +
+ + +

+ +
+ + +

+ +
+ + +

+ + + + + +
+ + + + + + + + + +

+ + + + + +
+ + +
+
+ +
+ + +
+
+ +
+ +
+ + + + + + +

+ +
+ + +

+ +
+ +
+ + + + + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+ + + + + + + +

+
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + +
+ +
+ +
+ + + + + +

+ +
+ + +
+ +
+ + +

+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+ +
+ +
diff --git a/Resources/Private/Templates/Dmail.html b/Resources/Private/Templates/Dmail.html new file mode 100644 index 000000000..9fd2e4f8e --- /dev/null +++ b/Resources/Private/Templates/Dmail.html @@ -0,0 +1,408 @@ + + + + + +
+
+
+ + {flashmessages} + +

+ + + + + + + + + + + + + + + + + + + +
+

{data.info.table.icon} {data.info.table.title}

+ + + + + + + + + + + + + +
{data.info.table.theadTitle1} {data.info.table.theadTitle2}{data.info.table.out}
{tr.title}{tr.value}
+
+
+ + + + + +
+ +

+
+

{data.cats.output.title}

+

{data.cats.output.subtitle}

+ + + + + + + + + + + + + + + + + {data.cats.catsForm} +
{row.title}: {row.value} + {row.icon}{row.header} + [{row.CType}; {row.list_type}] +
{row.bodytext}
+
+ {row.labelOnlyAll}
+ + + + + {checkbox.pVal}
+
+
+
+
+ +
+ +
+
+ + + + +
+ +

+
+ +

+ +

+ {data.test.testFormData.test_tt_address} +
+
+ +

+ +

+ + {table.iconFactory} {table.title} +

+ + + + +
{table.tds}
+
+
+
+

+ +

+

+ + + + +
+ + + + +
+ +

+
+

+ + + + +
+ {data.final.finalForm.groupInput} +

+ {data.final.finalForm.hookContents} + +
+
+
+ + + + + +
+
+
+
+ +
+ +

+ +
+
+ + + + +
+ +

-

+ + + + + + + + + + + + + +
+ +
+
+
+ + + +
+ +  {step}  + +
+ +   + + + + +
+
+
+ + + + + + + + + + + + + +
+ +
+
+ +
+
+
+
+ + + +

+ {data.cshItem} +

+ +

+ +
+ + + + + + + + + + + + + +
+ {row.pageIcon} {row.title} + + {row.createLink} + + + {row.iconActionsOpen} + + {row.previewLink}
+
+
+
+ + + +

+ {data.cshItem} +

+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +

+
+ + +
+ + + + + +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ + +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
  
{row.icon}{row.linkText}{row.tstamp}{row.issent}{row.renderedsize}{row.attachment}{row.type}
+
diff --git a/Resources/Private/Templates/MailerEngine.html b/Resources/Private/Templates/MailerEngine.html new file mode 100644 index 000000000..354ba0f57 --- /dev/null +++ b/Resources/Private/Templates/MailerEngine.html @@ -0,0 +1,50 @@ + + + + + + +

+ {cronMonitor} +

+ + +

+

+

+ +

+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
             
{row.icon}{row.subject}{row.scheduled}{row.scheduled_begin}{row.scheduled_end}{row.sent} + + + + + +
+
+
diff --git a/Resources/Private/Templates/NavFrame.html b/Resources/Private/Templates/NavFrame.html index 83f9d69d9..188d27a16 100644 --- a/Resources/Private/Templates/NavFrame.html +++ b/Resources/Private/Templates/NavFrame.html @@ -1,33 +1,23 @@ - -
- -
-
-
###HEADLINE###
-
-
-
###BUTTONLIST_LEFT###
-
###BUTTONLIST_RIGHT###
-
+ -
- -
- ###CONTENT### -
+ + - - - - - - - - - - - - - -###REFRESH######CSH### - \ No newline at end of file + diff --git a/Resources/Private/Templates/NoAccess.html b/Resources/Private/Templates/NoAccess.html new file mode 100644 index 000000000..69d4cdf6d --- /dev/null +++ b/Resources/Private/Templates/NoAccess.html @@ -0,0 +1,5 @@ + + + + + diff --git a/Resources/Private/Templates/RecipientList.html b/Resources/Private/Templates/RecipientList.html new file mode 100644 index 000000000..5ca97a027 --- /dev/null +++ b/Resources/Private/Templates/RecipientList.html @@ -0,0 +1,471 @@ + + + + + + + + +

+ +

+ {data.icon} {data.name} <{data.email}> +    + + {data.iconActionsOpen} + + +
+

+ +

+ + + {cat.pVal} +
+
+

+ +
+ + + +
+ +
+
+ +

{data.group_icon} {data.group_title}

+ {data.group_totalRecipients} + +

+
+
+ + + +

{table.table_custom}

+
+
+ + {table.recip_counter} +
+ +
+ +
+
+ +
+

+ +

+ + + + {data.special.selected} +
+
+ {data.special.selectTables} + + + +
+
+
+ +

+ + + + + + + + + + + + + + + + + + +
 
{row.icon}{row.editLink}{row.reciplink}{row.type}{row.description}{row.count}
+
+

+ + {data.sysDmailGroupIcon} + +
+

+ +
+ +
+

{formcontent.output.title}

+
+

{formcontent.output.subtitle}

+ + + +
+ +

+
+ + + + {formcontent.output.upload.fileInfo.name} ({formcontent.output.upload.fileInfo.extension}; {formcontent.output.upload.fileInfo.size}) + +
+
+
+


+
+
+ {formcontent.output.upload.csv}

+
+
+ + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + {st.text} + + + +
+ + + +
+ + + +
+ + + + + + {del.text} + + + +
+ + + + + + {en.text} + + + +
+ + + +
+ + + +
+ + + +
+ + + + + + {ru.text} + + + +
+
+
+ + + + + + + + +
+ +
+ + + + + + + +
+ + + + + + {cs.text} + + + +
+

+
+ +

+
+
    + +
  • +
    +
+
+

+
+ + + + + + + + + + + + + + + + + + + + + +
{iterator.cycle}{row.mapping_description} + + + + {field.1} + + + + + + + + + + + +
+ {mv} +
+
+
+
+
+

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + +
+ + + +
 {mapping_cat.cat} + +
+
+
+ + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + + + + + + + + + + + + +
{table.header}
{iterator.cycle}{row.val}{row.email}
+
+
+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + {formcontent.theOutput} + +
+
+
+
+
+ + + + {recipListConfig.title} {recipListConfig.counter}
+ + + + + + + + + +
{row.icon}{recipListConfig.actionsOpen}{row.email}{row.name}
+
+
\ No newline at end of file diff --git a/Resources/Private/Templates/Statistics.html b/Resources/Private/Templates/Statistics.html new file mode 100644 index 000000000..4b9174b49 --- /dev/null +++ b/Resources/Private/Templates/Statistics.html @@ -0,0 +1,510 @@ + + + + + + +

+ + + + + + + + + + + + {data.dataHook} + + +
+
+ + + +

+ + + + + + + + + + + + + + + + + + + + + +
 
{row.icon}{row.subject}{row.scheduled}{row.scheduled_begin}{row.scheduled_end}{row.sent}{row.status}
+
+
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + {cell} + +
+
+ + + + + + + + + + + + + + + + + + + + +
+ +
{tr.counter} + +
+
+ + + + +
+ + +

+ +
+ + +
+

+ +
+ + +
+

+ +
+ +
+

+ + + + + + + + + + + + + + + + + +
+ +
+ {cell} +
+
+ + + + + + + + + returnList + + +

{stats_emails}

+ +
+ +

{stats_website_users}

+ +
+ +

{stats_plainlist}

+
  • {dataStats.tables.6.returnList.PLAINLIST.PLAINLIST}
+
+ + returnDisable + + +
+ {dataStats.tables.6.returnDisable.tt_address.counter} {stats_emails_disabled} +
+ +
+ {dataStats.tables.6.returnDisable.fe_users.counter} {stats_website_users_disabled} +
+ + returnCSV + + +
+ +
+ +
+ + unknownList + + +
+ {stats_emails} +
+ +
+ +
+ {stats_website_users} +
+ +
+ +

{stats_plainlist}

+
  • {dataStats.tables.6.unknownList.PLAINLIST.PLAINLIST}
+
+ + unknownDisable + + +
+ {dataStats.tables.6.unknownDisable.tt_address.counter} {stats_emails_disabled} +
+ +
+ {dataStats.tables.6.unknownDisable.fe_users.counter} {stats_website_users_disabled} +
+ + unknownCSV + + +
+ +
+ +
+ + fullList + + +
+ {stats_emails} +
+ +
+ +
+ {stats_website_users} +
+ +
+ +
+ {stats_plainlist} +
  • {dataStats.tables.6.fullList.PLAINLIST.PLAINLIST}
+
+ + fullDisable + + +
+ {dataStats.tables.6.fullDisable.tt_address.counter} {stats_emails_disabled} +
+ +
+ {dataStats.tables.6.fullDisable.fe_users.counter} {stats_website_users_disabled} +
+ + fullCSV + + +
+ +
+ +
+ + badHostList + + +
+ {stats_emails} +
+ +
+ +
+ {stats_website_users} +
+ +
+ +
+ {stats_plainlist} +
  • {dataStats.tables.6.badHostList.PLAINLIST.PLAINLIST}
+
+ + badHostDisable + + +
+ {dataStats.tables.6.badHostDisable.tt_address.counter} {stats_emails_disabled} +
+ +
+ {dataStats.tables.6.badHostDisable.fe_users.counter} {stats_website_users_disabled} +
+ + badHostCSV + + +
+ +
+ +
+ + badHeaderList + + +
+ {stats_emails} +
+ +
+ +
+ {stats_website_users} +
+ +
+ +
+ {stats_plainlist} +
  • {dataStats.tables.6.badHeaderList.PLAINLIST.PLAINLIST}
+
+ + badHeaderDisable + + +
+ {dataStats.tables.6.badHeaderDisable.tt_address.counter} {stats_emails_disabled} +
+ +
+ {dataStats.tables.6.badHeaderDisable.fe_users.counter} {stats_website_users_disabled} +
+ + badHeaderCSV + + +
+ +
+ +
+ + reasonUnknownList + + +
+ {stats_emails} +
+ +
+ +
+ {stats_website_users} +
+ +
+ +
+ {stats_plainlist} +
  • {dataStats.tables.6.reasonUnknownList.PLAINLIST.PLAINLIST}
+
+ + reasonUnknownDisable + + +
+ {dataStats.tables.6.reasonUnknownDisable.tt_address.counter} {stats_emails_disabled} +
+ +
+ {dataStats.tables.6.reasonUnknownDisable.fe_users.counter} {stats_website_users_disabled} +
+ + reasonUnknownCSV + + +
+ +
+ +
+
+ + {dataStats.out} +
+

+

+
+ + + + + + {row.priority}; + {row.encoding}; + {row.charset} + + {row.dmailInfo} {row.includeMedia}; + {row.flowedFormat} + + + {row.replyto_name} <{row.replyto_email}>; + {row.organisation}; + {row.return_path} + + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{row.icon} {row.subject}
{row.from_name} <{row.from_email}>{row.iconInfo}
{row.type} : {row.dmailData}{row.iconInfo}
{row.sendOptions}{row.attachment}{row.iconInfo}
{row.delBegin} / {row.delEnd} 
{row.totalRecip} / {row.sentRecip} 
+
+
+ + + + +

+ {dataUserInfo.icon} {dataUserInfo.name} <{dataUserInfo.email}> + + + {dataUserInfo.iconActionsOpen} + + + +
+

+ +

+ + + {cat.pVal} +
+
+

+ +
+ + + +
+ +
+
+ + + + {returnConfig.title} {returnConfig.counter}
+ + + + + + + + + +
{row.icon}{returnConfig.actionsOpen}{row.email}{row.name}
+
+
\ No newline at end of file diff --git a/Resources/Public/StyleSheets/modules.css b/Resources/Public/StyleSheets/modules.css index f195da554..38c6ff73c 100644 --- a/Resources/Public/StyleSheets/modules.css +++ b/Resources/Public/StyleSheets/modules.css @@ -30,7 +30,6 @@ div.toggleTitle a img { background: #ffffff; border: 1px solid #aaaaaa; padding: 1em; - width: 70%; } @@ -55,7 +54,13 @@ div.toggleTitle a img { vertical-align: bottom; } - .t3-wizard-steps span.t3-wizard-item-active { color: #000000; +} + +#typo3-docheader-row2 { + line-height: 14px !important; +} +#typo3-docheader-row2 span { + font-weight: bold; margin-top: -3px; color: #000; margin-top: 0; padding-left: 20px; } \ No newline at end of file diff --git a/Tests/Unit/Dmailer/DirectMailEngineTest.php b/Tests/Unit/Dmailer/DirectMailEngineTest.php index 49d2e23b6..b7869bbe5 100644 --- a/Tests/Unit/Dmailer/DirectMailEngineTest.php +++ b/Tests/Unit/Dmailer/DirectMailEngineTest.php @@ -39,11 +39,11 @@ public function test_extractHyperLinks($content, $path, $expected) // also get added to the extracted hyperlinks // Create an instance of "dmailer" with only the "extractMediaLinks" being mocked. - $dmailer = $this->getMock('dmailer', array('extractMediaLinks')); + $dmailer = $this->getMock('dmailer', ['extractMediaLinks']); $dmailer->expects($this->once())->method('extractMediaLinks'); $dmailer->theParts['html']['content'] = $content; $dmailer->theParts['html']['path'] = $path; - $dmailer->theParts['html']['media'] = array(); + $dmailer->theParts['html']['media'] = []; $dmailer->extractHyperLinks(); $this->assertEquals($expected, $dmailer->theParts['html']['hrefs']); @@ -56,136 +56,136 @@ public function test_extractHyperLinks($content, $path, $expected) */ public function extractHyperLinksDataProvider() { - return array( - 'no hyperlinks found' => array('This is a simple test', '', null), - 'no hyperlinks in anchor' => array('This is a simple test', '', null), - 'absolute url' => array(' + return [ + 'no hyperlinks found' => ['This is a simple test', '', null], + 'no hyperlinks in anchor' => ['This is a simple test', '', null], + 'absolute url' => [' This is a simple test', 'http://www.server.com/', - array( - array( + [ + [ 'ref' => 'http://google.com', 'quotes' => '"', 'subst_str' => '"http://google.com"', 'absRef' => 'http://google.com', 'tag' => 'a', 'no_jumpurl' => 0, - ), - ) - ), - 'absolute url (fails currently, #54459)' => array(' + ], + ] + ], + 'absolute url (fails currently, #54459)' => [' This is a simple test', 'http://www.server.com/', - array( - array( + [ + [ 'ref' => 'http://google.com', 'quotes' => '"', 'subst_str' => '"http://google.com"', 'absRef' => 'http://google.com', 'tag' => 'a', 'no_jumpurl' => 0, - ), - ) - ), - 'relative link #1' => array(' + ], + ] + ], + 'relative link #1' => [' This is a simple test', 'http://www.server.com/', - array( - array( + [ + [ 'ref' => 'fileadmin/simple.pdf', 'quotes' => '"', 'subst_str' => '"fileadmin/simple.pdf"', 'absRef' => 'http://www.server.com/fileadmin/simple.pdf', 'tag' => 'a', 'no_jumpurl' => 0, - ), - ) - ), - 'relative link #2' => array(' + ], + ] + ], + 'relative link #2' => [' This is a simple test', 'http://www.server.com', - array( - array( + [ + [ 'ref' => 'fileadmin/simple.pdf', 'quotes' => '"', 'subst_str' => '"fileadmin/simple.pdf"', 'absRef' => 'http://www.server.com/fileadmin/simple.pdf', 'tag' => 'a', 'no_jumpurl' => 0, - ), - ) - ), - 'relative link #3' => array(' + ], + ] + ], + 'relative link #3' => [' This is a simple test', 'http://www.server.com/subdirectory/', - array( - array( + [ + [ 'ref' => 'fileadmin/simple.pdf', 'quotes' => '"', 'subst_str' => '"fileadmin/simple.pdf"', 'absRef' => 'http://www.server.com/subdirectory/fileadmin/simple.pdf', 'tag' => 'a', 'no_jumpurl' => 0, - ), - ) - ), - 'relative link #4' => array(' + ], + ] + ], + 'relative link #4' => [' This is a simple test', 'http://www.server.com/subdirectory', - array( - array( + [ + [ 'ref' => 'fileadmin/simple.pdf', 'quotes' => '"', 'subst_str' => '"fileadmin/simple.pdf"', 'absRef' => 'http://www.server.com/fileadmin/simple.pdf', 'tag' => 'a', 'no_jumpurl' => 0, - ), - ) - ), - 'absolute link #1' => array(' + ], + ] + ], + 'absolute link #1' => [' This is a simple test', 'http://www.server.com/subdirectory', - array( - array( + [ + [ 'ref' => '/fileadmin/simple.pdf', 'quotes' => '"', 'subst_str' => '"/fileadmin/simple.pdf"', 'absRef' => 'http://www.server.com/fileadmin/simple.pdf', 'tag' => 'a', 'no_jumpurl' => 0, - ), - ) - ), - 'absolute link #2' => array(' + ], + ] + ], + 'absolute link #2' => [' This is a simple test', 'http://www.server.com/subdirectory/', - array( - array( + [ + [ 'ref' => '/fileadmin/simple.pdf', 'quotes' => '"', 'subst_str' => '"/fileadmin/simple.pdf"', 'absRef' => 'http://www.server.com/fileadmin/simple.pdf', 'tag' => 'a', 'no_jumpurl' => 0, - ), - ) - ), - 'absolute link #3 (no_jumpurl)' => array(' + ], + ] + ], + 'absolute link #3 (no_jumpurl)' => [' This is a simple test', 'http://www.server.com/subdirectory', - array( - array( + [ + [ 'ref' => 'image.png', 'quotes' => '"', 'subst_str' => '"image.png"', 'absRef' => 'http://www.server.com/image.png', 'tag' => 'a', 'no_jumpurl' => 1, - ), - ) - ), - 'form action #1' => array(' + ], + ] + ], + 'form action #1' => [' Hello.
Here you can send us your comment
@@ -193,17 +193,17 @@ public function extractHyperLinksDataProvider()
Thanks!', 'http://www.server.com/subdirectory/', - array( - array( + [ + [ 'ref' => 'index.php?id=123', 'quotes' => '"', 'subst_str' => '"index.php?id=123"', 'absRef' => 'http://www.server.com/subdirectory/index.php?id=123', 'tag' => 'form', 'no_jumpurl' => 1, - ), - ) - ), - ); + ], + ] + ], + ]; } } diff --git a/composer.json b/composer.json index d4565fb37..d9740bbf5 100644 --- a/composer.json +++ b/composer.json @@ -22,10 +22,9 @@ "issues": "https://github.com/kartolo/direct_mail/issues" }, "require": { - "typo3/cms-core": "^10.4", - "friendsoftypo3/jumpurl": "^8.0", - "friendsoftypo3/tt-address": "^4.3 || ^5.0", - "friendsoftypo3/rdct": "^2.0" + "typo3/cms-core": "^11.5", + "friendsoftypo3/tt-address": "^5.3 || ^6.0", + "tedivm/fetch": "0.7.*" }, "require-dev": { "roave/security-advisories": "dev-master" @@ -33,8 +32,7 @@ "minimum-stability": "dev", "autoload": { "psr-4": { - "DirectMailTeam\\DirectMail\\": "Classes", - "Fetch\\": "Resources/Private/Php/Fetch/src/Fetch" + "DirectMailTeam\\DirectMail\\": "Classes" } }, "replace": { diff --git a/crowdin.yml b/crowdin.yml new file mode 100644 index 000000000..61c310583 --- /dev/null +++ b/crowdin.yml @@ -0,0 +1,3 @@ +files: + - source: /Resources/Private/Language/locallang*.xlf + translation: /Resources/Private/Language/%two_letters_code%.%original_file_name% diff --git a/ext_conf_template.txt b/ext_conf_template.txt index cdb40b83b..c1365dc35 100644 --- a/ext_conf_template.txt +++ b/ext_conf_template.txt @@ -1,23 +1,23 @@ - # cat=basic; type=int+; label=Number of messages per cycle : Number of messages to be sent per cycle of the dmailer cron task. +# cat=basic; type=int+; label=Number of messages per cycle : Number of messages to be sent per cycle of the dmailer cron task. sendPerCycle = 50 - # cat=basic; type=string; label=Language of the cron task : Language used to localize progress messages sent by the dmailer cron task. +# cat=basic; type=string; label=Language of the cron task : Language used to localize progress messages sent by the dmailer cron task. cron_language = en - # cat=basic; type=string; label= Additional DB fields of the recipient : Additional fields that may be substituted in the direct mail messages. +# cat=basic; type=string; label= Additional DB fields of the recipient : Additional fields that may be substituted in the direct mail messages. addRecipFields = - # cat=basic; type=string; label=Administrator Email: Administrator email is used to send email if there's cronjob error. +# cat=basic; type=string; label=Administrator Email: Administrator email is used to send email if there's cronjob error. adminEmail = admin@website.com - # cat=basic; type=int+; label=Interval of the cronjob: Interval of the cronjob (in minute). +# cat=basic; type=int+; label=Interval of the cronjob: Interval of the cronjob (in minute). cronInt = 5 - # cat=basic/enable; type=boolean; label=Enable notification email : Allow direct mail to send notification about start and end of a mailing job. +# cat=basic/enable; type=boolean; label=Enable notification email : Allow direct mail to send notification about start and end of a mailing job. notificationJob = 1 - # cat=basic/enable; type=boolean; label=Use http connection for fetching Newsletter-Content: Even if your TYPO3 Backend is in SSL-Mode, the URL for fetching the newsletter contents will be http +# cat=basic/enable; type=boolean; label=Use http connection for fetching Newsletter-Content: Even if your TYPO3 Backend is in SSL-Mode, the URL for fetching the newsletter contents will be http UseHttpToFetch = 0 - # cat=basic/enable; type=boolean; label=Use implicit port in URL for fetching Newsletter-Content: Even if your TYPO3 Backend is on a non-standard-port, the URL for fetching the newsletter contents from one of your Frontend-Domains will not use the PORT you are using to access your TYPO3 Backend, but use implicit port instead (e.g. no explicit port in URL) +# cat=basic/enable; type=boolean; label=Use implicit port in URL for fetching Newsletter-Content: Even if your TYPO3 Backend is on a non-standard-port, the URL for fetching the newsletter contents from one of your Frontend-Domains will not use the PORT you are using to access your TYPO3 Backend, but use implicit port instead (e.g. no explicit port in URL) UseImplicitPortToFetch = 0 diff --git a/ext_emconf.php b/ext_emconf.php index 39ddf7ae8..d7025ca70 100644 --- a/ext_emconf.php +++ b/ext_emconf.php @@ -1,39 +1,24 @@ 'Direct Mail', 'description' => 'Advanced Direct Mail/Newsletter mailer system with sophisticated options for personalization of emails including response statistics.', 'category' => 'module', - 'version' => '7.1.0-dev', - 'state' => 'stable', - 'clearcacheonload' => 0, - 'lockType' => '', 'author' => 'Ivan Kartolo', 'author_email' => 'ivan.kartolo@dkd.de', 'author_company' => 'd.k.d Internet Service GmbH', + 'state' => 'stable', + 'clearcacheonload' => 0, + 'version' => '8.0.0', 'constraints' => [ 'depends' => [ - 'tt_address' => '4.0.0-', - 'php' => '7.2.0', - 'typo3' => '10.4.0-10.4.99', - 'jumpurl' => '8.0.0-', - 'rdct' => '2.0.0' + 'typo3' => '11.5.0-11.99.99', + 'tt_address' => '5.3.0-6.0.99', + 'php' => '7.4.0-8.0.99', + 'jumpurl' => '8.0.3-', + 'rdct' => '2.1.0' ], 'conflicts' => [ - 'sr_direct_mail_ext' => '', - 'it_dmail_fix' => '', - 'plugin_mgm' => '', - 'direct_mail_123' => '', ], 'suggests' => [ ], @@ -42,8 +27,7 @@ ], 'autoload' => [ 'psr-4' => [ - 'DirectMailTeam\\DirectMail\\' => 'Classes/', - 'Fetch\\' => 'Resources/Private/Php/Fetch/src/Fetch/' + 'DirectMailTeam\\DirectMail\\' => 'Classes/' ] ], ]; diff --git a/ext_localconf.php b/ext_localconf.php index 019f0f766..67289b937 100644 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -1,101 +1,107 @@ ['source' => 'EXT:direct_mail/Resources/Public/Icons/attach.gif'], - 'directmail-dmail' => ['source' => 'EXT:direct_mail/Resources/Public/Icons/dmail.gif'], - 'directmail-dmail-list' => ['source' => 'EXT:direct_mail/Resources/Public/Icons/dmail_list.gif'], - 'directmail-folder' => ['source' => 'EXT:direct_mail/Resources/Public/Icons/ext_icon_dmail_folder.gif'], - 'directmail-category' => ['source' => 'EXT:direct_mail/Resources/Public/Icons/icon_tx_directmail_category.gif'], - 'directmail-mail' => ['source' => 'EXT:direct_mail/Resources/Public/Icons/mail.gif'], - 'directmail-mailgroup' => ['source' => 'EXT:direct_mail/Resources/Public/Icons/mailgroup.gif'], - 'directmail-page-modules-dmail' => ['source' => 'EXT:direct_mail/Resources/Public/Icons/modules_dmail.gif'], - 'directmail-page-modules-dmail-inactive' => ['source' => 'EXT:direct_mail/Resources/Public/Icons/modules_dmail__h.gif'], - 'directmail-dmail-new' => ['source' => 'EXT:direct_mail/Resources/Public/Icons/newmail.gif'], - 'directmail-dmail-preview-html' => ['source' => 'EXT:direct_mail/Resources/Public/Icons/preview_html.gif'], - 'directmail-dmail-preview-text' => ['source' => 'EXT:direct_mail/Resources/Public/Icons/preview_txt.gif'], -]; - -foreach ($icons as $identifier => $options) { - $iconRegistry->registerIcon($identifier, $iconProviderClassName, $options); -} - -// Register hook for simulating a user group -$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['determineId-PreProcessing']['direct_mail'] = 'DirectMailTeam\\DirectMail\\Hooks\TypoScriptFrontendController->simulateUsergroup'; - -// Get extension configuration so we can use it here: -$extConf = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Configuration\ExtensionConfiguration::class)->get('direct_mail'); - -/** - * Language of the cron task: - */ -$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['direct_mail']['cron_language'] = $extConf['cron_language'] ? $extConf['cron_language'] : 'en'; - -/** - * Number of messages sent per cycle of the cron task: - */ -$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['direct_mail']['sendPerCycle'] = $extConf['sendPerCycle'] ? $extConf['sendPerCycle'] : 50; - -/** - * Default recipient field list: - */ -$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['direct_mail']['defaultRecipFields'] = 'uid,name,title,email,phone,www,address,company,city,zip,country,fax,firstname,first_name,last_name'; - -/** - * Additional DB fields of the recipient: - */ -$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['direct_mail']['addRecipFields'] = $extConf['addRecipFields']; - -/** - * Admin email for sending the cronjob error message - */ -$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['direct_mail']['adminEmail'] = $extConf['adminEmail']; - -/** - * Direct Mail send a notification every time a job starts or ends - */ -$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['direct_mail']['notificationJob'] = $extConf['notificationJob']; - -/** - * Interval of the cronjob - */ -$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['direct_mail']['cronInt'] = $extConf['cronInt']; - -/** - * Use HTTP to fetch contents - */ -$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['direct_mail']['UseHttpToFetch'] = $extConf['UseHttpToFetch']; - -/** - * Use implicit port in URL for fetching Newsletter-Content: Even if your TYPO3 Backend is on a non-standard-port, the URL for fetching the newsletter contents from one of your Frontend-Domains will not use the PORT you are using to access your TYPO3 Backend, but use implicit port instead (e.g. no explicit port in URL) - */ -$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['UseImplicitPortToFetch'] = $extConf['UseImplicitPortToFetch']; - -/** - * Registering class to scheduler - */ -$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks']['DirectMailTeam\\DirectMail\\Scheduler\\DirectmailScheduler'] = [ - 'extension' => 'direct_mail', - 'title' => 'Direct Mail: Mailing Queue', - 'description' => 'This task invokes dmailer in order to process queued messages.', -]; - -$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks']['DirectMailTeam\\DirectMail\\Scheduler\\MailFromDraft'] = [ - 'extension' => 'direct_mail', - 'title' => 'Direct Mail: Create Mail from Draft', - 'description' => 'This task allows you to select a DirectMail draft that gets copied and then sent to the. This allows automatic (periodic) sending of the same TYPO3 page.', - 'additionalFields' => 'DirectMailTeam\\DirectMail\\Scheduler\\MailFromDraftAdditionalFields' -]; - -// bounce mail per scheduler -$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks']['DirectMailTeam\\DirectMail\\Scheduler\\AnalyzeBounceMail'] = [ - 'extension' => 'direct_mail', - 'title' => 'Direct Mail: Analyze bounce mail', - 'description' => 'This task will get bounce mail from the configured mailbox', - 'additionalFields' => 'DirectMailTeam\\DirectMail\\Scheduler\\AnalyzeBounceMailAdditionalFields' -]; +declare(strict_types=1); + +defined('TYPO3') || die(); + +// https://docs.typo3.org/m/typo3/reference-coreapi/11.5/en-us/ExtensionArchitecture/BestPractises/ConfigurationFiles.html +(function () { + // registering icons + $iconProviderClassName = \TYPO3\CMS\Core\Imaging\IconProvider\BitmapIconProvider::class; + + $iconRegistry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Imaging\IconRegistry::class); + $icons = [ + 'directmail-attachment' => ['source' => 'EXT:direct_mail/Resources/Public/Icons/attach.gif'], + 'directmail-dmail' => ['source' => 'EXT:direct_mail/Resources/Public/Icons/dmail.gif'], + 'directmail-dmail-list' => ['source' => 'EXT:direct_mail/Resources/Public/Icons/dmail_list.gif'], + 'directmail-folder' => ['source' => 'EXT:direct_mail/Resources/Public/Icons/ext_icon_dmail_folder.gif'], + 'directmail-category' => ['source' => 'EXT:direct_mail/Resources/Public/Icons/icon_tx_directmail_category.gif'], + 'directmail-mail' => ['source' => 'EXT:direct_mail/Resources/Public/Icons/mail.gif'], + 'directmail-mailgroup' => ['source' => 'EXT:direct_mail/Resources/Public/Icons/mailgroup.gif'], + 'directmail-page-modules-dmail' => ['source' => 'EXT:direct_mail/Resources/Public/Icons/modules_dmail.gif'], + 'directmail-page-modules-dmail-inactive' => ['source' => 'EXT:direct_mail/Resources/Public/Icons/modules_dmail__h.gif'], + 'directmail-dmail-new' => ['source' => 'EXT:direct_mail/Resources/Public/Icons/newmail.gif'], + 'directmail-dmail-preview-html' => ['source' => 'EXT:direct_mail/Resources/Public/Icons/preview_html.gif'], + 'directmail-dmail-preview-text' => ['source' => 'EXT:direct_mail/Resources/Public/Icons/preview_txt.gif'], + ]; + + foreach ($icons as $identifier => $options) { + $iconRegistry->registerIcon($identifier, $iconProviderClassName, $options); + } + + // Register hook for simulating a user group + $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['determineId-PreProcessing']['direct_mail'] = 'DirectMailTeam\\DirectMail\\Hooks\TypoScriptFrontendController->simulateUsergroup'; + + // Get extension configuration so we can use it here: + $extConf = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Configuration\ExtensionConfiguration::class)->get('direct_mail'); + + /** + * Language of the cron task: + */ + $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['direct_mail']['cron_language'] = $extConf['cron_language'] ? $extConf['cron_language'] : 'en'; + + /** + * Number of messages sent per cycle of the cron task: + */ + $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['direct_mail']['sendPerCycle'] = $extConf['sendPerCycle'] ? $extConf['sendPerCycle'] : 50; + + /** + * Default recipient field list: + */ + $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['direct_mail']['defaultRecipFields'] = 'uid,name,title,email,phone,www,address,company,city,zip,country,fax,firstname,first_name,last_name'; + + /** + * Additional DB fields of the recipient: + */ + $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['direct_mail']['addRecipFields'] = $extConf['addRecipFields']; + + /** + * Admin email for sending the cronjob error message + */ + $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['direct_mail']['adminEmail'] = $extConf['adminEmail']; + + /** + * Direct Mail send a notification every time a job starts or ends + */ + $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['direct_mail']['notificationJob'] = $extConf['notificationJob']; + + /** + * Interval of the cronjob + */ + $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['direct_mail']['cronInt'] = $extConf['cronInt']; + + /** + * Use HTTP to fetch contents + */ + $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['direct_mail']['UseHttpToFetch'] = $extConf['UseHttpToFetch']; + + /** + * Use implicit port in URL for fetching Newsletter-Content: Even if your TYPO3 Backend is on a non-standard-port, + * the URL for fetching the newsletter contents from one of your Frontend-Domains will not use the PORT you are using to access your TYPO3 Backend, + * but use implicit port instead (e.g. no explicit port in URL) + */ + $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['direct_mail']['UseImplicitPortToFetch'] = $extConf['UseImplicitPortToFetch']; + + /** + * Registering class to scheduler + */ + $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks']['DirectMailTeam\\DirectMail\\Scheduler\\DirectmailScheduler'] = [ + 'extension' => 'direct_mail', + 'title' => 'Direct Mail: Mailing Queue', + 'description' => 'This task invokes dmailer in order to process queued messages.', + ]; + + $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks']['DirectMailTeam\\DirectMail\\Scheduler\\MailFromDraft'] = [ + 'extension' => 'direct_mail', + 'title' => 'Direct Mail: Create Mail from Draft', + 'description' => 'This task allows you to select a DirectMail draft that gets copied and then sent to the. This allows automatic (periodic) sending of the same TYPO3 page.', + 'additionalFields' => 'DirectMailTeam\\DirectMail\\Scheduler\\MailFromDraftAdditionalFields' + ]; + + // bounce mail per scheduler + $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks']['DirectMailTeam\\DirectMail\\Scheduler\\AnalyzeBounceMail'] = [ + 'extension' => 'direct_mail', + 'title' => 'Direct Mail: Analyze bounce mail', + 'description' => 'This task will get bounce mail from the configured mailbox', + 'additionalFields' => 'DirectMailTeam\\DirectMail\\Scheduler\\AnalyzeBounceMailAdditionalFields' + ]; + })(); diff --git a/ext_tables.php b/ext_tables.php index 3bfd1cb3b..15fdf2b5e 100755 --- a/ext_tables.php +++ b/ext_tables.php @@ -1,31 +1,31 @@ DirectMailTeam\DirectMail\Module\NavFrame::class . '::mainAction', + 'routeTarget' => DirectMailTeam\DirectMail\Module\NavFrameController::class . '::indexAction', 'access' => 'group,user', 'name' => 'DirectMailNavFrame', 'icon' => 'EXT:direct_mail/Resources/Public/Images/module-directmail.svg', @@ -43,13 +43,17 @@ ] ); + // https://docs.typo3.org/m/typo3/reference-coreapi/11.5/en-us/ApiOverview/BackendModules/BackendModuleApi/Index.html#without-extbase + // https://docs.typo3.org/c/typo3/cms-core/main/en-us/Changelog/11.5/Deprecation-94094-NavigationFrameModuleInModuleRegistration.html + TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addModule( 'DirectMailNavFrame', 'DirectMail', 'bottom', '', [ - 'routeTarget' => DirectMailTeam\DirectMail\Module\Dmail::class . '::mainAction', + 'navigationComponentId' => 'TYPO3/CMS/Backend/PageTree/PageTreeElement', + 'routeTarget' => DirectMailTeam\DirectMail\Module\DmailController::class . '::indexAction', 'access' => 'group,user', 'name' => 'DirectMailNavFrame_DirectMail', 'workspaces' => 'online', @@ -57,8 +61,6 @@ 'labels' => [ 'll_ref' => 'LLL:EXT:direct_mail/Resources/Private/Language/locallangDirectMail.xlf', ], - 'navigationFrameModule' => 'DirectMailNavFrame', - 'navigationFrameModuleParameters' => ['currentModule' => 'DirectMailNavFrame_DirectMail'], ] ); @@ -68,7 +70,8 @@ 'bottom', '', [ - 'routeTarget' => DirectMailTeam\DirectMail\Module\RecipientList::class . '::mainAction', + 'navigationComponentId' => 'TYPO3/CMS/Backend/PageTree/PageTreeElement', + 'routeTarget' => DirectMailTeam\DirectMail\Module\RecipientListController::class . '::indexAction', 'access' => 'group,user', 'name' => 'DirectMailNavFrame_RecipientList', 'workspaces' => 'online', @@ -76,8 +79,6 @@ 'labels' => [ 'll_ref' => 'LLL:EXT:direct_mail/Resources/Private/Language/locallangRecipientList.xlf', ], - 'navigationFrameModule' => 'DirectMailNavFrame', - 'navigationFrameModuleParameters' => ['currentModule' => 'DirectMailNavFrame_RecipientList'], ] ); @@ -87,7 +88,8 @@ 'bottom', '', [ - 'routeTarget' => DirectMailTeam\DirectMail\Module\Statistics::class . '::mainAction', + 'navigationComponentId' => 'TYPO3/CMS/Backend/PageTree/PageTreeElement', + 'routeTarget' => DirectMailTeam\DirectMail\Module\StatisticsController::class . '::indexAction', 'access' => 'group,user', 'name' => 'DirectMailNavFrame_Statistics', 'workspaces' => 'online', @@ -95,18 +97,17 @@ 'labels' => [ 'll_ref' => 'LLL:EXT:direct_mail/Resources/Private/Language/locallangStatistics.xlf', ], - 'navigationFrameModule' => 'DirectMailNavFrame', - 'navigationFrameModuleParameters' => ['currentModule' => 'DirectMailNavFrame_Statistics'], ] ); - + TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addModule( 'DirectMailNavFrame', 'MailerEngine', 'bottom', '', [ - 'routeTarget' => DirectMailTeam\DirectMail\Module\MailerEngine::class . '::mainAction', + 'navigationComponentId' => 'TYPO3/CMS/Backend/PageTree/PageTreeElement', + 'routeTarget' => DirectMailTeam\DirectMail\Module\MailerEngineController::class . '::indexAction', 'access' => 'group,user', 'name' => 'DirectMailNavFrame_MailerEngine', 'workspaces' => 'online', @@ -114,8 +115,6 @@ 'labels' => [ 'll_ref' => 'LLL:EXT:direct_mail/Resources/Private/Language/locallangMailerEngine.xlf', ], - 'navigationFrameModule' => 'DirectMailNavFrame', - 'navigationFrameModuleParameters' => ['currentModule' => 'DirectMailNavFrame_MailerEngine'], ] ); @@ -125,7 +124,8 @@ 'bottom', '', [ - 'routeTarget' => DirectMailTeam\DirectMail\Module\Configuration::class . '::mainAction', + 'navigationComponentId' => 'TYPO3/CMS/Backend/PageTree/PageTreeElement', + 'routeTarget' => DirectMailTeam\DirectMail\Module\ConfigurationController::class . '::indexAction', 'access' => 'group,user', 'name' => 'DirectMailNavFrame_Configuration', 'workspaces' => 'online', @@ -133,12 +133,12 @@ 'labels' => [ 'll_ref' => 'LLL:EXT:direct_mail/Resources/Private/Language/locallangConfiguration.xlf', ], - 'navigationFrameModule' => 'DirectMailNavFrame', - 'navigationFrameModuleParameters' => ['currentModule' => 'DirectMailNavFrame_Configuration'], ] ); -} -if (TYPO3\CMS\Core\Utility\VersionNumberUtility::convertVersionNumberToInteger(TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getExtensionVersion('tt_address')) <= TYPO3\CMS\Core\Utility\VersionNumberUtility::convertVersionNumberToInteger('2.3.5')) { - include_once(TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('direct_mail').'Configuration/TCA/Overrides/tt_address.php'); -} + if (TYPO3\CMS\Core\Utility\VersionNumberUtility::convertVersionNumberToInteger(TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getExtensionVersion('tt_address')) <= TYPO3\CMS\Core\Utility\VersionNumberUtility::convertVersionNumberToInteger('2.3.5')) { + include_once(TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('direct_mail').'Configuration/TCA/Overrides/tt_address.php'); + } + + $GLOBALS['TBE_STYLES']['skins']['direct_mail']['stylesheetDirectories'][] = 'EXT:direct_mail/Resources/Public/StyleSheets/'; +})(); \ No newline at end of file diff --git a/ext_tables.sql b/ext_tables.sql index 0b40b7bb2..bf9609847 100755 --- a/ext_tables.sql +++ b/ext_tables.sql @@ -1,10 +1,3 @@ -## -## @package TYPO3 -## @subpackage tx_directmail -## @version $Id$ -## - - # # Table structure for table 'cache_sys_dmail_stat' # @@ -240,4 +233,3 @@ CREATE TABLE tt_address ( CREATE TABLE tt_content ( module_sys_dmail_category int(10) unsigned DEFAULT '0' NOT NULL, ); -