mirror of
https://github.com/saccas/mjml-typo3.git
synced 2024-12-22 18:46:10 +01:00
commit
75dbb1b132
12 changed files with 346 additions and 36 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -12,3 +12,7 @@
|
|||
.sass-cache
|
||||
node_modules
|
||||
bower_components
|
||||
composer.lock
|
||||
package-lock.json
|
||||
web
|
||||
vendor
|
||||
|
|
44
.travis.yml
Normal file
44
.travis.yml
Normal file
|
@ -0,0 +1,44 @@
|
|||
dist: trusty
|
||||
sudo: false
|
||||
language: php
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.composer/cache
|
||||
|
||||
install:
|
||||
- composer require typo3/cms="$TYPO3_VERSION"
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- php: 7.1
|
||||
env: TYPO3_VERSION=^8.7
|
||||
- php: 7.2
|
||||
env: TYPO3_VERSION=^8.7
|
||||
|
||||
- stage: test
|
||||
script:
|
||||
- composer lint
|
||||
- composer cgl
|
||||
- composer test
|
||||
|
||||
- stage: deploy
|
||||
if: tag IS present
|
||||
php: 7.1
|
||||
before_install: skip
|
||||
install: skip
|
||||
before_script: skip
|
||||
script: |
|
||||
echo -e "Preparing upload of release ${TRAVIS_TAG} to TER\n"
|
||||
|
||||
TAG_ANNOTATION="$(git tag -n -l $TRAVIS_TAG)"
|
||||
TAG_MESSAGE="${TAG_ANNOTATION#* }"
|
||||
|
||||
git reset --hard
|
||||
git clean -xfd
|
||||
|
||||
export PATH=$PATH:$(composer global config bin-dir --absolute 2>/dev/null)
|
||||
composer global require helhum/ter-client dev-master
|
||||
|
||||
echo "Uploading release ${TRAVIS_TAG} to TER"
|
||||
ter-client upload $(composer config extra.typo3/cms.extension-key) . -u "$TYPO3_ORG_USERNAME" -p "$TYPO3_ORG_PASSWORD" -m "$TAG_MESSAGE"
|
|
@ -1,20 +1,6 @@
|
|||
<?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\Fluid\View\StandaloneView;
|
||||
use TYPO3\CMS\Form\Domain\Finishers\Exception\FinisherException;
|
||||
use TYPO3\CMS\Form\Domain\Runtime\FormRuntime;
|
||||
|
|
45
Classes/Domain/Renderer/Command.php
Normal file
45
Classes/Domain/Renderer/Command.php
Normal file
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
namespace Saccas\Mjml\Domain\Renderer;
|
||||
|
||||
use TYPO3\CMS\Core\Utility\CommandUtility;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
class Command implements RendererInterface
|
||||
{
|
||||
public function getHtmlFromMjml($mjml)
|
||||
{
|
||||
$configuration = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['mjml']);
|
||||
|
||||
$temporaryMjmlFileWithPath = GeneralUtility::tempnam('mjml_', '.mjml');
|
||||
|
||||
GeneralUtility::writeFileToTypo3tempDir($temporaryMjmlFileWithPath, $mjml);
|
||||
|
||||
// see https://mjml.io/download and https://www.npmjs.com/package/mjml-cli
|
||||
$cmd = $configuration['nodeBinaryPath'] . ' ' . $configuration['mjmlBinaryPath'] . $configuration['mjmlBinary'];
|
||||
$args = $configuration['mjmlParams'] . ' ' . $temporaryMjmlFileWithPath;
|
||||
|
||||
$result = [];
|
||||
$returnValue = '';
|
||||
CommandUtility::exec($this->getEscapedCommand($cmd, $args), $result, $returnValue);
|
||||
|
||||
GeneralUtility::unlink_tempfile($temporaryMjmlFileWithPath);
|
||||
|
||||
return implode('', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $cmd
|
||||
* @param string $args
|
||||
* @return string
|
||||
*/
|
||||
protected function getEscapedCommand(string $cmd, string $args)
|
||||
{
|
||||
$escapedCmd = escapeshellcmd($cmd);
|
||||
|
||||
$argsArray = explode(' ', $args);
|
||||
$escapedArgsArray = CommandUtility::escapeShellArguments($argsArray);
|
||||
$escapedArgs = implode(' ', $escapedArgsArray);
|
||||
|
||||
return $escapedCmd . ' ' . $escapedArgs;
|
||||
}
|
||||
}
|
16
Classes/Domain/Renderer/RendererInterface.php
Normal file
16
Classes/Domain/Renderer/RendererInterface.php
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
namespace Saccas\Mjml\Domain\Renderer;
|
||||
|
||||
/**
|
||||
* Defines API of possible renderers.
|
||||
*/
|
||||
interface RendererInterface
|
||||
{
|
||||
/**
|
||||
* Convert mjml strings into html.
|
||||
*
|
||||
* @param string $mjml
|
||||
* @return string
|
||||
*/
|
||||
public function getHtmlFromMjml($mjml);
|
||||
}
|
|
@ -1,34 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace Saccas\Mjml\View;
|
||||
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use Saccas\Mjml\Domain\Renderer\RendererInterface;
|
||||
use TYPO3\CMS\Fluid\View\StandaloneView;
|
||||
use TYPO3\CMS\Core\Utility\CommandUtility;
|
||||
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
||||
|
||||
class MjmlBasedView extends StandaloneView
|
||||
{
|
||||
function render()
|
||||
/**
|
||||
* @var RendererInterface
|
||||
*/
|
||||
protected $renderer;
|
||||
|
||||
public function __construct(ContentObjectRenderer $contentObject = null, RendererInterface $renderer = null)
|
||||
{
|
||||
return $this->getHtmlFromMjml(parent::render());
|
||||
parent::__construct($contentObject);
|
||||
|
||||
$this->renderer = $renderer;
|
||||
if ($this->renderer === null) {
|
||||
$this->renderer = $this->objectManager->get(RendererInterface::class);
|
||||
}
|
||||
}
|
||||
|
||||
protected function getHtmlFromMjml($mjml)
|
||||
public function render($actionName = null)
|
||||
{
|
||||
$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);
|
||||
return $this->renderer->getHtmlFromMjml(parent::render($actionName));
|
||||
}
|
||||
}
|
||||
|
|
22
Tests/Unit/AbstractUnitTestCase.php
Normal file
22
Tests/Unit/AbstractUnitTestCase.php
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
namespace Saccas\Mjml\Tests\Unit;
|
||||
|
||||
use TYPO3\CMS\Core\Cache\Backend\NullBackend;
|
||||
use TYPO3\CMS\Core\Cache\CacheManager;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
|
||||
|
||||
abstract class AbstractUnitTestCase extends UnitTestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
GeneralUtility::makeInstance(CacheManager::class)
|
||||
->setCacheConfigurations([
|
||||
'extbase_object' => [
|
||||
'backend' => NullBackend::class,
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
66
Tests/Unit/Domain/Renderer/CommandTest.php
Normal file
66
Tests/Unit/Domain/Renderer/CommandTest.php
Normal file
File diff suppressed because one or more lines are too long
55
Tests/Unit/View/MjmlBasedViewTest.php
Normal file
55
Tests/Unit/View/MjmlBasedViewTest.php
Normal file
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
namespace Saccas\Mjml\Tests\Unit\View;
|
||||
|
||||
use Saccas\Mjml\Domain\Renderer\RendererInterface;
|
||||
use Saccas\Mjml\Tests\Unit\AbstractUnitTestCase;
|
||||
use Saccas\Mjml\View\MjmlBasedView;
|
||||
|
||||
class MjmlBasedViewTest extends AbstractUnitTestCase
|
||||
{
|
||||
public const EXAMPLE_MJML_TEMPLATE = '<mjml>
|
||||
<mj-body>
|
||||
<mj-container>
|
||||
<mj-section>
|
||||
<mj-column>
|
||||
<mj-image src="/assets/img/easy-and-quick.png" width="112" />
|
||||
<mj-text font-size="20px" color="#595959" align="center">Easy and Quick</mj-text>
|
||||
</mj-column>
|
||||
<mj-column>
|
||||
<mj-image src="/assets/img/responsive.png" width="135" />
|
||||
<mj-text font-size="20px" color="#595959" align="center">Responsive</mj-text>
|
||||
</mj-column>
|
||||
</mj-section>
|
||||
<mj-section>
|
||||
<mj-column>
|
||||
<mj-button background-color="#F45E43" font-size="15px">Discover</mj-button>
|
||||
</mj-column>
|
||||
</mj-section>
|
||||
</mj-container>
|
||||
</mj-body>
|
||||
</mjml>
|
||||
';
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function viewCallsRendererAndReturnsRenderedHtml()
|
||||
{
|
||||
$expectedHtml = '<h1>Simple HTML</h1>';
|
||||
$rendererMock = $this->getMockBuilder(RendererInterface::class)->getMock();
|
||||
$rendererMock->expects($this->once())
|
||||
->method('getHtmlFromMjml')
|
||||
->with(static::EXAMPLE_MJML_TEMPLATE)
|
||||
->willReturn($expectedHtml);
|
||||
|
||||
$subject = new MjmlBasedView(null, $rendererMock);
|
||||
$subject->setTemplateSource(static::EXAMPLE_MJML_TEMPLATE);
|
||||
$result = $subject->render();
|
||||
|
||||
$this->assertSame(
|
||||
$expectedHtml,
|
||||
$result,
|
||||
'Rendering of view did not return expected HTML.'
|
||||
);
|
||||
}
|
||||
}
|
|
@ -10,13 +10,45 @@
|
|||
"Saccas\\Mjml\\": "Classes/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Saccas\\Mjml\\Tests\\": "Tests/"
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.0.0 <=7.2.99",
|
||||
"typo3/cms-core": ">=8.7.0,<8.9.99"
|
||||
"typo3/cms-core": "^8.7.0",
|
||||
"typo3/cms-form": "^8.7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"squizlabs/php_codesniffer": "^3.2.0",
|
||||
"typo3/cms": "^8.7.0",
|
||||
"typo3/testing-framework": "^1.2.2"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": [
|
||||
"! find Classes -type f -name \"*.php\" -exec php -d error_reporting=32767 -l {} \\; 2>&1 >&- | grep \"^\"",
|
||||
"! find Tests -type f -name \"*.php\" -exec php -d error_reporting=32767 -l {} \\; 2>&1 >&- | grep \"^\""
|
||||
],
|
||||
"cgl": [
|
||||
"./vendor/bin/phpcs"
|
||||
],
|
||||
"test": [
|
||||
"TYPO3_PATH_ROOT=web ./vendor/bin/phpunit"
|
||||
],
|
||||
"post-install-cmd": [
|
||||
"npm install"
|
||||
]
|
||||
},
|
||||
"replace": {
|
||||
"mjml": "self.version",
|
||||
"typo3-ter/mjml": "self.version"
|
||||
},
|
||||
"extra": {
|
||||
"typo3/cms": {
|
||||
"extension-key": "mjml",
|
||||
"cms-package-dir": "{$vendor-dir}/typo3/cms",
|
||||
"web-dir": "web"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
17
phpcs.xml.dist
Normal file
17
phpcs.xml.dist
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0"?>
|
||||
<ruleset name="cgl">
|
||||
<description>The coding standard for this extension.</description>
|
||||
|
||||
<file>./Classes/</file>
|
||||
|
||||
<!-- Set default settings -->
|
||||
<arg value="s"/>
|
||||
<arg name="colors"/>
|
||||
<arg name="encoding" value="utf-8" />
|
||||
<arg name="extensions" value="php" />
|
||||
|
||||
<rule ref="PSR2">
|
||||
<!-- As it does not work with new array syntax. -->
|
||||
<exclude name="Squiz.Arrays.ArrayBracketSpacing.SpaceBeforeBracket" />
|
||||
</rule>
|
||||
</ruleset>
|
28
phpunit.xml.dist
Normal file
28
phpunit.xml.dist
Normal file
|
@ -0,0 +1,28 @@
|
|||
<phpunit
|
||||
backupGlobals="false"
|
||||
backupStaticAttributes="false"
|
||||
bootstrap="./vendor/typo3/testing-framework/Resources/Core/Build/UnitTestsBootstrap.php"
|
||||
|
||||
colors="true"
|
||||
convertErrorsToExceptions="false"
|
||||
convertWarningsToExceptions="false"
|
||||
forceCoversAnnotation="false"
|
||||
processIsolation="false"
|
||||
stopOnError="false"
|
||||
stopOnFailure="false"
|
||||
stopOnIncomplete="false"
|
||||
stopOnSkipped="false"
|
||||
verbose="false">
|
||||
|
||||
<testsuites>
|
||||
<testsuite name="unit-tests">
|
||||
<directory>./Tests/Unit</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory suffix=".php">./Classes</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
Loading…
Reference in a new issue