typeNum in Link funktioniert nicht. Typo3 type removed from URL (Typo3 9, Typo3 10)

Problem nach dem Update auf Typo3 9 oder 10:

Beim Erstellen eines Links über den ViewHelper f:link.page, f:uri.page, f:link.typolink, f:uri.typolink etc. wird der typeNum-Parameter ignoriert.
Auch beim Versuch, type manuell über additionalParams zu übergeben, erscheint kein &type=123456 in der generierten URL:

<f:link.page pageType="123456" additionalParams="{s:1,p:2,type:123456}" pageUid="3"<

wird zu:
https://www.domain.de/?s=1&p=2

Der type=123456-Parameter wird einfach entfernt.

Lösung:
Die site-yaml Konfiguration prüfen und darauf achten, dass ein routeEnhancer für den Page-Type definiert wurde!


routeEnhancers:
  PageTypeSuffix:
    type: PageType
    default: '/'
    index: ''
    map:
      beispiel: 123456

Hier – als kleiner Spickzettel – noch mal die TypoScript-Setup zum simplen Aufruf einer Methode über typeNum.

Mit entsprechender Einstellung im TypoScript und der Site-Konfiguration (yaml) wird die angegebene Methode beim Aufruf der URL https://www.beispiel.de/?type=123456 ausgeführt.


beispiel = PAGE
beispiel {
  typeNum = 123456
  config {
    disableAllHeaderCode = 1
    xhtml_cleaning = 0
    admPanel = 0
    additionalHeaders = Content-type: text/plain
    no_cache = 1
    contentObjectExceptionHandler = 0
  }
  10 = USER
  10.userFunc = Pfad\Zu\Deinem\Script->methodenName
}

Für Suchmaschinen: Typo3 Typolink ignores type-Parameter, typeNum not working Typo3, typeNum funktioniert nicht, type wird aus URL entfernt beim ViewHelper. Typoscript mit page-type wird nicht ausgeführt. Problem typeNum in Link-URL.

typo3 templavoila – Sie haben nicht die nötigen Rechte, um diese Änderung durchzuführen.

Sie haben nicht die nötigen Rechte, um diese Änderung durchzuführen

Bei einer Typo3 6.2 Installation mit TemplaVoila 1.9.2 standen wir vor einem fast unlösbaren Rätsel: Aus unerfindlichem Grund funktionierte das Anlegen von neuen Inhaltselementen nicht mehr – weder in der Listenansicht noch in der TV-Seitenansicht. Nach Auswahl eines Contentelementes aus dem Wizard brach Typo3 mit der Fehlermeldung „Sie haben nicht die nötigen Rechte, um diese Änderung durchzuführen.“ ab. Und das, obwohl wir als Admin eingeloggt waren.

Vor wenigen Tagen noch lief alles problemlos und wir hatten kein Update eingespielt.
Im Netz findet mal viele Lösungen dazu, am häufigsten den Hinweis, dass ein Feld in der Datenbank-Tabelle pages fehlen würde.

t3ver_swapmode ist es nicht!

Die allgemein anerkannte Lösung, folgenden MySQL-Befehl zum Einfügen der fehlenden Spalte auszuführen, funktionierte aber leider nicht:

ALTER table pages add(`t3ver_swapmode` tinyint(4) NOT NULL DEFAULT '0');

MariaDB hat Probleme mit unmaskiertem „recursive“ von Typo3

Nach langem Suchen: Der Host hatte die Datenbank auf MariaDB umgestellt. MariaDB hat ein reserviertes Keyword recursive – das blöderweise auch ein Spaltenname in der Tabelle tt_content ist. Beim Generieren der INSERT-Query in /typo3/sysext/core/Classes/Database/DatabaseConnection.php maskiert Typo3 allerdings die Feldnamen nicht durch backticks – es steht als INSERT INTO tt_content (recursive, ...) statt INSERT INTO tt_content(`recursive`, ...).

Die Query bricht mit der Fehlermeldung „SQL Error: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ‚recursive,menu_type,list_type,table_bgColor,table_border,table_cellspacing,ta…‘ at line 1“ ab.

Patch und Lösung

