mirror of
https://github.com/saccas/mjml-typo3.git
synced 2024-11-22 17:16:10 +01:00
[TASK] Init
This commit is contained in:
parent
91027442a7
commit
a7c019d658
9 changed files with 310 additions and 2 deletions
14
.gitignore
vendored
Normal file
14
.gitignore
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
# ide
|
||||||
|
/.project
|
||||||
|
/.buildpath
|
||||||
|
/.settings
|
||||||
|
/.nbproject
|
||||||
|
/.idea
|
||||||
|
|
||||||
|
# git
|
||||||
|
/.auth.json
|
||||||
|
|
||||||
|
# node / grunt / sass / bower
|
||||||
|
.sass-cache
|
||||||
|
node_modules
|
||||||
|
bower_components
|
130
Classes/Domain/Finishers/MjmlEmailFinisher.php
Normal file
130
Classes/Domain/Finishers/MjmlEmailFinisher.php
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
namespace Saccas\Mjml\Domain\Finishers;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the TYPO3 CMS project.
|
||||||
|
*
|
||||||
|
* It is free software; you can redistribute it and/or modify it under
|
||||||
|
* the terms of the GNU General Public License, either version 2
|
||||||
|
* of the License, or any later version.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the
|
||||||
|
* LICENSE.txt file that was distributed with this source code.
|
||||||
|
*
|
||||||
|
* The TYPO3 project - inspiring people to share!
|
||||||
|
*/
|
||||||
|
|
||||||
|
use TYPO3\CMS\Core\Mail\MailMessage;
|
||||||
|
use TYPO3\CMS\Extbase\Domain\Model\FileReference;
|
||||||
|
use TYPO3\CMS\Fluid\View\StandaloneView;
|
||||||
|
use TYPO3\CMS\Form\Domain\Finishers\Exception\FinisherException;
|
||||||
|
use TYPO3\CMS\Form\Domain\Model\FormElements\FileUpload;
|
||||||
|
use TYPO3\CMS\Form\Domain\Runtime\FormRuntime;
|
||||||
|
use TYPO3\CMS\Form\Service\TranslationService;
|
||||||
|
use TYPO3\CMS\Form\ViewHelpers\RenderRenderableViewHelper;
|
||||||
|
use Saccas\Mjml\View\MjmlBasedView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This finisher sends an email to one recipient
|
||||||
|
*
|
||||||
|
* Options:
|
||||||
|
*
|
||||||
|
* - templatePathAndFilename (mandatory): Template path and filename for the mail body
|
||||||
|
* - layoutRootPath: root path for the layouts
|
||||||
|
* - partialRootPath: root path for the partials
|
||||||
|
* - variables: associative array of variables which are available inside the Fluid template
|
||||||
|
*
|
||||||
|
* The following options control the mail sending. In all of them, placeholders in the form
|
||||||
|
* of {...} are replaced with the corresponding form value; i.e. {email} as recipientAddress
|
||||||
|
* makes the recipient address configurable.
|
||||||
|
*
|
||||||
|
* - subject (mandatory): Subject of the email
|
||||||
|
* - recipientAddress (mandatory): Email address of the recipient
|
||||||
|
* - recipientName: Human-readable name of the recipient
|
||||||
|
* - senderAddress (mandatory): Email address of the sender
|
||||||
|
* - senderName: Human-readable name of the sender
|
||||||
|
* - replyToAddress: Email address of to be used as reply-to email (use multiple addresses with an array)
|
||||||
|
* - carbonCopyAddress: Email address of the copy recipient (use multiple addresses with an array)
|
||||||
|
* - blindCarbonCopyAddress: Email address of the blind copy recipient (use multiple addresses with an array)
|
||||||
|
* - format: format of the email (one of the FORMAT_* constants). By default mails are sent as HTML
|
||||||
|
*
|
||||||
|
* Scope: frontend
|
||||||
|
*/
|
||||||
|
class MjmlEmailFinisher extends \TYPO3\CMS\Form\Domain\Finishers\EmailFinisher
|
||||||
|
{
|
||||||
|
const FORMAT_PLAINTEXT = 'plaintext';
|
||||||
|
const FORMAT_HTML = 'html';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $defaultOptions = [
|
||||||
|
'recipientName' => '',
|
||||||
|
'senderName' => '',
|
||||||
|
'format' => self::FORMAT_HTML,
|
||||||
|
'attachUploads' => true
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes this finisher
|
||||||
|
* @see AbstractFinisher::execute()
|
||||||
|
*
|
||||||
|
* @throws FinisherException
|
||||||
|
*/
|
||||||
|
protected function executeInternal()
|
||||||
|
{
|
||||||
|
parent::executeInternal();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param FormRuntime $formRuntime
|
||||||
|
* @return StandaloneView
|
||||||
|
* @throws FinisherException
|
||||||
|
*/
|
||||||
|
protected function initializeStandaloneView(FormRuntime $formRuntime): StandaloneView
|
||||||
|
{
|
||||||
|
$format = ucfirst($this->parseOption('format'));
|
||||||
|
$standaloneView = $this->objectManager->get(MjmlBasedView::class);
|
||||||
|
|
||||||
|
if (isset($this->options['templatePathAndFilename'])) {
|
||||||
|
$this->options['templatePathAndFilename'] = strtr($this->options['templatePathAndFilename'], [
|
||||||
|
'{@format}' => $format
|
||||||
|
]);
|
||||||
|
$standaloneView->setTemplatePathAndFilename($this->options['templatePathAndFilename']);
|
||||||
|
} else {
|
||||||
|
if (!isset($this->options['templateName'])) {
|
||||||
|
throw new FinisherException('The option "templateName" must be set for the EmailFinisher.', 1327058829);
|
||||||
|
}
|
||||||
|
$this->options['templateName'] = strtr($this->options['templateName'], [
|
||||||
|
'{@format}' => $format
|
||||||
|
]);
|
||||||
|
$standaloneView->setTemplate($this->options['templateName']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$standaloneView->assign('finisherVariableProvider', $this->finisherContext->getFinisherVariableProvider());
|
||||||
|
|
||||||
|
if (isset($this->options['templateRootPaths']) && is_array($this->options['templateRootPaths'])) {
|
||||||
|
$standaloneView->setTemplateRootPaths($this->options['templateRootPaths']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->options['partialRootPaths']) && is_array($this->options['partialRootPaths'])) {
|
||||||
|
$standaloneView->setPartialRootPaths($this->options['partialRootPaths']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->options['layoutRootPaths']) && is_array($this->options['layoutRootPaths'])) {
|
||||||
|
$standaloneView->setLayoutRootPaths($this->options['layoutRootPaths']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->options['variables'])) {
|
||||||
|
$standaloneView->assignMultiple($this->options['variables']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$standaloneView->assign('form', $formRuntime);
|
||||||
|
$standaloneView->getRenderingContext()
|
||||||
|
->getViewHelperVariableContainer()
|
||||||
|
->addOrUpdate(RenderRenderableViewHelper::class, 'formRuntime', $formRuntime);
|
||||||
|
|
||||||
|
return $standaloneView;
|
||||||
|
}
|
||||||
|
}
|
34
Classes/View/MjmlBasedView.php
Normal file
34
Classes/View/MjmlBasedView.php
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Saccas\Mjml\View;
|
||||||
|
|
||||||
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
|
use TYPO3\CMS\Fluid\View\StandaloneView;
|
||||||
|
use TYPO3\CMS\Core\Utility\CommandUtility;
|
||||||
|
|
||||||
|
class MjmlBasedView extends StandaloneView
|
||||||
|
{
|
||||||
|
function render()
|
||||||
|
{
|
||||||
|
return $this->getHtmlFromMjml(parent::render());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getHtmlFromMjml($mjml)
|
||||||
|
{
|
||||||
|
$configuration = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['mjml']);
|
||||||
|
|
||||||
|
$temporaryMjmlFileWithPath = GeneralUtility::tempnam('mjml_', '.mjml');
|
||||||
|
$mjmlFile = fopen($temporaryMjmlFileWithPath, 'w');
|
||||||
|
fwrite($mjmlFile, $mjml);
|
||||||
|
fclose($mjmlFile);
|
||||||
|
|
||||||
|
// see https://mjml.io/download and https://www.npmjs.com/package/mjml-cli
|
||||||
|
$cmd = $configuration['nodeBinaryPath'] . ' ' . $configuration['mjmlBinaryPath'] . $configuration['mjmlBinary'] .' ' . $configuration['mjmlParams'] . ' ' . $temporaryMjmlFileWithPath;
|
||||||
|
|
||||||
|
$result = [];
|
||||||
|
$returnValue = '';
|
||||||
|
CommandUtility::exec($cmd, $result, $returnValue);
|
||||||
|
|
||||||
|
return implode('',$result);
|
||||||
|
}
|
||||||
|
}
|
35
README.md
35
README.md
|
@ -1,2 +1,33 @@
|
||||||
# mjml
|
# MJML
|
||||||
TYPO3 Mjml.io integration for EXT:Form
|
|
||||||
|
https://mjml.io integration for **TYPO3 EXT:Form**
|
||||||
|
|
||||||
|
MJML is a markup language designed to reduce the pain of coding a responsive email. Its semantic syntax makes it easy and straightforward and its rich standard components library speeds up your development time and lightens your email codebase. MJML’s open-source engine generates high quality responsive HTML compliant with best practices. https://mjml.io/getting-started-onboard
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
### Over composer:
|
||||||
|
|
||||||
|
`composer require saccas/mjml`
|
||||||
|
|
||||||
|
### NPM
|
||||||
|
|
||||||
|
Npm is needed for the conversion of the MJML file to HTML
|
||||||
|
|
||||||
|
## Usage in EXT:Form
|
||||||
|
|
||||||
|
You can overwrite the default _finishersEmailMixin_ so that he uses the _MjmlEmailFinisher_
|
||||||
|
or create your own.
|
||||||
|
|
||||||
|
```
|
||||||
|
TYPO3:
|
||||||
|
CMS:
|
||||||
|
Form:
|
||||||
|
mixins:
|
||||||
|
finishersEmailMixin:
|
||||||
|
implementationClassName: 'Saccas\Mjml\Domain\Finishers\MjmlEmailFinisher'
|
||||||
|
```
|
||||||
|
|
||||||
|
## MJML Documentation
|
||||||
|
|
||||||
|
https://mjml.io/documentation/
|
||||||
|
|
22
composer.json
Normal file
22
composer.json
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"name": "saccas/mjml",
|
||||||
|
"description": "Mjml view using mjml over npm",
|
||||||
|
"type": "typo3-cms-extension",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"homepage": "https://mjml.io",
|
||||||
|
"license": ["GPL-2.0+"],
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Saccas\\Mjml\\": "Classes/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.0.0 <=7.2.99",
|
||||||
|
"typo3/cms-core": ">=8.7.0,<8.9.99"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"post-install-cmd": [
|
||||||
|
"npm install"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
11
ext_conf_template.txt
Normal file
11
ext_conf_template.txt
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# cat=node/Binary/1000; type=string; label=Path to node binary
|
||||||
|
nodeBinaryPath = /usr/local/bin/node
|
||||||
|
|
||||||
|
# cat=mjml/Binary/2000; type=string; label=Path to mjml binary
|
||||||
|
mjmlBinaryPath = ../node_modules/.bin/
|
||||||
|
|
||||||
|
# cat=mjml/Binary/3000; type=string; label=mjml binary
|
||||||
|
mjmlBinary = mjml
|
||||||
|
|
||||||
|
# cat=mjml/Binary/4000; type=string; label=mjml params
|
||||||
|
mjmlParams = -s -m
|
32
ext_emconf.php
Normal file
32
ext_emconf.php
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$EM_CONF[$_EXTKEY] = [
|
||||||
|
'title' => 'Mjml',
|
||||||
|
'description' => 'Mjml view using mjml over npm',
|
||||||
|
'category' => 'misc',
|
||||||
|
'shy' => 0,
|
||||||
|
'version' => '1.0.0',
|
||||||
|
'state' => 'stable',
|
||||||
|
'clearCacheOnLoad' => 1,
|
||||||
|
'author' => '',
|
||||||
|
'author_email' => '',
|
||||||
|
'author_company' => '',
|
||||||
|
'autoload' =>
|
||||||
|
[
|
||||||
|
'psr-4' => ['Saccas\\Mjml\\' => 'Classes']
|
||||||
|
],
|
||||||
|
'constraints' => [
|
||||||
|
'depends' => [
|
||||||
|
'php' => '7.0.0-0.0.0',
|
||||||
|
'typo3' => '8.7.*',
|
||||||
|
'extbase' => '',
|
||||||
|
],
|
||||||
|
'conflicts' => [
|
||||||
|
],
|
||||||
|
'suggests' => [
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'_md5_values_when_last_written' => 'a:0:{}',
|
||||||
|
'suggests' => [
|
||||||
|
],
|
||||||
|
];
|
28
ext_icon.svg
Normal file
28
ext_icon.svg
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1024 1024" style="enable-background:new 0 0 1024 1024;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:url(#Rectangle-1_1_);}
|
||||||
|
.st1{fill:#FFFFFF;}
|
||||||
|
</style>
|
||||||
|
<title>Logo</title>
|
||||||
|
<desc>Created with Sketch.</desc>
|
||||||
|
<g id="Page-1">
|
||||||
|
<g id="Logo">
|
||||||
|
|
||||||
|
<linearGradient id="Rectangle-1_1_" gradientUnits="userSpaceOnUse" x1="-254.2534" y1="1536.5005" x2="-254.2485" y2="1535.5005" gradientTransform="matrix(1024 0 0 -1024 260865 1573377)">
|
||||||
|
<stop offset="0" style="stop-color:#F46E42"/>
|
||||||
|
<stop offset="1" style="stop-color:#E3515B"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path id="Rectangle-1" class="st0" d="M62,0.5h900c34.2,0,62,27.8,62,62v900c0,34.2-27.8,62-62,62H62c-34.2,0-62-27.8-62-62v-900 C0,28.3,27.8,0.5,62,0.5z"/>
|
||||||
|
<g id="Group" transform="translate(288.000000, 318.000000)">
|
||||||
|
<circle id="Oval-1" class="st1" cx="398" cy="49.5" r="49"/>
|
||||||
|
<circle id="Oval-1-Copy-2" class="st1" cx="398" cy="338.5" r="49"/>
|
||||||
|
<circle id="Oval-1-Copy" class="st1" cx="50" cy="194.5" r="49"/>
|
||||||
|
<path class="st1" d="M261.4,98.5H49.5C22.3,98.5,0,76.2,0,49v0C0,21.8,22.3-0.5,49.5-0.5l211.9,0c27.2,0,49.5,22.3,49.5,49.5v0 C310.9,76.2,288.6,98.5,261.4,98.5z"/>
|
||||||
|
<path class="st1" d="M397.5,243.5H185.5c-27.2,0-49.5-22.3-49.5-49.5v0c0-27.2,22.3-49.5,49.5-49.5h211.9 c27.2,0,49.5,22.3,49.5,49.5v0C447,221.2,424.7,243.5,397.5,243.5z"/>
|
||||||
|
<path class="st1" d="M261.4,388H49.5C22.3,388,0,365.7,0,338.5v0C0,311.3,22.3,289,49.5,289h211.9c27.2,0,49.5,22.3,49.5,49.5v0 C310.9,365.7,288.6,388,261.4,388z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
6
package.json
Normal file
6
package.json
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"name": "mjml-typo3",
|
||||||
|
"dependencies": {
|
||||||
|
"mjml": "^3.3.5"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue