From 022abe132b7411e73c88b21387232fac5fd9ceaa Mon Sep 17 00:00:00 2001
From: trendschau
Date: Thu, 24 Aug 2023 23:14:29 +0200
Subject: [PATCH] add backend form builder, add captcha and fix shortcodes
---
composer.json | 2 +-
composer.lock | 15 +-
content/00-welcome/05-todos.md | 16 +-
content/00-welcome/05-todos.txt | 2 +-
content/00-welcome/05-todos.yaml | 2 +-
system/Extensions/ParsedownExtension.php | 1 +
.../ControllerApiAuthorArticle.php | 12 +-
.../Controllers/ControllerApiAuthorBlock.php | 8 +-
.../Controllers/ControllerWebAuthor.php | 10 +-
.../Controllers/ControllerWebFrontend.php | 2 +-
.../Extensions/ParsedownExtension.php | 4 +-
.../Extensions/TwigCaptchaExtension.php | 46 +++
system/typemill/Models/Content.php | 4 +-
system/typemill/Models/Extension.php | 4 +-
system/typemill/Models/Field.php | 289 ++++++++++++++++++
system/typemill/Models/Fields.php | 138 +++++++++
system/typemill/Models/Settings.php | 2 +-
system/typemill/Plugin.php | 38 +--
.../typemill/author/js/vue-blox-components.js | 4 +-
system/typemill/author/partials/fields.twig | 103 +++++++
system/typemill/author/partials/form.twig | 56 ++++
system/typemill/system.php | 2 +
22 files changed, 698 insertions(+), 62 deletions(-)
create mode 100644 system/typemill/Extensions/TwigCaptchaExtension.php
create mode 100644 system/typemill/Models/Field.php
create mode 100644 system/typemill/Models/Fields.php
create mode 100644 system/typemill/author/partials/fields.twig
create mode 100644 system/typemill/author/partials/form.twig
diff --git a/composer.json b/composer.json
index a4d74d5..4978860 100644
--- a/composer.json
+++ b/composer.json
@@ -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": {
diff --git a/composer.lock b/composer.lock
index 0918dfa..5adb12f 100644
--- a/composer.lock
+++ b/composer.lock
@@ -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",
diff --git a/content/00-welcome/05-todos.md b/content/00-welcome/05-todos.md
index e3abce2..cfb60a8 100644
--- a/content/00-welcome/05-todos.md
+++ b/content/00-welcome/05-todos.md
@@ -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:
diff --git a/content/00-welcome/05-todos.txt b/content/00-welcome/05-todos.txt
index 8ae8731..7b4b3ad 100644
--- a/content/00-welcome/05-todos.txt
+++ b/content/00-welcome/05-todos.txt
@@ -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 "]
\ No newline at end of file
+["# 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 "]
\ No newline at end of file
diff --git a/content/00-welcome/05-todos.yaml b/content/00-welcome/05-todos.yaml
index 1a374d9..77a04a6 100644
--- a/content/00-welcome/05-todos.yaml
+++ b/content/00-welcome/05-todos.yaml
@@ -6,7 +6,7 @@ meta:
heroimagealt: null
owner: Sebastian
author: null
- allowedrole: contributor
+ allowedrole: ''
alloweduser: null
manualdate: null
modified: '2023-06-19'
diff --git a/system/Extensions/ParsedownExtension.php b/system/Extensions/ParsedownExtension.php
index 11c38b0..dafb157 100644
--- a/system/Extensions/ParsedownExtension.php
+++ b/system/Extensions/ParsedownExtension.php
@@ -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);
diff --git a/system/typemill/Controllers/ControllerApiAuthorArticle.php b/system/typemill/Controllers/ControllerApiAuthorArticle.php
index 64efa77..782a7f8 100644
--- a/system/typemill/Controllers/ControllerApiAuthorArticle.php
+++ b/system/typemill/Controllers/ControllerApiAuthorArticle.php
@@ -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')
diff --git a/system/typemill/Controllers/ControllerApiAuthorBlock.php b/system/typemill/Controllers/ControllerApiAuthorBlock.php
index 4e187b0..d81b497 100644
--- a/system/typemill/Controllers/ControllerApiAuthorBlock.php
+++ b/system/typemill/Controllers/ControllerApiAuthorBlock.php
@@ -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);
diff --git a/system/typemill/Controllers/ControllerWebAuthor.php b/system/typemill/Controllers/ControllerWebAuthor.php
index 0d53ffc..0ba16ca 100644
--- a/system/typemill/Controllers/ControllerWebAuthor.php
+++ b/system/typemill/Controllers/ControllerWebAuthor.php
@@ -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();
diff --git a/system/typemill/Controllers/ControllerWebFrontend.php b/system/typemill/Controllers/ControllerWebFrontend.php
index ebfef03..67c7add 100644
--- a/system/typemill/Controllers/ControllerWebFrontend.php
+++ b/system/typemill/Controllers/ControllerWebFrontend.php
@@ -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);
diff --git a/system/typemill/Extensions/ParsedownExtension.php b/system/typemill/Extensions/ParsedownExtension.php
index 7f557f3..2c6037d 100644
--- a/system/typemill/Extensions/ParsedownExtension.php
+++ b/system/typemill/Extensions/ParsedownExtension.php
@@ -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))
diff --git a/system/typemill/Extensions/TwigCaptchaExtension.php b/system/typemill/Extensions/TwigCaptchaExtension.php
new file mode 100644
index 0000000..a0a208f
--- /dev/null
+++ b/system/typemill/Extensions/TwigCaptchaExtension.php
@@ -0,0 +1,46 @@
+build();
+
+ $error = '';
+ if(isset($_SESSION['captcha']) && $_SESSION['captcha'] === 'error')
+ {
+ $error = 'The captcha was wrong.';
+ }
+
+ $_SESSION['phrase'] = $builder->getPhrase();
+
+ $_SESSION['captcha'] = true;
+
+ $template = '';
+
+ return $template;
+ }
+ }
+}
\ No newline at end of file
diff --git a/system/typemill/Models/Content.php b/system/typemill/Models/Content.php
index 8290268..a517c5b 100644
--- a/system/typemill/Models/Content.php
+++ b/system/typemill/Models/Content.php
@@ -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)
diff --git a/system/typemill/Models/Extension.php b/system/typemill/Models/Extension.php
index 77c40a2..c07fc04 100644
--- a/system/typemill/Models/Extension.php
+++ b/system/typemill/Models/Extension.php
@@ -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;
}
diff --git a/system/typemill/Models/Field.php b/system/typemill/Models/Field.php
new file mode 100644
index 0000000..2f06fa0
--- /dev/null
+++ b/system/typemill/Models/Field.php
@@ -0,0 +1,289 @@
+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;
+ }
+}
\ No newline at end of file
diff --git a/system/typemill/Models/Fields.php b/system/typemill/Models/Fields.php
new file mode 100644
index 0000000..1657b22
--- /dev/null
+++ b/system/typemill/Models/Fields.php
@@ -0,0 +1,138 @@
+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;
+ }
+}
\ No newline at end of file
diff --git a/system/typemill/Models/Settings.php b/system/typemill/Models/Settings.php
index 38ee952..5e353e9 100644
--- a/system/typemill/Models/Settings.php
+++ b/system/typemill/Models/Settings.php
@@ -106,7 +106,7 @@ class Settings
return false;
}
-
+
public function getObjectSettings($objectType, $objectName)
{
$objectSettings = $this->storage->getYaml($objectType, $objectName, $objectName . '.yaml');
diff --git a/system/typemill/Plugin.php b/system/typemill/Plugin.php
index 1e50191..125b846 100644
--- a/system/typemill/Plugin.php
+++ b/system/typemill/Plugin.php
@@ -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 '';
- echo 'FIRST
';
- 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;
}
diff --git a/system/typemill/author/js/vue-blox-components.js b/system/typemill/author/js/vue-blox-components.js
index 23d0a13..1365d2c 100644
--- a/system/typemill/author/js/vue-blox-components.js
+++ b/system/typemill/author/js/vue-blox-components.js
@@ -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)
{
diff --git a/system/typemill/author/partials/fields.twig b/system/typemill/author/partials/fields.twig
new file mode 100644
index 0000000..232ded1
--- /dev/null
+++ b/system/typemill/author/partials/fields.twig
@@ -0,0 +1,103 @@
+
+
+
+
+ {% if field.type == 'image' %}
+
+
+
+

+
+
+
+
+
+
{{ translate('Upload an image') }}
+
+
+
+
+
+
+
+
+ {% if errors[itemName][field.name] %}
+
{{ errors[itemName][field.name] | first }}
+ {% endif %}
+
+ {% if field.description %}
{{ translate(field.description) }}
{% endif %}
+
+
+
+
+ {% else %}
+
+ {% if field.type == 'textarea' %}
+
+
+
+ {% elseif (field.type == 'paragraph') and (field.getContent() != '') %}
+
+ {{ markdown(field.getContent()) }}
+
+ {% elseif field.type == 'checkbox' %}
+
+
+
+ {% elseif field.type == 'checkboxlist' %}
+
+ {% set options = field.getOptions() %}
+
+ {% for value,label in options %}
+
+
+
+ {% endfor %}
+
+ {% elseif field.type == 'select' %}
+
+ {% set options = field.getOptions() %}
+
+
+
+ {% elseif field.type == 'radio' %}
+
+ {% set options = field.getOptions() %}
+
+ {% for value,label in options %}
+
+
+
+ {% endfor %}
+
+ {% else %}
+
+
+
+ {% endif %}
+
+ {% if field.description %}
{{ translate(field.description) }}
{% endif %}
+
+ {% if errors[itemName][field.name] %}
+
{{ errors[itemName][field.name] | first }}
+ {% endif %}
+
+ {% endif %}
+
+
\ No newline at end of file
diff --git a/system/typemill/author/partials/form.twig b/system/typemill/author/partials/form.twig
new file mode 100644
index 0000000..d0bfca1
--- /dev/null
+++ b/system/typemill/author/partials/form.twig
@@ -0,0 +1,56 @@
+{% if recaptcha_webkey %}
+
+
+
+{% endif %}
+
+ {% endif %}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/system/typemill/system.php b/system/typemill/system.php
index 56193f8..1afa309 100644
--- a/system/typemill/system.php
+++ b/system/typemill/system.php
@@ -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
/*