mirror of
https://github.com/typemill/typemill.git
synced 2025-08-06 14:16:46 +02:00
Version 1.2.9: Some preparations
This commit is contained in:
2
cache/lastCache.txt
vendored
2
cache/lastCache.txt
vendored
@@ -1 +1 @@
|
||||
1543940450
|
||||
1544113772
|
1
content/00-Welcome/03-test.txt
Normal file
1
content/00-Welcome/03-test.txt
Normal file
@@ -0,0 +1 @@
|
||||
["# Add Title","Add Content"]
|
16
content/01-stellenanzeigen/00-job-einstellen.md
Normal file
16
content/01-stellenanzeigen/00-job-einstellen.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# Stellenangebot veröffentlichen
|
||||
|
||||
CMSstash erreicht pro Monat mehrere tausend CMS-Experten in ganz Deutschland. Detaillierte Angaben finden sie in den [Mediadaten](/mediadaten). Unternehmen können diese Reichweite nutzen und ihre Stellenanzeigen mit CMS-Bezug auf CMSstash veröffentlichen. Wir bieten folgende Konditionen an:
|
||||
|
||||
| Kondition | Anzeige Standard | Anzeige Pro |
|
||||
|-----------|-----------|----------|
|
||||
| Laufzeit | 8 Wochen | 8 Wochen |
|
||||
| Exklusiver Teaser auf allen Seiten | Nein | 4 Wochen |
|
||||
| Tweets | 1 Tweet | 3 Tweets |
|
||||
| __Preis__ | **59,- Euro** | **159,- Euro** |
|
||||
| _(keine Ausweisung der Mwst. nach § 19 UStG)_ | | |
|
||||
|
||||
## Stellenanzeige aufgeben
|
||||
|
||||
Bei Interesse schreiben Sie uns gerne über [jobs@cmsstash.de](mailto:jobs@cmsstash.de) an oder nutzen Sie das Kontaktformular. Aufgrund der inhaltlichen Ausrichtung können wir nur Stellenangebote mit einem klaren Bezug zum Thema Content Management Systeme veröffentlichen.
|
||||
|
4
content/01-stellenanzeigen/index.md
Normal file
4
content/01-stellenanzeigen/index.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# Add Title
|
||||
|
||||
Add Content
|
||||
|
69
plugins/contactform/contactform.php
Normal file
69
plugins/contactform/contactform.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace Plugins\contactform;
|
||||
|
||||
use \Typemill\Plugin;
|
||||
|
||||
class ContactForm extends Plugin
|
||||
{
|
||||
protected $item;
|
||||
protected $originalHtml;
|
||||
protected $pluginSettings;
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
'onSessionSegmentsLoaded' => 'onSessionSegmentsLoaded',
|
||||
'onOriginalLoaded' => 'onOriginalLoaded',
|
||||
'onHtmlLoaded' => 'onHtmlLoaded',
|
||||
);
|
||||
}
|
||||
|
||||
public function onSessionSegmentsLoaded($segments)
|
||||
{
|
||||
$this->pluginSettings = $this->getPluginSettings('contactform');
|
||||
|
||||
if($this->getPath() == $this->pluginSettings['page'])
|
||||
{
|
||||
$data = $segments->getData();
|
||||
$data[] = $this->pluginSettings['page'];
|
||||
$segments->setData($data);
|
||||
}
|
||||
}
|
||||
|
||||
public function onOriginalLoaded($original)
|
||||
{
|
||||
if(substr($this->getPath(), 0, strlen($this->pluginSettings['area'])) === $this->pluginSettings['area'])
|
||||
{
|
||||
# get original html without manipulations
|
||||
$this->originalHtml = $original->getHTML();
|
||||
}
|
||||
}
|
||||
|
||||
public function onHtmlLoaded($html)
|
||||
{
|
||||
if(substr($this->getPath(), 0, strlen($this->pluginSettings['area'])) === $this->pluginSettings['area'])
|
||||
{
|
||||
$content = $this->originalHtml;
|
||||
|
||||
if($this->getPath() == $this->pluginSettings['page'])
|
||||
{
|
||||
# add css
|
||||
# $this->addCSS('/textadds/css/textadds.css');
|
||||
|
||||
# get Twig Instance and add the cookieconsent template-folder to the path
|
||||
$twig = $this->getTwig();
|
||||
$loader = $twig->getLoader();
|
||||
$loader->addPath(__DIR__ . '/templates');
|
||||
|
||||
# fetch the template and render it with twig
|
||||
$contactform = $twig->fetch('/contactform.twig', $this->pluginSettings);
|
||||
|
||||
$content = $this->originalHtml . $contactform;
|
||||
}
|
||||
|
||||
$html->setData($content);
|
||||
$html->stopPropagation();
|
||||
}
|
||||
}
|
||||
}
|
96
plugins/contactform/contactform.yaml
Normal file
96
plugins/contactform/contactform.yaml
Normal file
@@ -0,0 +1,96 @@
|
||||
name: ContactForm
|
||||
version: 1.0.0
|
||||
description: Integrate a google like text-add into each content page (file).
|
||||
author: Sebastian Schürmanns
|
||||
homepage: https://typemill.net
|
||||
licence: MIT
|
||||
|
||||
settings:
|
||||
page: ''
|
||||
name: 'Name: '
|
||||
email: 'E-Mail: '
|
||||
subject: 'Subject: '
|
||||
message: 'Message: '
|
||||
button: 'Send Message'
|
||||
|
||||
forms:
|
||||
fields:
|
||||
|
||||
page:
|
||||
type: text
|
||||
label: Path to the page where to show the form
|
||||
placeholder: 'path/to/page'
|
||||
required: true
|
||||
|
||||
area:
|
||||
type: text
|
||||
label: Path to the area with original content
|
||||
placeholder: 'path/to/rootpage'
|
||||
required: true
|
||||
|
||||
name:
|
||||
type: text
|
||||
label: Label for Name Input Field
|
||||
placeholder: 'Name: '
|
||||
required: true
|
||||
|
||||
email:
|
||||
type: text
|
||||
label: Label for E-Mail-Field
|
||||
placeholder: 'E-Mail: '
|
||||
required: true
|
||||
|
||||
subject:
|
||||
type: text
|
||||
label: Label for Subject-Field
|
||||
placeholder: 'Subject: '
|
||||
required: true
|
||||
|
||||
message:
|
||||
type: text
|
||||
label: Label for Message
|
||||
placeholder: 'Message: '
|
||||
required: true
|
||||
|
||||
button:
|
||||
type: text
|
||||
label: Label for Button
|
||||
placeholder: 'Send Message'
|
||||
required: true
|
||||
|
||||
hint:
|
||||
type: textarea
|
||||
label: Text below button (use markdown)
|
||||
placeholder: 'Add your legal text or other hints here'
|
||||
|
||||
frontend:
|
||||
fields:
|
||||
|
||||
name:
|
||||
type: text
|
||||
label: Label for Name Input Field
|
||||
placeholder: 'Name: '
|
||||
required: true
|
||||
|
||||
email:
|
||||
type: text
|
||||
label: Label for E-Mail-Field
|
||||
placeholder: 'E-Mail: '
|
||||
required: true
|
||||
|
||||
subject:
|
||||
type: text
|
||||
label: Label for Subject-Field
|
||||
placeholder: 'Subject: '
|
||||
required: true
|
||||
|
||||
message:
|
||||
type: text
|
||||
label: Label for Message
|
||||
placeholder: 'Message: '
|
||||
required: true
|
||||
|
||||
hint:
|
||||
type: textarea
|
||||
label: Text below button (use markdown)
|
||||
placeholder: 'Add your legal text or other hints here'
|
26
plugins/contactform/css/textadds.css
Normal file
26
plugins/contactform/css/textadds.css
Normal file
@@ -0,0 +1,26 @@
|
||||
.contentadd{
|
||||
display: block;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
border-top: 1px solid #ccc;
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
.contentadd span{
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 20px;
|
||||
text-transform: uppercase;
|
||||
color: #ccc;
|
||||
font-size: 0.6em;
|
||||
}
|
||||
.contentadd h3{
|
||||
margin-top: 20px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.contentadd small{
|
||||
margin: 0px;
|
||||
}
|
||||
.contentadd p{
|
||||
margin-top: 0px;
|
||||
margin-bottom: 20px;
|
||||
}
|
40
plugins/contactform/templates/contactform.twig
Normal file
40
plugins/contactform/templates/contactform.twig
Normal file
@@ -0,0 +1,40 @@
|
||||
<form method="POST" action="{{ path_for('settings.save') }}">
|
||||
|
||||
<fieldset>
|
||||
|
||||
<div class="medium{{ errors.contact.name ? ' error' : '' }}">
|
||||
<label for="contact[name]">{{ name }} *</label>
|
||||
<input type="text" name="contact[name]" id="name" pattern=".{2,20}" required title="Use 2 to 20 characters." value="{{ old.contact.title ? old.contact.name : contact.name }}" />
|
||||
{% if errors.contact.title %}
|
||||
<span class="error">{{ errors.contact.name | first }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="medium{{ errors.contact.email ? ' error' : '' }}">
|
||||
<label for="contact[email]">{{ email }} *</label>
|
||||
<input type="text" name="contact[email]" id="email" pattern=".{2,20}" required title="Use 2 to 20 characters." value="{{ old.contact.email ? old.contact.email : contact.email }}" />
|
||||
{% if errors.contact.title %}
|
||||
<span class="error">{{ errors.contact.email | first }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="medium{{ errors.contact.subject ? ' error' : '' }}">
|
||||
<label for="contact[email]">{{ subject }} *</label>
|
||||
<input type="text" name="contact[subject]" id="subject" pattern=".{2,20}" required title="Use 2 to 20 characters." value="{{ old.contact.subject ? old.contact.subject : contact.subject }}" />
|
||||
{% if errors.contact.title %}
|
||||
<span class="error">{{ errors.contact.email | first }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="medium{{ errors.contact.message ? ' error' : '' }}">
|
||||
<label for="contact[email]">{{ message }} *</label>
|
||||
<input type="textfield" name="contact[message]" id="message" pattern=".{2,20}" required title="Use 2 to 20 characters." value="{{ old.contact.message ? old.contact.message : contact.message }}" />
|
||||
{% if errors.contact.title %}
|
||||
<span class="error">{{ errors.contact.message | first }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<small>{{ hint }}</small>
|
||||
|
||||
</fieldset>
|
||||
|
||||
<input type="submit" value="{{ button }}" />
|
||||
{{ csrf_field() | raw }}
|
||||
|
||||
</form>
|
@@ -13,6 +13,7 @@ use Typemill\Models\Markdown;
|
||||
use Typemill\Events\OnPagetreeLoaded;
|
||||
use Typemill\Events\OnBreadcrumbLoaded;
|
||||
use Typemill\Events\OnItemLoaded;
|
||||
use Typemill\Events\OnOriginalLoaded;
|
||||
use Typemill\Events\OnMarkdownLoaded;
|
||||
use Typemill\Events\OnContentArrayLoaded;
|
||||
use Typemill\Events\OnHtmlLoaded;
|
||||
@@ -118,6 +119,9 @@ class PageController extends Controller
|
||||
$contentMD = isset($filePath) ? file_get_contents($filePath) : false;
|
||||
}
|
||||
|
||||
# dispatch the original content without plugin-manipulations for case anyone wants to use it
|
||||
$this->c->dispatcher->dispatch('onOriginalLoaded', new OnOriginalLoaded($contentMD));
|
||||
|
||||
$contentMD = $this->c->dispatcher->dispatch('onMarkdownLoaded', new OnMarkdownLoaded($contentMD))->getData();
|
||||
|
||||
/* initialize parsedown */
|
||||
@@ -136,7 +140,7 @@ class PageController extends Controller
|
||||
/* parse markdown-content-array to content-string */
|
||||
$contentHTML = $parsedown->markup($contentArray);
|
||||
$contentHTML = $this->c->dispatcher->dispatch('onHtmlLoaded', new OnHtmlLoaded($contentHTML))->getData();
|
||||
|
||||
|
||||
/* extract the h1 headline*/
|
||||
$contentParts = explode("</h1>", $contentHTML);
|
||||
$title = isset($contentParts[0]) ? strip_tags($contentParts[0]) : $settings['title'];
|
||||
@@ -155,7 +159,7 @@ class PageController extends Controller
|
||||
$lastSpace = strrpos($description, ' ');
|
||||
$description = substr($description, 0, $lastSpace);
|
||||
}
|
||||
|
||||
|
||||
/* get url and alt-tag for first image, if exists */
|
||||
if($firstImage)
|
||||
{
|
||||
|
@@ -49,9 +49,14 @@ class SettingsController extends Controller
|
||||
);
|
||||
|
||||
$copyright = $this->getCopyright();
|
||||
|
||||
|
||||
$validate->settings($newSettings, $copyright, 'settings');
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->c->flash->addMessage('error', 'Wrong Input');
|
||||
return $response->withRedirect($this->c->router->pathFor('settings.show'));
|
||||
}
|
||||
|
||||
if(isset($_SESSION['errors']))
|
||||
{
|
||||
|
35
system/Events/OnOriginalLoaded.php
Normal file
35
system/Events/OnOriginalLoaded.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Typemill\Events;
|
||||
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
|
||||
use Typemill\Extensions\ParsedownExtension;
|
||||
|
||||
/**
|
||||
* Event for html page.
|
||||
*/
|
||||
|
||||
class OnOriginalLoaded extends Event
|
||||
{
|
||||
protected $data;
|
||||
|
||||
public function __construct($data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
public function getMarkdown()
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
public function getHTML()
|
||||
{
|
||||
$parsedown = new ParsedownExtension();
|
||||
$contentArray = $parsedown->text($this->data);
|
||||
$contentHTML = $parsedown->markup($contentArray);
|
||||
|
||||
return $contentHTML;
|
||||
}
|
||||
}
|
14
system/Events/OnSessionSegmentsLoaded.php
Normal file
14
system/Events/OnSessionSegmentsLoaded.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Typemill\Events;
|
||||
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
|
||||
/**
|
||||
* Event for breadcrumb.
|
||||
*/
|
||||
|
||||
class OnSessionSegmentsLoaded extends BaseEvent
|
||||
{
|
||||
|
||||
}
|
@@ -357,7 +357,7 @@ class Validation
|
||||
break;
|
||||
case "text":
|
||||
$v->rule('lengthMax', $fieldName, 200);
|
||||
$v->rule('regex', $fieldName, '/^[\pL0-9_ \-\.\?\!]*$/u');
|
||||
$v->rule('regex', $fieldName, '/^[\pL0-9_ \-\.\?\!\/\:]*$/u');
|
||||
break;
|
||||
case "textarea":
|
||||
$v->rule('lengthMax', $fieldName, 1000);
|
||||
|
@@ -6,7 +6,7 @@ use \Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
abstract class Plugin implements EventSubscriberInterface
|
||||
{
|
||||
private $container;
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
@@ -17,6 +17,16 @@ abstract class Plugin implements EventSubscriberInterface
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
protected function getSettings()
|
||||
{
|
||||
return $this->container->get('settings');
|
||||
}
|
||||
|
||||
protected function getPluginSettings($plugin)
|
||||
{
|
||||
return $this->container->get('settings')['plugins'][$plugin];
|
||||
}
|
||||
|
||||
protected function getRoute()
|
||||
{
|
||||
|
@@ -19,6 +19,7 @@ const contentComponent = Vue.component('content-block', {
|
||||
methods: {
|
||||
switchToEditMode: function()
|
||||
{
|
||||
if(this.edit){ return; }
|
||||
eventBus.$emit('closeComponents');
|
||||
self = this;
|
||||
self.$root.$data.freeze = true; /* freeze the data */
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
use Typemill\Events\OnSettingsLoaded;
|
||||
use Typemill\Events\OnPluginsLoaded;
|
||||
use Typemill\Events\OnSessionSegmentsLoaded;
|
||||
|
||||
/****************************
|
||||
* CREATE EVENT DISPATCHER *
|
||||
@@ -103,13 +104,18 @@ $container['assets'] = function($c)
|
||||
* DECIDE FOR SESSION *
|
||||
************************/
|
||||
|
||||
$session_segments = array('setup', 'tm/', 'api/', '/setup', '/tm/', '/api/');
|
||||
$path = $container['request']->getUri()->getPath();
|
||||
$container['flash'] = false;
|
||||
$container['csrf'] = false;
|
||||
$session_segments = array('setup', 'tm/', 'api/', '/setup', '/tm/', '/api/');
|
||||
|
||||
# let plugins add own segments for session, eg. to enable csrf for forms
|
||||
$client_segments = $dispatcher->dispatch('onSessionSegmentsLoaded', new OnSessionSegmentsLoaded([]))->getData();
|
||||
$session_segments = array_merge($session_segments, $client_segments);
|
||||
|
||||
$path = $container['request']->getUri()->getPath();
|
||||
$container['flash'] = false;
|
||||
$container['csrf'] = false;
|
||||
|
||||
foreach($session_segments as $segment)
|
||||
{
|
||||
{
|
||||
if(substr( $path, 0, strlen($segment) ) === $segment)
|
||||
{
|
||||
// configure session
|
||||
|
Reference in New Issue
Block a user