Skip to content

Instantly share code, notes, and snippets.

@mneuhaus
Last active April 6, 2016 11:52
Show Gist options
  • Select an option

  • Save mneuhaus/36b0db58ffe436f4b6d3c6ba010119cf to your computer and use it in GitHub Desktop.

Select an option

Save mneuhaus/36b0db58ffe436f4b6d3c6ba010119cf to your computer and use it in GitHub Desktop.
{namespace v=FluidTYPO3\Vhs\ViewHelpers}
{namespace flux=FluidTYPO3\Flux\ViewHelpers}
{namespace t=Famelo\Template\ViewHelpers}
<f:layout name="{v:extension.loaded(extensionName: 'fluidcontent_core', then: 'ContentCore', else: 'Content')}" />
<f:section name="Configuration">
<flux:form id="contact" options="{group: 'forms'}" label="Kontaktformular für Footer">
<flux:field.text name="introduction" label="Einleitung" rows="3" />
<flux:field.text name="introductionglobalise" label="Einleitung (globalise)" rows="3" />
<flux:field.input name="recipient" label="Empfänger" required="1" />
<flux:field.input name="phone" label="Telefon" required="1" />
<flux:field.input name="subject" label="E-Mail Betreff" required="1" />
<flux:field.text name="successMessage" label="Bestätigungstext" rows="2" />
<t:flux.validate name="name" as="NotEmpty" />
<t:flux.validate name="email" as="EmailAddress" />
<t:flux.validate name="email" as="NotEmpty" />
<t:flux.validate name="message" as="NotEmpty" />
</flux:form>
</f:section>
<f:section name="Main">
<div class="row">
<div class="col-xs-12">
<div class="container bordered">
<div class="row">
<div class="col-sm-6">
<div class="logo">
<a href="#">
<span class="icon-logo"></span>
</a>
</div>
<p class="contacttext">
{introduction -> f:format.nl2br()}
</p>
<div class="globaliselogo">
<a href="https://www.globalise.com" title="Globalise Partner">
<img src="/typo3conf/ext/template/Resources/Public/Media/globalise_logo.png" alt="Globalise - The Global Interim Management Group" />
</a>
</div>
<p class="contacttext grey">
{introductionglobalise -> f:format.nl2br()}
</p>
</div>
<div class="col-sm-6">
<div class="container">
<div class="row">
<div class="col-xs-12">
<a class="action" href="tel:{phone}">
<span class="icon-phone icon-blue"></span> {phone}
</a>
<a class="action mail" href="mailto:{recipient}">
<span class="icon-mail icon-blue"></span> {recipient}
</a>
</div>
</div>
<f:form extensionName="template" pluginName="content" id="form{record.uid}" section="form{record.uid}" noCache="1" class="ajax-form">
<f:form.hidden name="nextSection" value="Success" />
<f:form.hidden name="form" value="contact" />
<f:comment>spam honeypot trap</f:comment>
<f:form.textfield name="subject" id="form-subject-3897" />
<f:comment>spam time trap, if it's send in under 5seconds it's spam</f:comment>
<f:form.hidden name="formtoken" value="{formtoken}" />
<div class="row">
<div class="col-xs-12">
<f:form.textfield name="name" class="form-control" placeholder="{f:translate(key: 'contact.name', extensionName: 'template')->v:format.trim()}" value="{name}"/>
<f:if condition="{validationResults.name}">
<f:for each="{validationResults.name}" as="error">
<span class="error"><f:translate key="LLL:EXT:template/Resources/Private/Language/validation.xlf:error.{error.code}" default="{error.code}: {error.message}"/></span>
</f:for>
</f:if>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<f:form.textfield name="email" class="form-control" placeholder="{f:translate(key: 'contact.mail', extensionName: 'template')->v:format.trim()}" value="{email}"/>
<f:if condition="{validationResults.email}">
<f:for each="{validationResults.email}" as="error">
<span class="error"><f:translate key="LLL:EXT:template/Resources/Private/Language/validation.xlf:error.{error.code}" default="{error.code}: {error.message}"/></span>
</f:for>
</f:if>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<f:form.textarea name="message" class="form-control" placeholder="{f:translate(key: 'contact.message', extensionName: 'template')->v:format.trim()}" value="{message}" />
<f:if condition="{validationResults.message}">
<f:for each="{validationResults.message}" as="error">
<span class="error"><f:translate key="LLL:EXT:template/Resources/Private/Language/validation.xlf:error.{error.code}" default="{error.code}: {error.message}"/></span>
</f:for>
</f:if>
<button type="submit" class="btn btn-default pull-right">
<f:translate key="contact.submit" extensionName="template"/>
</button>
</div>
<div class="spinner">
<div class="bounce1"></div>
<div class="bounce2"></div>
<div class="bounce3"></div>
</div>
</div>
</f:form>
</div>
</div>
</div>
</div>
</div>
</div>
</f:section>
<f:section name="Success">
<div id="form{record.uid}">
<div class="row">
<div class="col-xs-12">
<p class="contacttext">
{successMessage}
</p>
</div>
</div>
</div>
<t:sendMail subject="{subject}" recipients="{recipient}">
<strong>{name}</strong>
<strong>{email}</strong>
<p>{message}</p>
</t:sendMail>
</f:section>
<?php
namespace Famelo\Template\Controller;
/*
* This file is part of the FluidTYPO3/Fluidcontent project under GPLv2 or later.
*
* For the full copyright and license information, please read the
* LICENSE.md file that was distributed with this source code.
*/
use FluidTYPO3\Fluidcontent\Controller\AbstractContentController;
use FluidTYPO3\Fluidcontent\Controller\ContentControllerInterface;
use Famelo\Template\ViewHelpers\Flux\ValidateViewHelper;
use TYPO3\CMS\Extbase\Validation\Validator\ConjunctionValidator;
/**
* Flexible Content Element Plugin Rendering Controller
*
* @route off
*/
class ContentController extends AbstractContentController implements ContentControllerInterface {
/**
* Calls the specified action method and passes the arguments.
*
* If the action returns a string, it is appended to the content in the
* response object. If the action doesn't return anything and a valid
* view exists, the view is rendered automatically.
*
* @return void
* @api
*/
protected function callActionMethod() {
$preparedArguments = array();
/** @var \TYPO3\CMS\Extbase\Mvc\Controller\Argument $argument */
foreach ($this->arguments as $argument) {
$preparedArguments[] = $argument->getValue();
}
$this->emitBeforeCallActionMethodSignal($preparedArguments);
$actionResult = call_user_func_array(array($this, $this->actionMethodName), $preparedArguments);
if ($actionResult === null && $this->view instanceof ViewInterface) {
$this->response->appendContent($this->view->render());
} elseif (is_string($actionResult) && $actionResult !== '') {
$this->response->appendContent($actionResult);
} elseif (is_object($actionResult) && method_exists($actionResult, '__toString')) {
$this->response->appendContent((string) $actionResult);
}
}
/**
* Adds the needed validators to the Arguments:
*
* - Validators checking the data type from the @param annotation
* - Custom validators specified with validate annotations.
* - Model-based validators (validate annotations in the model)
* - Custom model validator classes
*
* @return void
*/
protected function initializeActionMethodValidators() {
parent::initializeActionMethodValidators();
foreach (ValidateViewHelper::getValidations() as $argument => $validators) {
$argument = $this->arguments->addNewArgument($argument, 'string');
$conjunctionValidator = new ConjunctionValidator();
foreach ($validators as $validatorName) {
$validator = $this->validatorResolver->createValidator($validatorName);
$conjunctionValidator->addValidator($validator);
}
$argument->setValidator($conjunctionValidator);
}
}
public function formAction($formName) {
$salt = 'as89ud0ajsd0a90sdjapjsd0ß9jasdj09apisd0ß';
$arguments = array_merge(
$this->settings,
$this->request->getArguments(),
array(
'page' => $GLOBALS['TSFE']->page,
'user' => $GLOBALS['TSFE']->fe_user->user,
'record' => $this->getRecord(),
'contentObject' => $this->configurationManager->getContentObject(),
'cookies' => $_COOKIE,
'session' => $_SESSION,
'formtoken' => sha1(time() . $salt)
)
);
if (!$this->request->hasArgument('form') || $this->request->getArgument('form') !== $formName) {
return $this->view->renderStandaloneSection('Main', $arguments);
}
$validationResult = $this->arguments->getValidationResults();
// honeypot :)
if ($this->request->hasArgument('subject') && strlen($this->request->getArgument('subject')) > 0) {
return $this->view->renderStandaloneSection('Main', $arguments);
}
if ($validationResult->hasErrors()) {
$arguments['validationResults'] = $validationResult->getFlattenedErrors();
return $this->view->renderStandaloneSection('Main', $arguments);
}
if ($this->request->hasArgument('nextSection')) {
// time trap (any form send within 5 seconds can only be crap)
if ($this->request->hasArgument('formtoken') === TRUE) {
$submittedToken = $this->request->getArgument('formtoken');
for($i = 0; $i <= 5; $i++) {
$testToken = sha1((time() - $i) . $salt);
if ($submittedToken === $testToken) {
return $this->view->renderStandaloneSection('Main', $arguments);
}
}
}
return $this->view->renderStandaloneSection($this->request->getArgument('nextSection'), $arguments);
}
}
public function contactAction() {
return $this->formAction('contact');
}
}
<?php
namespace Famelo\Template\ViewHelpers;
/* *
* This script is part of the TYPO3 project - inspiring people to share! *
* *
* TYPO3 is free software; you can redistribute it and/or modify it under *
* the terms of the GNU General Public License version 2 as published by *
* the Free Software Foundation. *
* *
* This script is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- *
* TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General *
* Public License for more details. *
* */
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Mail\MailMessage;
use TYPO3\CMS\Frontend\Category\Collection\CategoryCollection;
/**
*/
class SendMailViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper {
/**
*
* @param string $subject
* @param string $recipients
* @param string $senderName
* @param string $senderEmail
* @return string Rendered tag
*/
public function render($subject, $recipients, $senderName = NULL, $senderEmail = NULL) {
$mail = new MailMessage();
$mail->setSubject($subject);
$mail->setTo(explode(',', $recipients));
$mail->setBody($this->renderChildren(), 'text/html');
if ($senderEmail === NULL) {
$senderEmail = $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress'];
}
if ($senderName === NULL) {
$senderName = $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromName'];
}
$mail->setFrom($senderEmail, $senderName);
$mail->send();
}
}
<?php
namespace Famelo\Template\ViewHelpers\Flux;
/*
* This file is part of the FluidTYPO3/Flux project under GPLv2 or later.
*
* For the full copyright and license information, please read the
* LICENSE.md file that was distributed with this source code.
*/
use FluidTYPO3\Flux\ViewHelpers\AbstractFormViewHelper;
use TYPO3\CMS\Fluid\Core\Rendering\RenderingContextInterface;
/**
*/
class ValidateViewHelper extends AbstractFormViewHelper {
/**
* @var array
*/
protected static $validations = array();
/**
* Initialize
* @return void
*/
public function initializeArguments() {
parent::initializeArguments();
$this->registerArgument('name', 'string', 'Name of the argument to validate', TRUE);
$this->registerArgument('as', 'string', 'validator to apply', TRUE);
}
/**
* @param array $arguments
* @param \Closure $renderChildrenClosure
* @param RenderingContextInterface $renderingContext
* @return void
*/
static public function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext) {
if (!isset(static::$validations[$arguments['name']])) {
static::$validations[$arguments['name']] = array();
}
static::$validations[$arguments['name']][$arguments['as']] = $arguments['as'];
}
static public function getValidations() {
return static::$validations;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment