mirror of
https://github.com/typemill/typemill.git
synced 2025-07-17 12:31:13 +02:00
add backend form builder, add captcha and fix shortcodes
This commit is contained in:
@@ -28,7 +28,7 @@
|
||||
"jbroadway/urlify": "1.1.3",
|
||||
"laminas/laminas-permissions-acl": "^2.10",
|
||||
"akrabat/proxy-detection-middleware": "^1.0.0",
|
||||
"gregwar/captcha": "1.*"
|
||||
"gregwar/captcha": "master"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
15
composer.lock
generated
15
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "0cc1a21b272d67b53b9e5f448c2960ac",
|
||||
"content-hash": "841b98a23a247d8faad15d86df8cbeba",
|
||||
"packages": [
|
||||
{
|
||||
"name": "akrabat/proxy-detection-middleware",
|
||||
@@ -223,16 +223,16 @@
|
||||
},
|
||||
{
|
||||
"name": "gregwar/captcha",
|
||||
"version": "v1.2.0",
|
||||
"version": "dev-master",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Gregwar/Captcha.git",
|
||||
"reference": "6e5b61b66ac89885b505153f4ef9a74ffa5b3074"
|
||||
"reference": "5b8323637b502d3dbcbe28a74633dad8aed63452"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Gregwar/Captcha/zipball/6e5b61b66ac89885b505153f4ef9a74ffa5b3074",
|
||||
"reference": "6e5b61b66ac89885b505153f4ef9a74ffa5b3074",
|
||||
"url": "https://api.github.com/repos/Gregwar/Captcha/zipball/5b8323637b502d3dbcbe28a74633dad8aed63452",
|
||||
"reference": "5b8323637b502d3dbcbe28a74633dad8aed63452",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -244,6 +244,7 @@
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^6.4"
|
||||
},
|
||||
"default-branch": true,
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
@@ -274,9 +275,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Gregwar/Captcha/issues",
|
||||
"source": "https://github.com/Gregwar/Captcha/tree/v1.2.0"
|
||||
"source": "https://github.com/Gregwar/Captcha/tree/master"
|
||||
},
|
||||
"time": "2023-03-24T22:12:41+00:00"
|
||||
"time": "2023-05-08T15:17:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "jbroadway/urlify",
|
||||
|
@@ -9,6 +9,8 @@
|
||||
* DONE: License feature
|
||||
* DONE: Enhance with plugins
|
||||
|
||||
[:contactform :]
|
||||
|
||||
----
|
||||
|
||||
## Visual Editor
|
||||
@@ -93,20 +95,20 @@
|
||||
## Open tasks
|
||||
|
||||
* DONE: Sitemap and ping
|
||||
* SVG checker
|
||||
* Version check
|
||||
* DONE: Version check
|
||||
* DONE: Proxy support
|
||||
* DONE: SVG checker: https://github.com/TribalSystems/SVG-Sanitizer
|
||||
* NEARLY DONE: Backend form builder
|
||||
* Markdown secure rendering
|
||||
* Responsive design
|
||||
* Backend form builder
|
||||
* Proxy support
|
||||
* Image generation on the fly
|
||||
* Captcha integration
|
||||
* Clear cache
|
||||
* Show security Log
|
||||
* Fix error api systemnavi
|
||||
* Reference feature
|
||||
* Typemill Utilities
|
||||
* Clear cache
|
||||
* Show security Log
|
||||
* User search only for +10 users
|
||||
* Fix error api systemnavi
|
||||
|
||||
## Cleanups:
|
||||
|
||||
|
@@ -1 +1 @@
|
||||
["# ToDos Version 2","[TOC]","## System settings","* DONE: Migrate from backend to frontend with vue and api\n* DONE: Redesign\n* DONE: License feature\n* DONE: Enhance with plugins","----","## Visual Editor","* DONE: Refactor and redesign\n* DONE: Fix toc component in new block\n* DONE: Fix hr component in new block\n* DONE: finish shortcode component\n* DONE: Fix inline formats\n* DONE: fix lenght of page\n* DONE: Fix design of new block at the end (background color)\n* DONE: Move Block\n* DONE: Fix headline design\n* DONE: Fix save on two enter\n* DONE: fix quote design\n* DONE: Fix toc preview\n* DONE: disable enable \n* DONE: Add load sign (from navigation)\n* DONE: File is not published from tmp to media\/files if you save the block.\n* ToDo: Customfields not styled yet.\n* ToDo: Warn if open another block\n* ToDo: finish youtube component","## Raw Editor","* DONE: Refactor and redesign\n* DONE: Integrate highlighting","## Navigation","* DONE: Refactor and redesign\n* DONE: fix status in navigation\n* DONE: refresh navigation after changes\n* ToDo: fix error messages\n* ToDo: Wrong frontend navigation if unpublished pages","## Publish Controller","* DONE: Refactor and redesign\n* DONE: Create \n* DONE: publish\n* DONE: unpublish\n* DONE: discard\n* DONE: delete\n* DONE: save draft\n* DONE: switch to raw","## Meta Tabs","* DONE: Refactor and redesign\n* DONE: Enhance with plugins","## Medialib","* DONE: Refactor and redesign","## Posts","* DONE: Refactor and redesign","## Plugins","* Asset Class in progress","## Frontend","* DONE: Refactor\n* DONE: Test restrictions","## Other big tasks","* DONE: System setup\n* DONE: Recover Password","## Medium tasks","* DONE: Merge processAssets modell\n* DONE: Table of content duplicated for published pages\n* DONE: Session handling: csrf fail and session start error if restrictions are active\n* DONE: Image and files for meta","## Open tasks","* DONE: Sitemap and ping\n* DONE: Version check\n* DONE: Proxy support\n* DONE: SVG checker: https:\/\/github.com\/TribalSystems\/SVG-Sanitizer\n* Markdown secure rendering\n* Responsive design\n* Backend form builder\n* Image generation on the fly\n* Captcha integration\n* Fix error api systemnavi\n* Reference feature\n* Typemill Utilities\n* Clear cache\n* Show security Log\n* User search only for +10 users","## Cleanups:","* DONE: Events\n* Error messages\n* Translations","## Info: Select userroles","* Userroles for file restriction: in vue-blox-components loaded via api\n* Userroles for userfields: in php model user getUserFields()\n* Userroles for meta: in php controller apiAuthorMeta getMeta()\n* Plugins and themes: in php model extension getThemeDefinitions()","## Info: License Check","* On activation in apiControllerExtension. It checks the license in yaml.\n* In plugin php code with setPremiumLicense\n* In static plugins, it checks manual premium list and method setPremiumLicense and more "]
|
||||
["# ToDos Version 2","[TOC]","## System settings","* DONE: Migrate from backend to frontend with vue and api\n* DONE: Redesign\n* DONE: License feature\n* DONE: Enhance with plugins","[:contactform :]","----","## Visual Editor","* DONE: Refactor and redesign\n* DONE: Fix toc component in new block\n* DONE: Fix hr component in new block\n* DONE: finish shortcode component\n* DONE: Fix inline formats\n* DONE: fix lenght of page\n* DONE: Fix design of new block at the end (background color)\n* DONE: Move Block\n* DONE: Fix headline design\n* DONE: Fix save on two enter\n* DONE: fix quote design\n* DONE: Fix toc preview\n* DONE: disable enable \n* DONE: Add load sign (from navigation)\n* DONE: File is not published from tmp to media\/files if you save the block.\n* ToDo: Customfields not styled yet.\n* ToDo: Warn if open another block\n* ToDo: finish youtube component","## Raw Editor","* DONE: Refactor and redesign\n* DONE: Integrate highlighting","## Navigation","* DONE: Refactor and redesign\n* DONE: fix status in navigation\n* DONE: refresh navigation after changes\n* ToDo: fix error messages\n* ToDo: Wrong frontend navigation if unpublished pages","## Publish Controller","* DONE: Refactor and redesign\n* DONE: Create \n* DONE: publish\n* DONE: unpublish\n* DONE: discard\n* DONE: delete\n* DONE: save draft\n* DONE: switch to raw","## Meta Tabs","* DONE: Refactor and redesign\n* DONE: Enhance with plugins","## Medialib","* DONE: Refactor and redesign","## Posts","* DONE: Refactor and redesign","## Plugins","* Asset Class in progress","## Frontend","* DONE: Refactor\n* DONE: Test restrictions","## Other big tasks","* DONE: System setup\n* DONE: Recover Password","## Medium tasks","* DONE: Merge processAssets modell\n* DONE: Table of content duplicated for published pages\n* DONE: Session handling: csrf fail and session start error if restrictions are active\n* DONE: Image and files for meta","## Open tasks","* DONE: Sitemap and ping\n* DONE: Version check\n* DONE: Proxy support\n* DONE: SVG checker: https:\/\/github.com\/TribalSystems\/SVG-Sanitizer\n* DONE: Backend form builder\n* Handle formdata centrally ???\n* Image generation on the fly\n* Markdown secure rendering\n* Responsive design\n* Captcha integration\n* Fix error api systemnavi\n* Reference feature\n* Typemill Utilities\n* Clear cache\n* Show security Log\n* User search only for +10 users","## Cleanups:","* DONE: Events\n* Error messages\n* Translations","## Info: Select userroles","* Userroles for file restriction: in vue-blox-components loaded via api\n* Userroles for userfields: in php model user getUserFields()\n* Userroles for meta: in php controller apiAuthorMeta getMeta()\n* Plugins and themes: in php model extension getThemeDefinitions()","## Info: License Check","* On activation in apiControllerExtension. It checks the license in yaml.\n* In plugin php code with setPremiumLicense\n* In static plugins, it checks manual premium list and method setPremiumLicense and more "]
|
@@ -6,7 +6,7 @@ meta:
|
||||
heroimagealt: null
|
||||
owner: Sebastian
|
||||
author: null
|
||||
allowedrole: contributor
|
||||
allowedrole: ''
|
||||
alloweduser: null
|
||||
manualdate: null
|
||||
modified: '2023-06-19'
|
||||
|
@@ -736,6 +736,7 @@ class ParsedownExtension extends \ParsedownExtra
|
||||
|
||||
protected function blockShortcode($Line)
|
||||
{
|
||||
|
||||
if ($this->dispatcher && preg_match('/^\[:.*:\]/', $Line['text'], $matches))
|
||||
{
|
||||
return $this->createShortcodeArray($matches,$block = true);
|
||||
|
@@ -59,7 +59,7 @@ class ControllerApiAuthorArticle extends Controller
|
||||
}
|
||||
|
||||
# publish content
|
||||
$content = new Content($urlinfo['baseurl']);
|
||||
$content = new Content($urlinfo['baseurl'], $this->settings, $this->c->get('dispatcher'));
|
||||
$draftMarkdown = $content->getDraftMarkdown($item);
|
||||
$publish = $content->publishMarkdown($item, $draftMarkdown);
|
||||
if($publish !== true)
|
||||
@@ -141,7 +141,7 @@ class ControllerApiAuthorArticle extends Controller
|
||||
}
|
||||
|
||||
# publish content
|
||||
$content = new Content($urlinfo['baseurl']);
|
||||
$content = new Content($urlinfo['baseurl'], $this->settings, $this->c->get('dispatcher'));
|
||||
$draftMarkdown = $content->getDraftMarkdown($item);
|
||||
$content->unpublishMarkdown($item, $draftMarkdown);
|
||||
|
||||
@@ -218,7 +218,7 @@ class ControllerApiAuthorArticle extends Controller
|
||||
}
|
||||
|
||||
# save draft content
|
||||
$content = new Content($urlinfo['baseurl']);
|
||||
$content = new Content($urlinfo['baseurl'], $this->settings, $this->c->get('dispatcher'));
|
||||
$markdown = $params['title'] . PHP_EOL . PHP_EOL . $params['body'];
|
||||
$markdownArray = $content->markdownTextToArray($markdown);
|
||||
$content->saveDraftMarkdown($item, $markdownArray);
|
||||
@@ -281,7 +281,7 @@ class ControllerApiAuthorArticle extends Controller
|
||||
}
|
||||
|
||||
# save draft content
|
||||
$content = new Content($urlinfo['baseurl']);
|
||||
$content = new Content($urlinfo['baseurl'], $this->settings, $this->c->get('dispatcher'));
|
||||
$markdown = $params['title'] . PHP_EOL . PHP_EOL . $params['body'];
|
||||
$markdownArray = $content->markdownTextToArray($markdown);
|
||||
$content->publishMarkdown($item, $markdownArray);
|
||||
@@ -361,7 +361,7 @@ class ControllerApiAuthorArticle extends Controller
|
||||
}
|
||||
|
||||
# publish content
|
||||
$content = new Content($urlinfo['baseurl']);
|
||||
$content = new Content($urlinfo['baseurl'], $this->settings, $this->c->get('dispatcher'));
|
||||
$content->deleteDraft($item);
|
||||
|
||||
# refresh navigation and item
|
||||
@@ -896,7 +896,7 @@ class ControllerApiAuthorArticle extends Controller
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(404);
|
||||
}
|
||||
|
||||
$content = new Content($urlinfo['baseurl']);
|
||||
$content = new Content($urlinfo['baseurl'], $this->settings, $this->c->get('dispatcher'));
|
||||
|
||||
# check if it is a folder and if the folder has published pages.
|
||||
if($item->elementType == 'folder')
|
||||
|
@@ -50,7 +50,7 @@ class ControllerApiAuthorBlock extends Controller
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(404);
|
||||
}
|
||||
|
||||
$content = new Content($urlinfo['baseurl']);
|
||||
$content = new Content($urlinfo['baseurl'], $this->settings, $this->c->get('dispatcher'));
|
||||
$draftMarkdown = $content->getDraftMarkdown($item);
|
||||
|
||||
# if it is a new content-block
|
||||
@@ -154,7 +154,7 @@ class ControllerApiAuthorBlock extends Controller
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(404);
|
||||
}
|
||||
|
||||
$content = new Content($urlinfo['baseurl']);
|
||||
$content = new Content($urlinfo['baseurl'], $this->settings, $this->c->get('dispatcher'));
|
||||
|
||||
$draftMarkdown = $content->getDraftMarkdown($item);
|
||||
|
||||
@@ -247,7 +247,7 @@ class ControllerApiAuthorBlock extends Controller
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(404);
|
||||
}
|
||||
|
||||
$content = new Content($urlinfo['baseurl']);
|
||||
$content = new Content($urlinfo['baseurl'], $this->settings, $this->c->get('dispatcher'));
|
||||
|
||||
$draftMarkdown = $content->getDraftMarkdown($item);
|
||||
|
||||
@@ -353,7 +353,7 @@ class ControllerApiAuthorBlock extends Controller
|
||||
return $response->withHeader('Content-Type', 'application/json')->withStatus(404);
|
||||
}
|
||||
|
||||
$content = new Content($urlinfo['baseurl']);
|
||||
$content = new Content($urlinfo['baseurl'], $this->settings, $this->c->get('dispatcher'));
|
||||
|
||||
$draftMarkdown = $content->getDraftMarkdown($item);
|
||||
|
||||
|
@@ -7,7 +7,6 @@ use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Slim\Routing\RouteContext;
|
||||
use Typemill\Models\Navigation;
|
||||
use Typemill\Models\Content;
|
||||
use Typemill\Models\SvgSanitizer;
|
||||
use Typemill\Events\OnPagetreeLoaded;
|
||||
use Typemill\Events\OnItemLoaded;
|
||||
use Typemill\Events\OnMarkdownLoaded;
|
||||
@@ -17,10 +16,7 @@ use Typemill\Events\OnPageReady;
|
||||
class ControllerWebAuthor extends Controller
|
||||
{
|
||||
public function showBlox(Request $request, Response $response, $args)
|
||||
{
|
||||
|
||||
$svg = new SvgSanitizer();
|
||||
|
||||
{
|
||||
# get url for requested page
|
||||
$url = isset($args['route']) ? '/' . $args['route'] : '/';
|
||||
$urlinfo = $this->c->get('urlinfo');
|
||||
@@ -65,7 +61,7 @@ class ControllerWebAuthor extends Controller
|
||||
|
||||
$mainNavigation = $navigation->getMainNavigation($request->getAttribute('c_userrole'), $this->c->get('acl'), $urlinfo, $this->settings['editor']);
|
||||
|
||||
$content = new Content($urlinfo['baseurl']);
|
||||
$content = new Content($urlinfo['baseurl'], $this->settings, $this->c->get('dispatcher'));
|
||||
|
||||
$draftMarkdown = $content->getDraftMarkdown($item);
|
||||
$draftMarkdown = $this->c->get('dispatcher')->dispatch(new OnMarkdownLoaded($draftMarkdown), 'onMarkdownLoaded')->getData();
|
||||
@@ -134,7 +130,7 @@ class ControllerWebAuthor extends Controller
|
||||
|
||||
$mainNavigation = $navigation->getMainNavigation($request->getAttribute('c_userrole'), $this->c->get('acl'), $urlinfo, $this->settings['editor']);
|
||||
|
||||
$content = new Content($urlinfo['baseurl']);
|
||||
$content = new Content($urlinfo['baseurl'], $this->settings, $this->c->get('dispatcher'));
|
||||
|
||||
$draftMarkdown = $content->getDraftMarkdown($item);
|
||||
$draftMarkdown = $this->c->get('dispatcher')->dispatch(new OnMarkdownLoaded($draftMarkdown), 'onMarkdownLoaded')->getData();
|
||||
|
@@ -90,7 +90,7 @@ class ControllerWebFrontend extends Controller
|
||||
|
||||
|
||||
# GET THE CONTENT
|
||||
$content = new Content($urlinfo['baseurl']);
|
||||
$content = new Content($urlinfo['baseurl'], $this->settings, $this->c->get('dispatcher'));
|
||||
$liveMarkdown = $content->getLiveMarkdown($item);
|
||||
$liveMarkdown = $this->c->get('dispatcher')->dispatch(new OnMarkdownLoaded($liveMarkdown), 'onMarkdownLoaded')->getData();
|
||||
$markdownArray = $content->markdownTextToArray($liveMarkdown);
|
||||
|
@@ -361,7 +361,7 @@ class ParsedownExtension extends \ParsedownExtra
|
||||
}
|
||||
|
||||
$text = trim($Line['text'], '#');
|
||||
$headline = Slug::createSlug($Line['text'], $this->settings);
|
||||
$headline = Slug::createSlug($Line['text'], $this->settings['langattr']);
|
||||
|
||||
if ($this->strictMode and isset($text[0]) and $text[0] !== ' ')
|
||||
{
|
||||
@@ -815,7 +815,7 @@ class ParsedownExtension extends \ParsedownExtra
|
||||
}
|
||||
}
|
||||
|
||||
$html = $this->dispatcher->dispatch('onShortcodeFound', new OnShortcodeFound($shortcode))->getData();
|
||||
$html = $this->dispatcher->dispatch(new OnShortcodeFound($shortcode), 'onShortcodeFound')->getData();
|
||||
|
||||
# if no shortcode has been processed, add the original string
|
||||
if(is_array($html) OR is_object($html))
|
||||
|
46
system/typemill/Extensions/TwigCaptchaExtension.php
Normal file
46
system/typemill/Extensions/TwigCaptchaExtension.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace Typemill\Extensions;
|
||||
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFunction;
|
||||
use Gregwar\Captcha\CaptchaBuilder;
|
||||
|
||||
class TwigCaptchaExtension extends AbstractExtension
|
||||
{
|
||||
public function getFunctions()
|
||||
{
|
||||
return [
|
||||
new TwigFunction('captcha', array($this, 'captchaImage' ))
|
||||
];
|
||||
}
|
||||
|
||||
public function captchaImage($initialize = false)
|
||||
{
|
||||
|
||||
if(isset($_SESSION['captcha']) OR $initialize)
|
||||
{
|
||||
$builder = new CaptchaBuilder;
|
||||
$builder->build();
|
||||
|
||||
$error = '';
|
||||
if(isset($_SESSION['captcha']) && $_SESSION['captcha'] === 'error')
|
||||
{
|
||||
$error = '<span class="error">The captcha was wrong.</span>';
|
||||
}
|
||||
|
||||
$_SESSION['phrase'] = $builder->getPhrase();
|
||||
|
||||
$_SESSION['captcha'] = true;
|
||||
|
||||
$template = '<div class="formElement">' .
|
||||
'<label for="captcha">Captcha</label>' .
|
||||
'<input type="text" name="captcha">' .
|
||||
$error .
|
||||
'<img class="captcha" src="' . $builder->inline() . '" />' .
|
||||
'</div>';
|
||||
|
||||
return $template;
|
||||
}
|
||||
}
|
||||
}
|
@@ -9,10 +9,10 @@ class Content
|
||||
{
|
||||
private $storage;
|
||||
|
||||
public function __construct($baseurl = NULL)
|
||||
public function __construct($baseurl = NULL, $settings = NULL, $dispatcher = NULL)
|
||||
{
|
||||
$this->storage = new StorageWrapper('\Typemill\Models\Storage');
|
||||
$this->parsedown = new ParsedownExtension($baseurl);
|
||||
$this->parsedown = new ParsedownExtension($baseurl, $settings, $dispatcher);
|
||||
}
|
||||
|
||||
public function getDraftMarkdown($item)
|
||||
|
@@ -70,8 +70,8 @@ class Extension
|
||||
'description' => 'You can overwrite the theme-css with your own css here.'
|
||||
];
|
||||
|
||||
# add image preview file
|
||||
$themeSettings['preview'] = 'http://localhost/typemill/themes/' . $themeName . '/' . $themeName . '.png';
|
||||
# add image preview file
|
||||
$themeSettings['preview'] = '/themes/' . $themeName . '/' . $themeName . '.png';
|
||||
|
||||
return $themeSettings;
|
||||
}
|
||||
|
289
system/typemill/Models/Field.php
Normal file
289
system/typemill/Models/Field.php
Normal file
@@ -0,0 +1,289 @@
|
||||
<?php
|
||||
|
||||
namespace Typemill\Models;
|
||||
|
||||
class Field
|
||||
{
|
||||
private $type;
|
||||
|
||||
private $label;
|
||||
|
||||
private $name;
|
||||
|
||||
private $content;
|
||||
|
||||
/* holds all simple attributes for this field like "required" */
|
||||
private $attributes = array();
|
||||
|
||||
/* holds all attribute value pairs for this field like "id=''" */
|
||||
private $attributeValues = array();
|
||||
|
||||
/* holds all options for this field (e.g. select options) */
|
||||
private $options = array();
|
||||
|
||||
/* defines all field types, that are allowed */
|
||||
private $types = array(
|
||||
'checkbox',
|
||||
'checkboxlist',
|
||||
'color',
|
||||
'date',
|
||||
'datetime',
|
||||
'datetime-local',
|
||||
'email',
|
||||
'file',
|
||||
'hidden',
|
||||
'image',
|
||||
'month',
|
||||
'number',
|
||||
'password',
|
||||
'radio',
|
||||
'range',
|
||||
'tel',
|
||||
'text',
|
||||
'time',
|
||||
'url',
|
||||
'week',
|
||||
'textarea',
|
||||
'select',
|
||||
'paragraph'
|
||||
);
|
||||
|
||||
/* defines all boolean attributes, that are allowed for fields */
|
||||
private $attr = array(
|
||||
'autofocus',
|
||||
'checked',
|
||||
'disabled',
|
||||
'formnovalidate',
|
||||
'multiple',
|
||||
'readonly',
|
||||
'required'
|
||||
);
|
||||
|
||||
/* defines all attribute value paires, that are allowed for fields */
|
||||
private $attrValues = array(
|
||||
'id',
|
||||
'autocomplete',
|
||||
'placeholder',
|
||||
'maxlength',
|
||||
'size',
|
||||
'rows',
|
||||
'cols',
|
||||
'min',
|
||||
'max',
|
||||
'class',
|
||||
'pattern',
|
||||
'steps'
|
||||
);
|
||||
|
||||
/* defines additional data, that are allowed for fields */
|
||||
private $helpers = array(
|
||||
'help',
|
||||
'description',
|
||||
'fieldsize'
|
||||
);
|
||||
|
||||
public function __construct($fieldName, array $fieldConfigs)
|
||||
{
|
||||
$this->setName($fieldName);
|
||||
|
||||
$type = isset($fieldConfigs['type']) ? $fieldConfigs['type'] : false;
|
||||
$this->setType($type);
|
||||
|
||||
$label = isset($fieldConfigs['label']) ? $fieldConfigs['label'] : false;
|
||||
$this->setLabel($label);
|
||||
|
||||
$checkboxlabel = isset($fieldConfigs['checkboxlabel']) ? $fieldConfigs['checkboxlabel'] : false;
|
||||
$this->setCheckboxLabel($checkboxlabel);
|
||||
|
||||
$options = isset($fieldConfigs['options']) ? $fieldConfigs['options'] : array();
|
||||
$this->setOptions($options);
|
||||
|
||||
$this->setAttributes($fieldConfigs);
|
||||
|
||||
$this->setAttributeValues($fieldConfigs);
|
||||
|
||||
$this->setHelpers($fieldConfigs);
|
||||
}
|
||||
|
||||
private function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
private function setType($type)
|
||||
{
|
||||
if(in_array($type, $this->types))
|
||||
{
|
||||
$this->type = $type;
|
||||
}
|
||||
}
|
||||
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function setLabel($label)
|
||||
{
|
||||
$this->label = $label;
|
||||
}
|
||||
|
||||
public function getLabel()
|
||||
{
|
||||
return $this->label;
|
||||
}
|
||||
|
||||
public function setCheckboxLabel($label)
|
||||
{
|
||||
$this->checkboxLabel = $label;
|
||||
}
|
||||
|
||||
public function getCheckboxLabel()
|
||||
{
|
||||
return $this->checkboxLabel;
|
||||
}
|
||||
|
||||
public function setContent($content)
|
||||
{
|
||||
$this->content = $content;
|
||||
}
|
||||
|
||||
public function getContent()
|
||||
{
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
private function setOptions(array $options)
|
||||
{
|
||||
foreach($options as $key => $value)
|
||||
{
|
||||
$this->options[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
public function getOptions()
|
||||
{
|
||||
if(isset($this->options))
|
||||
{
|
||||
return $this->options;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private function setAttributes($fieldConfigs)
|
||||
{
|
||||
foreach($fieldConfigs as $key => $value)
|
||||
{
|
||||
if(is_string($key) && in_array($key, $this->attr))
|
||||
{
|
||||
$this->attributes[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* get all attributes of the field and return them as a string. For usage in templates */
|
||||
public function getAttributes()
|
||||
{
|
||||
$string = false;
|
||||
|
||||
foreach($this->attributes as $key => $attribute)
|
||||
{
|
||||
$string .= ' ' . $key;
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
/* set a single attribute. Used e.g. in controller to change the value */
|
||||
public function setAttribute($key, $value)
|
||||
{
|
||||
$this->attributes[$key] = $value;
|
||||
}
|
||||
|
||||
public function unsetAttribute($key)
|
||||
{
|
||||
unset($this->attributes[$key]);
|
||||
}
|
||||
|
||||
/* get a single attribute, if it is defined. For usage in templates like getAttribute('required') */
|
||||
public function getAttribute($key)
|
||||
{
|
||||
if(isset($this->attributes[$key]))
|
||||
{
|
||||
return $this->attributes[$key];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function setAttributeValues($fieldConfigs)
|
||||
{
|
||||
foreach($fieldConfigs as $key => $value)
|
||||
{
|
||||
if(is_string($key) && in_array($key, $this->attrValues))
|
||||
{
|
||||
$this->attributeValues[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* get all attributes as string. For usage in template */
|
||||
public function getAttributeValues()
|
||||
{
|
||||
$string = false;
|
||||
|
||||
foreach($this->attributeValues as $key => $attribute)
|
||||
{
|
||||
$string .= ' ' . $key . '="' . $attribute . '"';
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
public function setAttributeValue($key, $value)
|
||||
{
|
||||
/* pretty dirty, but you should not add a value for a simple checkbox */
|
||||
if($key == 'value' && $this->type == 'checkbox')
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
$this->attributeValues[$key] = $value;
|
||||
}
|
||||
|
||||
public function getAttributeValue($key)
|
||||
{
|
||||
if(isset($this->attributeValues[$key]))
|
||||
{
|
||||
return $this->attributeValues[$key];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public function setHelpers($fieldConfigs)
|
||||
{
|
||||
foreach($fieldConfigs as $key => $config)
|
||||
{
|
||||
if(is_string($key) && in_array($key, $this->helpers))
|
||||
{
|
||||
$this->$key = $config;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getHelper($helperName)
|
||||
{
|
||||
if(isset($this->$helperName))
|
||||
{
|
||||
return $this->$helperName;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
138
system/typemill/Models/Fields.php
Normal file
138
system/typemill/Models/Fields.php
Normal file
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
namespace Typemill\Models;
|
||||
|
||||
use Typemill\Models\Field;
|
||||
|
||||
class Fields
|
||||
{
|
||||
|
||||
protected $c;
|
||||
|
||||
public function __construct($c = NULL)
|
||||
{
|
||||
$this->c = $c;
|
||||
}
|
||||
|
||||
public function getFields($userSettings, $objectType, $objectName, $objectSettings, $formType = false)
|
||||
{
|
||||
# hold all fields in array
|
||||
$fields = array();
|
||||
|
||||
# formtype are backend forms or public forms, only relevant for plugins for now
|
||||
$formType = $formType ? $formType : 'forms';
|
||||
|
||||
# iterate through all fields of the objectSetting (theme or plugin)
|
||||
foreach($objectSettings[$formType]['fields'] as $fieldName => $fieldConfigurations)
|
||||
{
|
||||
if($fieldConfigurations['type'] == 'fieldset')
|
||||
{
|
||||
# if it is a fieldset, then create a subset for the containing field and read them with a recursive function
|
||||
$subSettings = $objectSettings;
|
||||
$subSettings['forms'] = $fieldConfigurations;
|
||||
|
||||
$fieldset = array();
|
||||
$fieldset['type'] = 'fieldset';
|
||||
$fieldset['legend'] = $fieldConfigurations['legend'];
|
||||
$fieldset['fields'] = $this->getFields($userSettings, $objectType, $objectName, $subSettings, $formType);
|
||||
$fields[] = $fieldset;
|
||||
}
|
||||
else
|
||||
{
|
||||
# For label, helptext and description you can use the value of another field. This is useful e.g. to localize the label of public forms via plugin settings.
|
||||
if(isset($fieldConfigurations['label']) && isset($userSettings[$objectType][$objectName][$fieldConfigurations['label']]))
|
||||
{
|
||||
$fieldConfigurations['label'] = $userSettings[$objectType][$objectName][$fieldConfigurations['label']];
|
||||
}
|
||||
if(isset($fieldConfigurations['help']) && isset($userSettings[$objectType][$objectName][$fieldConfigurations['help']]))
|
||||
{
|
||||
$fieldConfigurations['help'] = $userSettings[$objectType][$objectName][$fieldConfigurations['help']];
|
||||
}
|
||||
if(isset($fieldConfigurations['description']) && isset($userSettings[$objectType][$objectName][$fieldConfigurations['description']]))
|
||||
{
|
||||
$fieldConfigurations['description'] = $userSettings[$objectType][$objectName][$fieldConfigurations['description']];
|
||||
}
|
||||
|
||||
# check if the field is a select field with dataset = userroles
|
||||
if(isset($this->c) && isset($fieldConfigurations['type']) && ($fieldConfigurations['type'] == 'select' ) && isset($fieldConfigurations['dataset']) && ($fieldConfigurations['dataset'] == 'userroles' ) )
|
||||
{
|
||||
$userroles = [null => null];
|
||||
foreach($this->c->acl->getRoles() as $userrole)
|
||||
{
|
||||
$userroles[$userrole] = $userrole;
|
||||
}
|
||||
$fieldConfigurations['options'] = $userroles;
|
||||
}
|
||||
|
||||
# for each field generate a new field object with the field name and the field configurations
|
||||
$field = new Field($fieldName, $fieldConfigurations);
|
||||
|
||||
# handle the value for the field
|
||||
$userValue = false;
|
||||
|
||||
# first, add the default value from the original plugin or theme settings
|
||||
if(isset($objectSettings['settings'][$fieldName]))
|
||||
{
|
||||
$userValue = $objectSettings['settings'][$fieldName];
|
||||
}
|
||||
|
||||
# now overwrite the default values with the user values stored in the user settings
|
||||
if(isset($userSettings[$objectType][$objectName][$fieldName]))
|
||||
{
|
||||
$userValue = $userSettings[$objectType][$objectName][$fieldName];
|
||||
}
|
||||
|
||||
# now overwrite user-values, if there are old-input values from the actual form (e.g. after input error)
|
||||
if(isset($_SESSION['old'][$objectName][$fieldName]))
|
||||
{
|
||||
$userValue = $_SESSION['old'][$objectName][$fieldName];
|
||||
}
|
||||
|
||||
# Now prepopulate the field object with the value */
|
||||
if($field->getType() == "textarea")
|
||||
{
|
||||
if($fieldName == "publicformdefinitions" && $userValue == '')
|
||||
{
|
||||
$userValue = $objectSettings['settings'][$fieldName];
|
||||
}
|
||||
if($userValue)
|
||||
{
|
||||
$field->setContent($userValue);
|
||||
}
|
||||
}
|
||||
elseif($field->getType() == 'paragraph')
|
||||
{
|
||||
if(isset($fieldConfigurations['value']))
|
||||
{
|
||||
$field->setContent($fieldConfigurations['value']);
|
||||
}
|
||||
if($userValue)
|
||||
{
|
||||
$field->setContent($userValue);
|
||||
}
|
||||
}
|
||||
elseif($field->getType() == "checkbox")
|
||||
{
|
||||
# checkboxes need a special treatment, because field does not exist in settings if unchecked by user
|
||||
if(isset($userSettings[$objectType][$objectName][$fieldName]))
|
||||
{
|
||||
$field->setAttribute('checked', 'true');
|
||||
}
|
||||
else
|
||||
{
|
||||
$field->unsetAttribute('checked');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$field->setAttributeValue('value', $userValue);
|
||||
}
|
||||
|
||||
# add the field to the field-List
|
||||
$fields[] = $field;
|
||||
|
||||
}
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
}
|
@@ -106,7 +106,7 @@ class Settings
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public function getObjectSettings($objectType, $objectName)
|
||||
{
|
||||
$objectSettings = $this->storage->getYaml($objectType, $objectName, $objectName . '.yaml');
|
||||
|
@@ -4,10 +4,10 @@ namespace Typemill;
|
||||
|
||||
use \Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use DI\Container;
|
||||
# use Typemill\Models\Fields;
|
||||
use Typemill\Models\StorageWrapper;
|
||||
use Typemill\Models\Extension;
|
||||
use Typemill\Models\Validation;
|
||||
use Typemill\Models\Fields;
|
||||
use Typemill\Extensions\ParsedownExtension;
|
||||
|
||||
abstract class Plugin implements EventSubscriberInterface
|
||||
@@ -22,11 +22,7 @@ abstract class Plugin implements EventSubscriberInterface
|
||||
|
||||
public function __construct(Container $container)
|
||||
{
|
||||
/*
|
||||
echo '<pre>';
|
||||
echo '<h1>FIRST</h1>';
|
||||
print_r($container);
|
||||
*/
|
||||
|
||||
$this->container = $container;
|
||||
$this->urlinfo = $this->container->get('urlinfo');
|
||||
$this->route = $this->urlinfo['route'];
|
||||
@@ -281,23 +277,27 @@ abstract class Plugin implements EventSubscriberInterface
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function generateForm($pluginName, $routename)
|
||||
protected function generateForm($routename, $pluginname = NULL)
|
||||
{
|
||||
$fieldsModel = new Fields();
|
||||
|
||||
$settings = $this->getSettings();
|
||||
$form = false;
|
||||
|
||||
$pluginDefinitions = \Typemill\Settings::getObjectSettings('plugins', $pluginName);
|
||||
if(isset($settings['plugins'][$pluginName]['publicformdefinitions']) && $settings['plugins'][$pluginName]['publicformdefinitions'] != '')
|
||||
$fieldsModel = new Fields();
|
||||
$extensionModel = new Extension();
|
||||
|
||||
$pluginSettings = $this->getPluginSettings();
|
||||
$pluginName = $this->getPluginName($pluginname);
|
||||
$pluginDefinitions = $extensionModel->getPluginDefinition($pluginName);
|
||||
|
||||
# add field-definitions entered into author interface
|
||||
if(isset($pluginSettings['publicformdefinitions']) && $pluginSettings['publicformdefinitions'] != '')
|
||||
{
|
||||
$arrayFromYaml = \Symfony\Component\Yaml\Yaml::parse($settings['plugins'][$pluginName]['publicformdefinitions']);
|
||||
$arrayFromYaml = \Symfony\Component\Yaml\Yaml::parse($pluginSettings['publicformdefinitions']);
|
||||
$pluginDefinitions['public']['fields'] = $arrayFromYaml;
|
||||
}
|
||||
|
||||
$buttonlabel = isset($settings['plugins'][$pluginName]['button_label']) ? $settings['plugins'][$pluginName]['button_label'] : false;
|
||||
$captchaoptions = isset($settings['plugins'][$pluginName]['captchaoptions']) ? $settings['plugins'][$pluginName]['captchaoptions'] : false;
|
||||
$recaptcha = isset($settings['plugins'][$pluginName]['recaptcha']) ? $settings['plugins'][$pluginName]['recaptcha_webkey'] : false;
|
||||
$buttonlabel = isset($pluginSettings['button_label']) ? $pluginSettings['button_label'] : false;
|
||||
$captchaoptions = isset($pluginSettings['captchaoptions']) ? $pluginSettings['captchaoptions'] : false;
|
||||
$recaptcha = isset($pluginSettings['recaptcha']) ? $pluginSettings['recaptcha_webkey'] : false;
|
||||
|
||||
if($captchaoptions == 'disabled')
|
||||
{
|
||||
@@ -308,7 +308,9 @@ abstract class Plugin implements EventSubscriberInterface
|
||||
$fieldsModel = new Fields();
|
||||
|
||||
if(isset($pluginDefinitions['public']['fields']))
|
||||
{
|
||||
{
|
||||
$settings = $this->container->get('settings');
|
||||
|
||||
# get all the fields and prefill them with the dafault-data, the user-data or old input data
|
||||
$fields = $fieldsModel->getFields($settings, 'plugins', $pluginName, $pluginDefinitions, 'public');
|
||||
|
||||
@@ -326,7 +328,7 @@ abstract class Plugin implements EventSubscriberInterface
|
||||
'recaptcha_webkey' => $recaptcha,
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
|
@@ -2293,7 +2293,7 @@ bloxeditor.component('shortcode-component', {
|
||||
{
|
||||
params:
|
||||
{
|
||||
'url': data.urlinfo.route,
|
||||
'url': data.urlinfo.route,
|
||||
}
|
||||
})
|
||||
.then(function (response)
|
||||
@@ -2359,7 +2359,7 @@ bloxeditor.component('shortcode-component', {
|
||||
|
||||
this.compmarkdown = '[:' + shortcodename + attributes + ' :]';
|
||||
|
||||
this.$emit('updatedMarkdown', this.compmarkdown);
|
||||
this.$emit('updateMarkdownEvent', this.compmarkdown);
|
||||
},
|
||||
selectsearch: function(item,attribute)
|
||||
{
|
||||
|
103
system/typemill/author/partials/fields.twig
Normal file
103
system/typemill/author/partials/fields.twig
Normal file
@@ -0,0 +1,103 @@
|
||||
<div class="{{ class ? class : 'cardField' }}{{ errors[itemName][field.name] ? ' error' : '' }}{{field.fieldsize ? ' ' ~ field.fieldsize : ''}}">
|
||||
|
||||
<label for="{{ itemName }}[{{ field.name }}]">{{ translate( field.getLabel() ) }}
|
||||
{% if field.getAttribute('required') %}<strong><abbr title="{{ translate('required') }}">*</abbr></strong>{% endif %}
|
||||
{% if field.help %}<div class="help">?<span class="tooltip">{{ translate(field.help|slice(0,100)) }}</span></div>{% endif %}
|
||||
</label>
|
||||
|
||||
{% if field.type == 'image' %}
|
||||
<div class="img-upload flex flex-wrap item-start">
|
||||
<div class="w-50">
|
||||
<div class="w6 h6 bg-black-40 dtc v-mid bg-chess">
|
||||
<img src="{{ base_url }}/{{ settings[object][itemName][field.name] }}" class="function-img-src mw6 max-h6 dt center">
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-50 ph3 lh-copy f6 relative">
|
||||
<div class="relative dib w-100">
|
||||
<input class="function-img-file absolute o-0 w-100 top-0 z-1 pointer" type="file" id="{{ itemName }}[{{ field.name }}]" name="{{ itemName }}[{{ field.name }}]" accept="image/*" />
|
||||
<div class="relative w-100 bn br1 bg-tm-green white pa3 ma0 tc"><svg class="icon icon-upload baseline"><use xlink:href="#icon-upload"></use></svg> {{ translate('Upload an image') }}</div>
|
||||
</div>
|
||||
<div class="dib w-100 mt3">
|
||||
<label>{{ translate('Image URL') }}</label>
|
||||
<div class="flex">
|
||||
<button class="function-delete-img w-10 bg-tm-gray bn hover-bg-tm-red hover-white">x</button>
|
||||
<input class="function-img-url w-90 mbfix" type="text" name="{{ itemName }}[{{ field.name }}]" value="{{ settings[object][itemName][field.name] }}" readonly>
|
||||
</div>
|
||||
</div>
|
||||
{% if errors[itemName][field.name] %}
|
||||
<div class="error f6">{{ errors[itemName][field.name] | first }}</div>
|
||||
{% endif %}
|
||||
|
||||
{% if field.description %}<div class="description pv3">{{ translate(field.description) }}</div>{% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% else %}
|
||||
|
||||
{% if field.type == 'textarea' %}
|
||||
|
||||
<textarea id="{{ itemName }}[{{ field.name }}]" name="{{ itemName }}[{{ field.name }}]"{{field.getAttributeValues() }}{{ field.getAttributes() }}>{{ field.getContent() }}</textarea>
|
||||
|
||||
{% elseif (field.type == 'paragraph') and (field.getContent() != '') %}
|
||||
|
||||
{{ markdown(field.getContent()) }}
|
||||
|
||||
{% elseif field.type == 'checkbox' %}
|
||||
|
||||
<label class="control-group">{{ markdown( field.getCheckboxLabel() ) }}
|
||||
<input type="checkbox" id="{{ itemName}}[{{ field.name }}]" name="{{ itemName}}[{{ field.name }}]"{{ field.getAttributeValues() }}{{ field.getAttributes() }}>
|
||||
<span class="checkmark"></span>
|
||||
</label>
|
||||
|
||||
{% elseif field.type == 'checkboxlist' %}
|
||||
|
||||
{% set options = field.getOptions() %}
|
||||
|
||||
{% for value,label in options %}
|
||||
|
||||
<label class="control-group">{{ markdown( label ) }}
|
||||
<input type="checkbox" id="{{ itemName }}[{{ field.name }}][{{value}}]" name="{{ itemName }}[{{ field.name }}][{{value}}]" {{ settings[object][itemName][field.name][value] ? ' checked' : '' }}>
|
||||
<span class="checkmark"></span>
|
||||
</label>
|
||||
|
||||
{% endfor %}
|
||||
|
||||
{% elseif field.type == 'select' %}
|
||||
|
||||
{% set options = field.getOptions() %}
|
||||
|
||||
<select id="{{ itemName }}[{{ field.name }}]" name="{{ itemName }}[{{ field.name }}]"{{ field.getAttributeValues() }}{{ field.getAttributes() }}>
|
||||
{% for value,label in options %}
|
||||
<option value="{{ value }}" {{ (value == field.getAttributeValue('value')) ? ' selected' : '' }}>{{ translate(label) }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
||||
{% elseif field.type == 'radio' %}
|
||||
|
||||
{% set options = field.getOptions() %}
|
||||
|
||||
{% for value,label in options %}
|
||||
|
||||
<label class="control-group">{{ markdown(label) }}
|
||||
<input type="radio" id="{{ itemName }}[{{ field.name }}]" name="{{ itemName }}[{{ field.name }}]" value="{{ value }}" {{ (value == settings[object][itemName][field.name]) ? ' checked' : '' }}>
|
||||
<span class="radiomark"></span>
|
||||
</label>
|
||||
|
||||
{% endfor %}
|
||||
|
||||
{% else %}
|
||||
|
||||
<input id="{{itemName}}[{{ field.name }}]" name="{{itemName}}[{{ field.name }}]" type="{{ field.type }}"{{ field.getAttributeValues() }}{{ field.getAttributes() }}>
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% if field.description %}<div class="description">{{ translate(field.description) }}</div>{% endif %}
|
||||
|
||||
{% if errors[itemName][field.name] %}
|
||||
<span class="error">{{ errors[itemName][field.name] | first }}</span>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
</div>
|
56
system/typemill/author/partials/form.twig
Normal file
56
system/typemill/author/partials/form.twig
Normal file
@@ -0,0 +1,56 @@
|
||||
{% if recaptcha_webkey %}
|
||||
|
||||
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
|
||||
|
||||
{% endif %}
|
||||
<form method="POST" action="{{ url_for(routename) }}" enctype="multipart/form-data">
|
||||
|
||||
<fieldset class="card{{ errors[itemName] ? ' errors' : '' }}">
|
||||
|
||||
{% for field in fields %}
|
||||
|
||||
{% if field.type == 'fieldset' %}
|
||||
|
||||
<fieldset class="subfield">
|
||||
<legend>{{ field.legend }}</legend>
|
||||
{% for field in field.fields %}
|
||||
|
||||
{% include '/partials/fields.twig' with {'itemName' : itemName, 'object' : object } %}
|
||||
|
||||
{% endfor %}
|
||||
</fieldset>
|
||||
|
||||
{% else %}
|
||||
|
||||
{% include '/partials/fields.twig' with {'itemName' : itemName, 'object' : object } %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
<div class="personal-mail">
|
||||
<label>Personal Mail</label>
|
||||
<input type="text" name="personal-honey-mail">
|
||||
</div>
|
||||
|
||||
{% if captchaoptions == 'disabled' %}
|
||||
|
||||
{% elseif captchaoptions == 'aftererror' %}
|
||||
|
||||
{{ captcha(old) }}
|
||||
|
||||
{% else %}
|
||||
|
||||
{{ captcha(true) }}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% if recaptcha_webkey %}
|
||||
<p><div class="g-recaptcha" data-sitekey="{{ recaptcha_webkey }}"></div></p>
|
||||
{% endif %}
|
||||
|
||||
<input type="submit" value="{{ buttonlabel ? buttonlabel : 'send' }}" />
|
||||
|
||||
<style>.personal-mail{display:none}</style>
|
||||
</fieldset>
|
||||
</form>
|
@@ -32,6 +32,7 @@ use Typemill\Extensions\TwigUrlExtension;
|
||||
use Typemill\Extensions\TwigUserExtension;
|
||||
use Typemill\Extensions\TwigLanguageExtension;
|
||||
use Typemill\Extensions\TwigMarkdownExtension;
|
||||
use Typemill\Extensions\TwigCaptchaExtension;
|
||||
|
||||
$timer = [];
|
||||
$timer['start'] = microtime(true);
|
||||
@@ -301,6 +302,7 @@ $container->set('view', function() use ($settings, $csrf, $urlinfo, $translation
|
||||
$twig->addExtension(new TwigUrlExtension($urlinfo));
|
||||
$twig->addExtension(new TwigLanguageExtension( $translations ));
|
||||
$twig->addExtension(new TwigMarkdownExtension());
|
||||
$twig->addExtension(new TwigCaptchaExtension());
|
||||
|
||||
# start csrf only if session is active
|
||||
/*
|
||||
|
Reference in New Issue
Block a user