Das Problem wurde in einer späteren Version von Typo3 gefixed. Für Typo3 < 6 kann es mithilfe dieser Patches zum Laufen gebracht werden: https://forge.typo3.org/attachments/35472?utf8=%E2%9C%93&type=sbs

Schritt für Schritt Anleitung

  1. Die Datei /typo3/sysext/core/Classes/Database/DatabaseConnection.php bearbeiten
  2. Folgende Zeilen suchen und ersetzen:

Suche nach:
$query = 'INSERT INTO ' . $table . ' (' . implode(',', array_keys($fields_values)) . ') VALUES ' . '(' . implode(',', $fields_values) . ')';
Ersetzen mit:
$query = 'INSERT INTO ' . $table . ' (`' . implode('`,`', array_keys($fields_values)) . '`) VALUES ' . '(' . implode(',', $fields_values) . ')';


Suche nach:
$query = 'INSERT INTO ' . $table . ' (' . implode(', ', $fields) . ') VALUES ';
Ersetzen mit:
$query = 'INSERT INTO ' . $table . ' (`' . implode('`,`', $fields) . '`) VALUES ';


Suche nach:
$fields[] = $k . '=' . $v;
Ersetzen mit:
$fields[] = '`' . $k . '`=' . $v;


Suche nach:
$queryParts[] = $table . '.' . implode(($like . ' OR ' . $table . '.'), $fields) . $like;
Ersetzen mit:
$queryParts[] = $table . '.`' . implode(('`' . $like . ' OR ' . $table . '.`'), $fields) . '`' .$like;


Für Suchmaschinen: In TYPO3 erscheint beim Anlegen eines Inhaltselements folgende Fehlermeldung von TemplaVoila: „Sie haben nicht die nötigen Rechte, um diese Änderung durchzuführen.“ Probleme Typo3 Zugriffsrechte Backend Templavoila trotz Admin-Rechten. TemplaVoila funktioniert unter MariaDB nicht mehr. Typo3 Problem MariaDB INSERT Query. TemplaVoila forbidden new content element, SQL Error: You have an error in your SQL syntax. MariaDB.

Typo3 Extension „mask“: Mehrere templateRootPaths angeben

Kleines, sehr hilfreiches TypoScript für die wunderbare Extension „mask“ (Typo3).

Nicht selten kommt man an das Problem, mehr als nur einen Pfad zu seinen Mask-Templates definieren zu wollen. Die Extension-Konfiguration im Backend lässt leider nur jeweils einen einzigen Pfad für Folder for Content Fluid Templates (with trailing slash) frontend.content (folder), Folder for Content Fluid Layouts (with trailing slash) frontend.layouts (folder) und Folder for Content Fluid Partials (with trailing slash) frontend.partials (folder) zu.

Das Problem lässt sich aber im TypoScript-Setup lösen.

Ab Typo3 9 LTS


lib.maskContentElement {
  templateRootPaths {
    // 10 wird von mask gesetzt, abhängig von der EXT-Konfiguration im Backend
    20 = EXT:deine/ext/Resources/Private/Templates/
  }
  partialRootPaths {
    // 10 wird von mask gesetzt, abhängig von der EXT-Konfiguration im Backend
    20 = EXT:deine/ext/Resources/Private/Partials/
  }
  layoutRootPaths {
    // 10 wird von mask gesetzt, abhängig von der EXT-Konfiguration im Backend
    20 = EXT:deine/ext/Resources/Private/Layouts/
  }
}

Bis einschließlich Typo3 8 LTS


lib.tx_mask {
  templateRootPaths {
    // 10 wird von mask gesetzt, abhängig von der EXT-Konfiguration im Backend
    20 = EXT:deine/ext/Resources/Private/Templates/
  }
  partialRootPaths {
    // 10 wird von mask gesetzt, abhängig von der EXT-Konfiguration im Backend
    20 = EXT:deine/ext/Resources/Private/Partials/
  }
  layoutRootPaths {
    // 10 wird von mask gesetzt, abhängig von der EXT-Konfiguration im Backend
    20 = EXT:deine/ext/Resources/Private/Layouts/
  }
}

Wenn mir jetzt noch jemand sagen könnte, wie man die mask.json in mehrere Dateien bekommt… dann würde ich den Entwicklern von mask eine Bierkasten-Abo schenken 🙂

Für Suchmaschinen: Typo3 Extension Mask. Mehrere Pfade zu Templates und templateRootPaths für mask typo3. mask typo3 multiple templateRootPaths. Zusätzliche Pfade für Mask-Templates per TypoScript angeben.

Typo3 tx_form: Empfänger im Frontend auswählbar machen. Eigenes Formular-Element und eigener Finisher

Im Formular-Editor des FormFrameworks von Typo3 soll man verschiedene Empfänger angeben können. Im Frontend erscheint eine Dropdown-Liste der Empfänger. Der User kann eine Zieladresse aus dem Dropdown auswählen und so bestimmen, wer die Mail erhält.


Anleitung im Backend FormEditor

  • Neues Formular-Element in Formular einfügen
  • Im Formular-Element eine Liste der möglichen Empfänger angeben. Pro Zeile ein Empfänger in dieser Schreibweise: email@adresse.de;Empfängername
  • Neuen Finisher für das Formular auswählen

1. Wähle einen Namen für Deine Extension

Wenn Du die beiden Felder hier ausfüllst, wird im Quelltext alles automatisch für Dich ersetzt:



2. Eine Extension anlegen

(oder eine vorhandene nutzen)

Wir ignorieren mal alle Normen und halten es simpel. Folgende Dateien und Struktur brauchst Du in Deiner Extension.

Ersetze nng durch den Ordner-Namen Deiner Extension, in der Du arbeitest.
Ersetze das Wort RecipientSelector im Dateinamen durch Deinen Bezeichner.

nng
│
├── Classes
│   ├── Finishers
│   │   └── RecipientSelectorFinisher.php
│   ├── ViewHelpers
│   │   └── RecipientSelectorViewHelper.php
├── Configuration
│   ├── TypoScript
│   │   └── setup.txt
│   └── Yaml
│       ├── BaseSetup.yaml
│       ├── FormEditorSetup.yaml
│       └── FormEngineSetup.yaml
├── Resources
│   ├── Private
│   │   └── FormFramework
│   │       └── Frontent
│   │           └── Partials
│   │               └── RecipientSelector.html
│   └── Public
│       ├── Icons
│       │   └── RecipientSelector-icon.svg
│       └── JavaScript
│           └── Backend
│               └── FormEditor
│                   └── RecipientSelectorViewModel.js
├── ext_emconf.php
├── ext_localconf.php
└── ext_typoscript_setup.txt

3. Inhalte der Dateien

Folgender Code muss in die einzelnen Dateien:


Configuration/TypoScript/setup.txt


# Einstellungen für das Frontend
plugin.tx_form.settings.yamlConfigurations {
   153450370601 = EXT:nng/Configuration/Yaml/FormEditorSetup.yaml
}
# Einstellungen für das Backend
module.tx_form.settings.yamlConfigurations {
   153450370601 = EXT:nng/Configuration/Yaml/FormEditorSetup.yaml
   153450370602 = EXT:nng/Configuration/Yaml/FormEngineSetup.yaml
}

Configuration/Yaml/FormEditorSetup.yaml


# ---------------------------------------------------------------------------
# Diese YAML wird im Backend UND Frontend geladen.
# 

TYPO3:
  CMS:
    Form:
      prototypes:
        standard:
          formElementsDefinition:

            # ---------------------------------------------------------
            # Registrierung zusätzlicher Fluid-Pfade

            Form:
              renderingOptions:
                templateRootPaths:
                  125: 'EXT:nng/Resources/Private/FormFramework/Frontend/Templates/'
                partialRootPaths:
                  125: 'EXT:nng/Resources/Private/FormFramework/Frontend/Partials/'
                layoutRootPaths:
                  125: 'EXT:nng/Resources/Private/FormFramework/Frontend/Layouts/'

            # ---------------------------------------------------------
            # Registrierung des neuen Formular-Elementes

            RecipientSelector:
              __inheritances:
                10: 'TYPO3.CMS.Form.mixins.formElementMixins.FormElementMixin'
              formEditor:
                label: 'Empfänger-Auswahl'
                group: custom
                groupSorting: 1000
                iconIdentifier: 'nng-selectrecipient'
                predefinedDefaults:
                  properties:
                    nng-recipients: ''
                editors:
                  300:
                    identifier: 'nng-recipients'
                    templateName: 'Inspector-TextareaEditor'
                    label: 'Empfänger-Liste'
                    propertyPath: 'properties.nng-recipients'

          # ---------------------------------------------------------
          # Registrierung des Finishers
          
          finishersDefinition:
            RecipientSelector:
              __inheritances:
                10: 'TYPO3.CMS.Form.mixins.finishersEmailMixin'
              implementationClassName: 'Nng\RecipientSelector\Finishers\RecipientSelectorFinisher'
              FormEngine:
                label: "C E-Mail an Empfänger aus Auswahl (nng)"
              formEditor:
                iconIdentifier: 'nng-selectrecipient'
                label: 'D E-Mail an Empfänger aus Auswahl (nng)'
                predefinedDefaults:
                  options:
                    pageUid: ''
                    additionalParameters: ''



Configuration/Yaml/FormEngineSetup.yaml



# ---------------------------------------------------------------------------
# Diese YAML wird NUR im Backend geladen.
# 

TYPO3:
  CMS:
    Form:
      prototypes:
        standard:

          # -------------------------------------------------------
          # JS für Formular-Element im Backend bereitstellen
          
          formEditor:

            dynamicRequireJsModules:
              additionalViewModelModules:
                125: 'TYPO3/CMS/Nnsite/Backend/FormEditor/RecipientSelectorViewModel'

            formEditorPartials:
              FormElement-RecipientSelector: 'Stage/SimpleTemplate'

          formElementsDefinition:
            Form:
              # -------------------------------------------------------
              # Backend: Definition des Finishers

              formEditor:
                editors:
                  # 900 ist fix. Hier werden die Finisher definiert.
                  900:
                    selectOptions:
                      125:
                        value: 'RecipientSelector'
                        label: 'E-Mail an Empfänger aus Auswahl (nnsite)'

                propertyCollections:
                  finishers:
                    125:
                      identifier: 'RecipientSelector'
                      editors:
                        __inheritances:
                          10: 'TYPO3.CMS.Form.mixins.formElementMixins.BaseCollectionEditorsMixin'
                        100:
                          label: "E-Mail an Empfänger aus Auswahl (nnsite)"
                        120:
                          identifier: 'fieldSubject'
                          templateName: 'Inspector-TextEditor'
                          label: 'Betreff'
                          propertyPath: 'options.fieldSubject'
                          enableFormelementSelectionButton: true
                          propertyValidators:
                            10: 'NotEmpty'
                        500:
                          identifier: 'fieldFromEmail'
                          templateName: 'Inspector-TextEditor'
                          label: 'formEditor.elements.Form.finisher.EmailToSender.editor.senderAddress.label'
                          propertyPath: 'options.fieldFromEmail'
                          enableFormelementSelectionButton: true
                          propertyValidatorsMode: 'OR'
                          propertyValidators:
                            10: 'NaiveEmail'
                            20: 'FormElementIdentifierWithinCurlyBracesExclusive'
                          fieldExplanationText: 'formEditor.elements.Form.finisher.EmailToSender.editor.senderAddress.fieldExplanationText'
                        600:
                          identifier: 'fieldFromName'
                          templateName: 'Inspector-TextEditor'
                          label: 'formEditor.elements.Form.finisher.EmailToSender.editor.senderName.label'
                          propertyPath: 'options.fieldFromName'
                          enableFormelementSelectionButton: true
                          propertyValidators:
                            10: 'FormElementIdentifierWithinCurlyBracesInclusive'
                          fieldExplanationText: 'formEditor.elements.Form.finisher.EmailToSender.editor.senderName.fieldExplanationText'

Classes/ViewHelpers/RecipientSelectorViewHelper.html

Das eigentliche Fluid-Template für die Ausgabe im Frontend.


<?php

namespace Extname\RecipientSelector\ViewHelpers;

use \TYPO3\CMS\Extbase\Utility\DebuggerUtility;
use \TYPO3\CMS\Core\Utility\GeneralUtility;


class RecipientSelectorViewHelper extends \TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper {


    /**
     * @var boolean
     */
    protected $escapeChildren = false;


    /**
     * @var boolean
     */
    protected $escapeOutput = false;
    
    
    /**
	 * Initialize arguments.
	 *
	 * @return void
	 */
	public function initializeArguments() {
		parent::initializeArguments();
    	$this->registerArgument('str', 'string', 'Text', false);
	}
	
	
	/**
	 * 
	 *
	 * @throws \TYPO3\CMS\Fluid\Core\ViewHelper\Exception
	 * @return string Rendered tag
	 */
	public function render() {
		$str = $this->arguments['str'] ?: $this->renderChildren();
		$rows = explode("\n", $str);
		foreach ($rows as $k => $row) {
			$parts = explode(";", $row);
			$rows[$k] = ['key' => $k, 'email' => $parts[0], 'label'=>$parts[1]];
		}
		return $rows;
    }


}

Classes/Finishers/RecipientSelectorFinisher.php


<?php
namespace Extname\RecipientSelector'\Finishers;
 
use TYPO3\CMS\Core\Utility\GeneralUtility;	 
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Core\Environment;
use TYPO3\CMS\Core\Utility\PathUtility;

class RecipientSelectorFinisher extends \TYPO3\CMS\Form\Domain\Finishers\EmailFinisher {
    
    /**
	 * Finisher
     * 
	 */
	protected function executeInternal()
	{
		$formRuntime = $this->finisherContext->getFormRuntime();
		$formValues = $this->finisherContext->getFormValues();

		$fromEmail = $this->parseOption('fieldFromEmail');
		$fromName = $this->parseOption('fieldFromName');
		$subjectEmail = $this->parseOption('fieldSubject');

		$recipientElement = false;

		// Finde das ERSTE Formular-Element, in dem die Empfänger definiert wurden
		foreach ($formValues as $k => $val) {
			$element = $formRuntime->getFormDefinition()->getElementByIdentifier($k);
			if ($element->getType() == 'RecipientSelector') {
				$recipientElement = [
					'key' 		=> $k,
					'element' 	=> $element,
					'value'		=> $val,
				];
			}
		}

		if (!$recipientElement) {
			die('Finisher ist im Formular angegeben, aber Formular-Element für Auswahl des Empfängers fehlt.');
		}

		$recipients = explode("\n", $recipientElement['element']->getProperties()['nnsite-recipients'] ?? '');

		foreach ($recipients as $n=>$recipient) {
			$parts = explode(";", $recipient);
			$recipients[$n] = [
				'key' => $n,
				'label' => $parts[1],
				'email' => $parts[0],
			];
		}

		if (!$recipients) {
			die('Keine Zieladressen im Formular angegeben.');
		}

		$recipientName = $recipients[$recipientElement['value']]['label'] ?? '';
		$recipientEmail = $recipients[$recipientElement['value']]['email'] ?? '';

		if (!$recipients) {
			die('Zieladresse nicht bekannt.');
		}

		$this->setOption('templateName', 'html');
		$this->setOption('subject', $subjectEmail);
		$this->setOption('recipientName', $recipientName);
		$this->setOption('recipientAddress', $recipientEmail);
		$this->setOption('senderName', $fromName);
		$this->setOption('senderAddress', $fromEmail);

		parent::executeInternal();
	}

}

Resources/Private/FormFramework/Frontend/Partials/RecipientSelector.html

Das eigentliche Fluid-Template für die Ausgabe im Frontend.

<div>
	<h2>{element.properties.elementDescription}</h2>
	<f:form.textfield
		property="{element.identifier}"
		id="{element.uniqueIdentifier}"
		class="{element.properties.elementClassAttribute} form-control form-field"
		errorClass="{element.properties.elementErrorClassAttribute}"
		additionalAttributes="{formvh:translateElementProperty(element:element, property: 'fluidAdditionalAttributes')}"
	/>	
</div>

Resources/Public/Icons/RecipientSelector-icon.svg

Ein simples, quadratisches SVG-Icon für die Darstellung im Backend.


Resources/Public/JavaScript/Backend/FormEditor/RecipientSelectorViewmodel.js


// Resources/Public/JavaScript/Backend/FormEditor/RecipientSelectorViewmodel.js

define([
    'jquery',
    'TYPO3/CMS/Form/Backend/FormEditor/Helper'
], function ($, Helper) {
    'use strict';

    return (function ($, Helper) {

        /**
         * @private
         *
         * @var object
         */
        var _formEditorApp = null;

        /**
         * @private
         *
         * @return object
         */
        function getFormEditorApp() {
            return _formEditorApp;
        };

        /**
         * @private
         *
         * @return object
         */
        function getPublisherSubscriber() {
            return getFormEditorApp().getPublisherSubscriber();
        };

        /**
         * @private
         *
         * @return object
         */
        function getUtility() {
            return getFormEditorApp().getUtility();
        };

        /**
         * @private
         *
         * @param object
         * @return object
         */
        function getHelper() {
            return Helper;
        };

        /**
         * @private
         *
         * @return object
         */
        function getCurrentlySelectedFormElement() {
            return getFormEditorApp().getCurrentlySelectedFormElement();
        };

        /**
         * @private
         *
         * @param mixed test
         * @param string message
         * @param int messageCode
         * @return void
         */
        function assert(test, message, messageCode) {
            return getFormEditorApp().assert(test, message, messageCode);
        };

        /**
         * @private
         *
         * @return void
         * @throws 1491643380
         */
        function _helperSetup() {
            assert('function' === $.type(Helper.bootstrap),
                'The view model helper does not implement the method "bootstrap"',
                1491643380
            );
            Helper.bootstrap(getFormEditorApp());
        };

        /**
         * @private
         *
         * @return void
         */
        function _subscribeEvents() {
            /**
             * @private
             *
             * @param string
             * @param array
             *              args[0] = formElement
             *              args[1] = template
             * @return void
             */
            getPublisherSubscriber().subscribe('view/stage/abstract/render/template/perform', function (topic, args) {
                if (args[0].get('type') === 'RecipientSelector') {
                    getFormEditorApp().getViewModel().getStage().renderSimpleTemplateWithValidators(args[0], args[1]);
                }
            });
        };

        /**
         * @public
         *
         * @param object formEditorApp
         * @return void
         */
        function bootstrap(formEditorApp) {
            _formEditorApp = formEditorApp;
            _helperSetup();
            _subscribeEvents();
        };

        /**
         * Publish the public methods.
         * Implements the "Revealing Module Pattern".
         */
        return {
            bootstrap: bootstrap
        };
    })($, Helper);
});

ext_emconf.php

Der übliche Code, um eine Extension zu registrieren – falls nicht schon vorhanden.

<?php
$EM_CONF[$_EXTKEY] = [
    'title' => 'Meine Extension',
    'description' => '',
    'category' => 'plugin',
    'author' => 'David Bascom',
    'author_email' => 'deine@email.de',
    'state' => 'stable',
    'internal' => '',
    'uploadfolder' => '1',
    'createDirs' => '',
    'clearCacheOnLoad' => 0,
    'version' => '0.1',
    'constraints' => [
        'depends' => [
            'typo3' => '8.7.0',
        ],
        'conflicts' => [],
        'suggests' => [],
    ],
];

ext_localconf.php

Registriert das Icon

<?php 
if (TYPO3_MODE === 'BE') {
    /** @var \TYPO3\CMS\Core\Imaging\IconRegistry $iconRegistry */
    $iconRegistry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Imaging\IconRegistry::class);
    $iconRegistry->registerIcon(
        'RecipientSelector-icon',
        \TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider::class,
        ['source' => 'EXT:nng/Resources/Public/Icons/RecipientSelector-icon.svg']
    );
}

ext_typoscript_setup.txt

Lädt das TypoScript, ohne das im Root-Template die „Enthält Erweiterungen“ gewählt werden müssen.

<INCLUDE_TYPOSCRIPT: source="FILE:EXT:nng/Configuration/Typoscript/setup.txt">

jQuery rebuild data – data-Attribut erneut parsen / einlesen

Bei der Arbeit mit VueJS in Kombination mit jQuery kommt es häufig zu dem Problem, dass VueJS das DOM oder sogar das data-Attribut eines Elementes ändert, aber jQuery noch per jQuery.data() auf alte Daten zugreift.

Hintergrund: Beim Initialisieren der Elemente cached jQuery die data-*-Attribute und speichert sie in einer internen Variable, um später schneller darauf zugreifen zu können. Eine Änderung der data-*-Attribute über VueJS – oder bereits eine Änderung der Reihenfolge der Elemente im DOM – führt zu einer falschen Zuordnung zwischen Element und dem data-Cache von jQuery.

Dieses kleine Plugin löst das Problem: Nach einer Änderung des DOM über VueJS kann einfach $('.element').rebuildData(); aufgerufen werden, um alle data-Attribute des Elementes und rekursiv aller Unterknoten erneut zu parsen und in jQuery.data() zu speichern.

Weiterlesen

Spamfreie E-Mails mit eigenem Server versenden

Wer eine eigene Domain besitzt, steht vor der Entscheidung die E-Mails auf ein Konto bei Anbietern wie Google Mail, GMX oder Web.de weiterzuleiten oder ein sich beim Hoster ein eigenes Konto für die E-Mail-Adresse einzurichten. Für letzteren Fall bieten Hosting-Provider wie Host Europe in der Regel einen eigenen Mailserver an, der bereits über eine entsprechende vorgefertigte Konfiguration verfügt. So werden auch passende DNS-Einträge der Domain beim Hoster automatisch gesetzt. Ganz bequem also. Doch sobald ein eigener Server im Einsatz ist, wird es möglicherweise schon etwas kniffeliger, um mit versendeten E-Mails nicht im Spam-Order des Empfängers zu landen. Wie ist dies also einzustellen?

Weiterlesen

Site-to-Site-Transfer (FXP) auf Server aktivieren

Folgendes Szenario:
Wir besitzen zwei verschiedene Server und möchten Daten via FTP von Server A auf Server B transferieren. Die einfachste und herkömmliche Methode wäre hierbei die Daten von Server A herunterzuladen und sie anschließend bei Server B wieder hochzuladen. Dieser Umweg kann insbesondere bei einer Vielzahl an Daten sehr langwierig sein.

Abhilfe für dieses Problem schafft das sogenannte File eXchange Protocol (FXP), welches einen Site-to-Site-Transfer von zwischen zwei Servern herstellt und eine direkte Datenübertragung ermöglicht.

Weiterlesen

Typo3 autoload-Cache leeren bei Klick auf Typo3-Blitz und „alle Caches leeren“

Während der Entwicklung von Typo3-Extensions ändert, erstellt und erweitert man häufig Klassen in seinem eigenen Namespace. Durch das (sinnvolle) Typo3-Caching werden diese Klassennamen und Pfade in einer PHP-Datei gecached (typo3conf/autoload/autoload_classmap.php).

Leider greift der Klick auf den „Typo3 Blitz“ mit der Option „Alle Caches leeren“ nicht, um auch diese Dateien neu aufzubauen. Typo3 zwingt den Entwickler ins Install-Tool und dort zu der Option „Create autoload information for extensions“. Dieser Wechsel ist relativ nervig – und eine klassische Frustrations-Quelle, wenn im Frontend mal wieder das „striped Zebra of death“ mit einem Fatal Error erscheint.

Weiterlesen

Eigenes Custom Form Element für tx_form-Extension – Typo3 v8

How-To für das Erstellen eines Custom Form Elements für die tx_form-Extension unter Typo3 v8.

Falls man ein Custom Form Element erstellen möchte, haltet euch an das How-To. Für detaillierte Informationen und die Dokumentation zur ext:form besucht: https://docs.typo3.org/typo3cms/extensions/form/Index.html

Außerdem haben wir eine „Anleitung für Dummies und Normalsterbliche, die einfach einen Job zu erledigen haben“ erstellt – eine Kurzfassung mit farblicher Kennzeichnung und einem simplen Online-Generator.

Weiterlesen