Quantcast
Channel: Typo3 – 99° Labor
Viewing all 20 articles
Browse latest View live

TYPO3 – Problem mit Datenbank: SQL error: ‘Incorrect integer value: ” for column ‘…’ at row 1′

$
0
0

Wenn diese Meldung auftaucht ist es meist ein Problem der Datenbank und dessen “StrictMode”.

Dies lässt sich ganz leicht lösen indem man im Install Tool folgendes einfügt:

$TYPO3_CONF_VARS['SYS']['setDBinit'] = "SET NAMES utf8; SET SESSION sql_mode = '';";

Typo3 page / pages_language_overlay um eigenes Feld erweitern, mit slide per TypoScript vererben

$
0
0

Aufgabe: Man möchte bei Typo3 in die Seiteneigenschaften einer Seite ein Feld ergänzen, z.B. eine Telefon-Nummer. Dieses Feld soll auf die Unterseiten per slide vererbt werden, wenn in einem Auswahlfeld der Wert “zeigen” gewählt wurde. Wählt man in dem Auswahlfeld nichts aus, wird die Einstellung der darüberliegenden Seite verwendet. Dadurch kann für einen Ast im Seitenbaum die Einstellung der darüberliegenden Seite komplett überschrieben werden.

Das Auswahlfeld soll für alle Sprachen gelten (ist also nur in der Tabelle “pages” vorhanden), das Textfeld für die Telefon-Nummer soll aber für jede Sprache getrennt voneinander angegeben werden können.

Das alles hier spiel sich in einer eigenen Extension ab.

Für Suchmaschinen: pageoverlayfields typo3, Seiteneigenschaften um eigenes Feld erweitern. Mehrsprachigkeit und sys_language_overlay bei eigenem Feld der Tabelle pages. levelfield mit slide bei eigenem Feld und Mehrsprachigkeit. pageOverlayFields und addRootLineFields um Wert auf Unterseiten zu vererben und mit slide per TypoScript auslesen. Tabelle pages_language_overlay um eigenes Feld erweitern. Mehrsprachigkeit bei eigenem Feld der Tabelle pages wird nicht angezeigt. Problem mit slide mit localization von pages_language_overlay. Tabellen pages, pages_language_overlay erweitern und das neue Feld slide-bar machen.

Wonach ich alles gesucht habe: “page field language_overlay typoscript typo3″, “languageOverlay typo3 tca”, “page typo3 field overlay language”, “typo3 slide typo3script text”, “addToAllTCAtypes(‘pages_language_overlay’”, “addToAllTCAtypes pages_language_overlay”, “page field language_overlay typoscript typo3″


Am Ende soll das ganze so aussehen:

Seiteneigenschaften in der Standard-Sprache
Hier sind zwei Felder: phone_btn zur Auswahl, ob das Feld angezeigt werden soll und phone_text mit der eigentlichen Texteingabe. Beide Felder sind neue Felder der Datenbank-Tabelle pages.

Seiteneigenschaften in den fremden (lokalisierten) Sprachversionen
Hier gibt es nur das Feld phone_text. Dieses Feld wurde der Tabelle pages_language_overlay hinzugefügt.


ext_tables.sql
CREATE TABLE pages (
   phone_btn varchar(15) DEFAULT '' NOT NULL,
   phone_text varchar(255) DEFAULT '' NOT NULL
);
 
CREATE TABLE pages_language_overlay (
   phone_text varchar(255) DEFAULT '' NOT NULL
);

ext_tables.php
// Feld, das nur in der Standardsprache existiert
$addPagesColumn = array (
   'phone_btn' => array(
      'exclude' => 0,
      'label' => 'Telefon-Nr zeigen',
      'config' => array(
         'type' => 'select',
         'default' => '',
         'items' => array(
            array('', ''),
            array('nicht zeigen', '-1'),
            array('zeigen', '1'),
         )
      ),
   ),
);
 
// Feld, das in allen Sprachen existiert
$addLangPagesColumn = array(
   'phone_text' => array(
      'exclude' => 0,
      'label' => 'Telefon-Nr',
      'config' => array(
         'type' => 'input',
         'default' => '',
      ),
   ),
);
 
// Feld im TCA der Tabelle 'pages' hinzufügen
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns('pages',$addPagesColumn,1);
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns('pages',$addLangPagesColumn,1);
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns('pages_language_overlay',$addLangPagesColumn,1);
 
// Ort der Feldes in den Backendeinstellungen definieren
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addFieldsToPalette('pages', 'layout', '--linebreak--,phone_btn,phone_text', '');
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes('pages_language_overlay', '--linebreak--,phone_text');

ext_localconf.php
$rootlinefields = &$GLOBALS["TYPO3_CONF_VARS"]["FE"]["addRootLineFields"];
if($rootlinefields != '') $rootlinefields .= ' , ';
$rootlinefields .= 'phone_btn,phone_text';
 
$GLOBALS['TYPO3_CONF_VARS']['FE']['pageOverlayFields'] .= ',phone_text';

TypoScript Setup Beispiel
lib.phone_text = TEXT
lib.phone_text {
    override.data = levelfield:-1, phone_text, slide
    override.if.isPositive.cObject = TEXT
    override.if.isPositive.cObject {
       data = levelfield:-1, phone_btn, slide
    }
}

The package “cdsrc_sass” depends on “leafo/scssphp” which is not present in the system

$
0
0

Beim Update der Typo3 Extension cdsrc_sass erscheint – abhängig von der Server-Umgebung – in der Version 2.0 die Fehlermeldung “The package “cdsrc_sass” depends on “leafo/scssphp” which is not present in the system”. Dadurch ist der Extension-Manager im Backend nicht mehr aufrufbar.

Um das Problem zu lösen, einfach in dem Ordner typo3conf/ext/cdsrc_sass die Datei composer.json löschen und den Typo3 Konfigurations-Cache leeren. Danach läuft alles wieder problemlos.

Typo3 DCE – Dynamic Content Elements – Spickzettel

$
0
0

Überschrift (header) in DCE nutzen

Den normalen Header der Inhaltselemente inkl. der Felder für Header-Layout (header_layout), Header-Ausrichtung (header_align) im DCE nutzen.

Im DCE unter dem Reiter Miscellaneous / Sonstiges in das Feld DCE palette fields folgendes eintragen:

header,--linebreak--,header_layout,header_position,--linebreak--,header_link,--linebreak--,subheader,--linebreak--,sys_language_uid,l18n_parent,colPos,spaceBefore,spaceAfter,section_frame,hidden

Und dann im Fluid-Template diese Anweisung zum Rendern nutzen:

<f:cObject typoscriptObjectPath="tt_content.header" data="{contentObject}" />

Typo3 hreflang-Metatag per TypoScript erstellen

$
0
0

SEO in Typo3: Mit Hilfe des hreflang-Tags kann man Google verständlich machen, dass die gewählte Seite in anderen Sprachen existiert. Hier eine Möglichkeit den hreflang-Tag inklusive des x-default-Tags per TypoScript zu generieren. Dabei wird der x-default-Tag auf “EN” (L=1) gestellt, falls eine Englische Übersetzung der Sprache existiert und auf “DE” (L=0), falls die Seite “EN” nicht existiert.

page.headerData.22 = HMENU
page.headerData.22 {
 
   special = language
   special.normalWhenNoLanguage = 0
   special.value = 0,1,2,3,4,5,6,7,8,9,10
 
   1 = TMENU
   1 {
      NO = 1
      NO {
         stdWrap.cObject = TEXT
         stdWrap.cObject {   
            value = de || en || nl || ru || tr || dk || fr || it || sw || no || es
         }
         linkWrap = <link rel="alternate" hreflang="|
         doNotLinkIt = 1
         after.cObject = TEXT
         after.cObject {
            stdWrap.wrap.cObject = COA
            stdWrap.wrap.cObject {
               10 = TEXT
               10.value < config.baseURL
               10.stdWrap.wrap = " href="|
               20 = TEXT
               20.value = |" />
            }
            stdWrap.typolink.parameter.data = page:uid
            stdWrap.typolink.additionalParams = &L=0 || &L=1 || &L=2 || &L=3 || &L=4 || &L=5 || &L=6 || &L=7 || &L=8 || &L=9 || &L=10
            stdWrap.typolink.returnLast = url
         }
 
         before.cObject = TEXT
         before.cObject {
            stdWrap.wrap.cObject = TEXT
            stdWrap.wrap.cObject {
               value =
               stdWrap.wrap = || <link rel="alternate" hreflang="x-default" href="|" /> || || || || || || || ||
               stdWrap.typolink.additionalParams = &L=1
               stdWrap.typolink.parameter.data = page:uid
               stdWrap.typolink.returnLast = url
               stdWrap.typolink.forceAbsoluteUrl = 1
 
               if.isTrue.cObject = TEXT
               if.isTrue.cObject.stdWrap.wrap = || 1 || ||
            }
         }
      }
 
      CUR = 1
      CUR {
         doNotShowLink = 1
      }
 
      # Seite existiert nicht in Übersetzung!
      USERDEF1 < .NO
      USERDEF1 {
         doNotShowLink = 1
         doNotLinkIt = 1
         linkWrap >
         stdWrap >
         after >
         before.cObject {
            stdWrap.wrap.cObject {
               stdWrap.typolink.additionalParams = &L=0
            }
         }
      }
   }
}

Installation Typo3 unter AMPPS

$
0
0

Spickzettel für verschiedene Problem, die bei der Installation von Typo3 6.2 unter AMPPS (Mac OSX El Capitan) mit PHP 5.6 entstanden sind. Als SMTP-Server diente ein externer Server bei HostEurope, der als SMTP-Zieladresse für die lokale postfix Konfiguration angegeben wurde.


TER Typo3 Repository: Update nicht möglich

Beim Versuch, über den Extension Manager die Liste der Typo3 Extensions aus dem TER (Typo3 Extension Repository) zu aktualisieren erscheint die Fehlermeldung “Aktualisieren der Erweiterungsliste: Could not access remote resource https://repositories.typo3.org/mirrors.xml.gz”.
Grund dafür war hier leider nicht eine einfache und in vielen Foren beschriebene Fehlkonfiguration von PHP (z.B. fehlendes PHP curl-Modul, allow_url_open = 0/Off oder allow_url_include = Off), sondern eine Änderung des Sicherheitsstandards bei OpenSSL und cURL.

Lösung:
1. Per Terminal mit HomeBrew OpenSSL installieren

brew install openssl

2. In der php.ini diese Zeile am Ende einfügen (Pfad evtl. anpassen)

openssl.cafile=/usr/local/etc/openssl/cert.pem

3. In der php.ini darauf achten, dass diese Zeile nicht auskommentiert ist:

extension=curl.so

4. Die cacert.pem von https://curl.haxx.se/docs/caextract.html downloaden und in ein Verzeichnis spielen, dass von PHP erreicht werden kann. Im Beispiel habe ich es unter /Applications/AMPPS/php-5.6/etc/ abgelegt. Dann am Ende der php.ini diese Zeile einfügen:

curl.cainfo = /Applications/AMPPS/php-5.6/etc/cacert.pem

5. Apache neu starten (direkt über das AMPPS Interface)


Mailversand über PHP mail() funktioniert nicht

Typo3 versendet keine Mails. Dazu gibt es zwei mögliche Lösungsansätze.
Falls es nur um Formhandler geht, diesen Beitrag lesen.
Einfacher Test, um zu prüfen, ob der mail()-Befehl funktioniert:

<?php
	$empfaenger = 'deine@email.de';
	$betreff = 'Wichtige Nachricht an Dich!';
	$nachricht = "Diese Mail sollte versendet werden.";
	$header = 'From: Dein Name<'.$empfaenger.'>' . "\r\n" .
		'Reply-To: ' . $empfaenger . "\r\n" .
		'X-Mailer: PHP/' . phpversion();
 
	$status = mail($empfaenger, $betreff, $nachricht, $header, "-f".$empfaenger);
	echo $status ? "Mail versendet." : "Mail konnte nicht gesendet werden.";
?>

Erste Lösung: SMTP für Versand nutzen

In der LocalConfiguration.php den Abschnitt “MAIL” mit einem externen SMTP-Server bestücken:

'MAIL' => [
     'transport' => 'smtp',
     'transport_smtp_password' => 'xxxxxxxxxxxx',
     'transport_smtp_server' => 'mail.xxxxxxxxxx.de:25',
     'transport_smtp_username' => 'wp-xxxxxxxxxx',
 ],

Zweite Lösung: postfix für den Versand konfigurieren

Diese Lösung behebt das Problem an der Wurzel und konfiguriert den bei Mac vorinstallierten postfix/sendmail zum Versand der Mails über einen externen SMTP-Dienst. In diesem Beispiel nutzen wir einen Mailserver bei HostEurope (Webpack, Virtual Server etc.). Die Zugangsdaten entsprechen den identischen Daten, die auch im Programm Mac “Mail” eingegeben werden.

1. Die Datei /etc/postfix/master.cf bearbeiten und folgenden Zeilen am Ende ergänzen.
Unter relayhost den HostEurope MailServer eintragen.

relayhost=mail.deineDomain.de:25
smtp_sasl_auth_enable=yes
smtp_sasl_password_maps=hash:/etc/postfix/sasl_passwd
smtp_use_tls=yes
smtp_tls_security_level=encrypt
smtp_sasl_security_options =

2. In dem Verzeichnis /etc/postfix/ eine Datei sasl_passwd anlegen und folgenden Inhalt einfügen.
deineDomain, wpXXXXXX-user und passwort durch Deine Mail-Zugangsdaten beim Host ersetzen.

mail.deineDomain.de	wpXXXXXXX-user:passwort

3. Im Terminal nacheinander folgende Kommandos ausführen:

sudo postmap /etc/postfix/sasl_passwd
sudo postfix stop && sudo postfix start
echo "Dies ist eine Testmail" | mailx -s "Test" deine@adresse.de

Danach sollte eine Mail versendet werden. Falls nicht, lässt sich der Status des lokalen Mail-Queues mit folgender Eingabe prüfen:

mailq

Um den Mail-Versand in einer Textdatei zu loggen, richte ich gerne noch ein Logfile ein. Diese Anpassungen kommt in die php.ini von AMPPS. Der Benutzername “99grad” muss natürlich angepasst werden:

mail.log = /Users/99grad/Desktop/mail.log

Grunt auf Mac installieren

$
0
0

Schnelldurchlauf, um auf Mac OSX (10.11 El Capitan) Grunt zu installieren. Vielen Dank an Martin Wagner für die Starthilfe!

1. NodeJS/npm Installer für Mac downloaden und installieren:

https://nodejs.org/en/download/

2. Im Terminal diese Befehle ausführen:

sudo npm update -g npm
sudo npm install -g grunt-cli

3. Config-Dateien anlegen

Ins Projekt-Verzeichnis gehen und in der Root diese beiden Dateien anlegen:
package.json

{
  "name": "testgrunt",
  "version": "1.0.0",
  "description": "MyTest",
  "main": "index.html",
  "scripts": {
    "test": ""
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "grunt": "^1.0.1",
    "grunt-autoprefixer": "^3.0.4",
    "grunt-bootstrap": "^0.1.0",
    "grunt-bootstrap-prefix": "^0.1.0",
    "grunt-contrib-uglify": "^1.0.1",
    "grunt-contrib-watch": "^1.0.0",
    "grunt-css-prefix": "^0.2.3",
    "grunt-sass": "^1.2.0"
  }
}

gruntfile.js (Pfade müssen angepasst werden)

module.exports = function(grunt) {
 
	// Configure task(s)
	grunt.initConfig({
		pkg: grunt.file.readJSON('package.json'),
 
		uglify: {
			build: {
				src: 'grunt_test/js/*.js',
				dest: 'grunt_test/ugliy-js.js'
			},
			dev: {
				options: {
					beautify: true,
					mangle: false,
					compress: false,
					preserveComments: 'all'
				},
				src: 'grunt_test/js/*.js',
				dest: 'grunt_test/ugliy-dev-js.js'
			}
		},
 
		watch: {
			options: {
				livereload: true,
			},
			js: {
				files: ['grunt_test/**/*.js'],
				tasks: ['uglify:dev']
 
			},
			html: {
				files: ['grunt_test/**/*.html']
 
			},
			css: {
				files: ['grunt_test/**/*.scss'],
				tasks: ['sass:dev']
			},
			typoscript: {
				files: ['grunt_test/**/*.ts']
			}
		},
		sass: {
			dev: {
				options: {
					outputStyle: 'expanded'
				},
				files: {
					'grunt_test/dev-merged.css' : 'grunt_test/scss/main.scss',
					// 'css/bootstrap.css' : 'src/scss/bootstrap.scss'
				}
			},
			build: {
				options: {
					outputStyle: 'compressed'
				},
				files: {
					'grunt_test/merged.css' : 'grunt_test/scss/main.scss',
					// 'css/bootstrap.css' : 'src/scss/bootstrap.scss'
				}
			}
		},
	});
 
 
	// Load PlugIns
	grunt.loadNpmTasks('grunt-contrib-uglify');
	grunt.loadNpmTasks('grunt-contrib-watch');
	grunt.loadNpmTasks('grunt-sass');
 
	// Register Tasks
	// grunt.registerTask('default', ['uglify:dev', 'sass:dev', 'watch']);
	// grunt.registerTask('build', ['uglify:build', 'sass:build', 'watch']);
 
	grunt.registerTask('default', ['uglify:dev', 'sass:dev']);
	grunt.registerTask('build', ['uglify:build', 'sass:build']);
 
};

4. Grunt initialisieren

Per Terminal ins Projektverzeichnis wechseln und das hier ausführen:

npm install
npm install grunt --save-dev

5. Befehle testen

Ab dann können folgende Befehle ausgeführt werden:

grunt (alle dateien uncompressed etc…)
grunt build (alles fertig für live version)
grunt watch (beobachten im Browser, dazu dann die Seite im Browser nochmal nach neu laden per Hand, danach übernimmt „Liverelad“ das Neuladen)

“Live-Reload” Chrome-PlugIn installieren:
https://chrome.google.com/webstore/detail/livereload/jnihajbhpnppcggbcgedagnkighmdlei

Typo3: TCA Default-Werte dynamisch setzen, per TSConfig oder Script

$
0
0

Problem: Man möchte, dass beim Anlegen eines neuen Datensatzes in Typo3 (z.B. News- oder Kalender-Eintrag) im Backend automatisch bestimmte Default-Werte für die Eingabefelder (TCA) gesetzt werden. Die default-Werte des TCA sollen sich aber dynamisch ändern, z.B. abhängig von der aktuell gewählten Seite (pid).

Anwendungsbeispiel: Mehrere Redakteure legen News für unterschiedliche Zentren an. Für jedes Zentrum gibt es einen eigenen SysFolder. Abhängig von Ordner soll die News direkt einer bestimmten News-Kategorie zugeordnet werden.

Für Suchmaschinen: Setzen von default-Werten TCA Typo3. Typo3 dynamically set default TCA values with TypoScript. Hook Signal Slot for setting TCA default value. News (tx_news) automatisch einer News-Kategorie / sys_category zuweisen, abhängig von der pid. SysFolder automatisch bestimmte default-Werte oder News-Kategorie. TCAdefaults per Hook setzen. TCA default-Werte dynamisch in Signal Slot setzen. Typo3 7.6 FormEngine getSingleField_preProcess getSingleFieldClass Hook. Typo3 TCA default Werte dynamisch per Script setzen, abhängig von der pid aktueller Seite.

Einfache Anwendungsfälle

Lösung per PageCondition in page TSconfig mit TCAdefaults

Definition in der pageTsConfig: Beim Durchlesen der Typo3 Dokumentation zu dem Thema klingt die page TSconfig für TCEFORM zunächst relativ vielversprechend:

TCEFORM.[table name].[field].config.[key] = Wert

Diese Einstellung funktioniert allerdings nur, wenn man damit z.B. die Anzahl der Zeilen eines Textfeldes ändern möchte, hier am Beispiel der Extension News (tx_news):

TCEFORM.tx_news_domain_model_news.title.config.type = text
TCEFORM.tx_news_domain_model_news.title.config.rows = 10

Irreführend ist, dass das Setzen eines default-Wertes damit nicht möglich, dafür aber mit TCAdefaults:

# No chance!!
TCEFORM.tx_news_domain_model_news.title.config.default = Mein Default-Titel
# So geht es:
TCAdefaults.tx_news_domain_model_news.title = Wundervoll!

Mit Hilfe einer einfache Page-Condition kann damit die Aufgabe für simple Anwendungsfälle gelöst werden:

[PIDinRootline = 21]
   TCAdefaults.tx_deineextension_domain_model_entry.title = Artikel auf Seite 21
[PIDinRootline = 23]
   TCAdefaults.tx_deineextension_domain_model_entry.title = Artikel auf Seite 23
[global]

Kleines Wunder nebenbei: das Setzen der Werte funktioniert auch mit MM-Relationen, z.B. für sys_category! Solle eine News direkt bestimmten sys_category-Kategorien zugeordnet werden, kann das über eine kommaseparierte Liste mit den uids der sys_category gemacht werden:

TCAdefaults.tx_news_domain_model_news.categories = 1,2,7

Komplexere Anwendungsfälle

Lösung per Hook – bis Typo3 Version 4.7

Wie in einem schönen Artikel von Irene Höppner beschrieben, gab es bis zu Typo3 Version 4.7 einen wundervollen Hook (getSingleField_preProcess bzw. getSingleFieldClass), um das Problem zu lösen. Ein Artikel auf StackOverflow bringt die Lösung auf den Punkt: tt_news Autor automatisch per Hook setzen
Seit dem Einsatz der neuen FormEngine wurden aber ersatzlos alle Hooks und Signal/Slots entfernt.

Stefan Frömken schlägt für Typo3 > 6.2 eine modernere Lösung vor, die sich aber für die meisten Anwendungsfälle etwas zu aufwändig anfühlt.

Lösung per dynamischem User TSconfig in der ext_localconf.php

In einem Artikel von Netzhaut beschrieben, besteht die Möglichkeit, dass User TSconfig dynamisch einzubinden. Das erlaubt z.B. auch die Verwendung von PHP Code.

Entgegen des TCA (dessen final generiertes Array im Cache landet), wird der Inhalt der ext_localconf.php bei jedem Seitenaufruf im Backend neu gerendert. Dadurch wird in dem Beispiel der TimeStamp jedes Mal neu generiert:

Dazu kommt diese Zeile in die ext_localconf.php der eigenen Extension:

 \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addUserTSConfig(
   'TCAdefaults.tx_nnportfolio_domain_model_entry.title = Aktueller tstamp: '.mktime()
);

Lösung per dynamischem Page TSconfig in der ext_localconf.php

Das Gleiche funktioniert mit einer dynamischen Erweiterung der PageTSconfig:

\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPageTSConfig(
   'TCAdefaults.tx_nnportfolio_domain_model_entry.title = Aktueller tstamp: '.mktime()
);

Maximal komplexe Anwendungsfälle

Wem das noch nicht reicht, der könnte das Problem noch deutlich flexibler lösen. In folgendem Beispiel sollen die Default-Werte für einen Datensatz per TypoScript-Setup definierbar sein. Dazu definieren wir alle Default-Werte im Setup – key ist dabei die pid der entsprechenden Seite:

plugin.tx_nnportfolio_nnportfolio {
   settings {
      defaultValuesByPid {
         21 {
            title = Hallo! Du bist auf Seite 21.
            addresses = 2,3
            categories = 1,2,3,4,5
         }
         23 {
            title = Das ist Seite 23.
            addresses = 1
            categories = 5
         }
 
      }      
   }
}

In die ext_localconf.php kommt eine Funktion, die unseren eigenen “Hook” aufruft und die TCA-Spalten für unsere Extension übergibt:

if (TYPO3_MODE == 'BE') {
   \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('Nng\\Nnportfolio\\Hooks\\TCAdefaultValuesHook')
      ->setDefaultValuesFromTS( $GLOBALS['TCA']['tx_nnportfolio_domain_model_entry']['columns'] );
}

Dann fehlt nur noch der entsprechende Hook. Er enthält einige zusätzliche Methoden, um im Backend an das TypoScript Setup für die aktuell ausgewählte Seite zu kommen.

 
<?php
 
namespace Nng\Nnportfolio\Hooks;
 
 
class TCAdefaultValuesHook {
 
   /**
   *   Get TypoScript Setup in backend
   *
   */
   public static function getTsSetup () {
 
      $pageUid = self::get_current_pid($pageUid);
 
      $sysPageObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\Page\\PageRepository');
      $rootLine = $sysPageObj->getRootLine($pageUid);
 
      $TSObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\TypoScript\\ExtendedTemplateService');
      $TSObj->tt_track = 0;
      $TSObj->init();
      $TSObj->runThroughTemplates($rootLine);
      $TSObj->generateConfig();
 
      $typoscriptService = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\Extbase\\Service\\TypoScriptService');
 
      return $typoscriptService->convertTypoScriptArrayToPlainArray(
         (array) $TSObj->setup['plugin.']['tx_nnportfolio_nnportfolio.']
      );
 
   }
 
   /**
   *   Get current PID in backend.
   *   Uses various fallbacks depending on current view and backend module.
   *   ToDo: Ask somebody, how this can be done simple :)
   */
   public static function get_current_pid ( $pageUid = null ) {
      if (!$pageUid) $pageUid = (int) $GLOBALS['_REQUEST']['popViewId'];
      if (!$pageUid) $pageUid = (int) preg_replace( '/(.*)(id=)([0-9]*)(.*)/i', '\\3', $GLOBALS['_REQUEST']['returnUrl'] );
      if (!$pageUid) $pageUid = (int) preg_replace( '/(.*)(id=)([0-9]*)(.*)/i', '\\3', $GLOBALS['_POST']['returnUrl'] );
      if (!$pageUid) $pageUid = (int) preg_replace( '/(.*)(id=)([0-9]*)(.*)/i', '\\3', $GLOBALS['_GET']['returnUrl'] );
      if (!$pageUid) $pageUid = (int) $GLOBALS['TSFE']->id;
      if (!$pageUid) $pageUid = (int) $_GET['id'];
      if (!$pageUid) {
         list($page) = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordsByField('pages', 'pid', 0);
          $pageUid = intval($page['uid']);
      }
      return $pageUid;
   }
 
 
   /**
   *   Set TCA default value from TypoScript setup
   *
   */
   public static function setDefaultValuesFromTS ( &$columns ) {
 
      $settings = self::getTsSetup();
      $pid = self::get_current_pid();
 
      if ($defaultValuesByPid = $settings['settings']['defaultValuesByPid'][$pid]) {      
         foreach ($defaultValuesByPid as $k=>$v) {
            $columns[$k]['config']['default'] = $v;
         }
      }
   }
 
 
}

Typo3 bootstrap_grids Header rendern

$
0
0

So kann man bei der Typo3-Extension bootstrap_grids den Header für die 2-, 3- und 4-Spalter ausgeben lassen:

tt_content.gridelements_pi1.20.10.setup {
   2cols.prepend = COA
   2cols.prepend.5 < lib.stdheader
   3cols.prepend = COA
   3cols.prepend.5 < lib.stdheader
   4cols.prepend = COA
   4cols.prepend.5 < lib.stdheader
}

Für Google: Header field:header bei bootstrap_grid ausgeben, rendern lib.stdheader für tt_content-Element. gridelements: Header aus tt_content-Tabelle ausgeben.

Typo3 Button “Dateien auswählen und hochladen” fehlt im Backend bei Redakteuren

$
0
0

Thema “Benutzer-Rechte anlegen im Typo3 Backend” – weil ich es immer wieder suche. Folgendes Problem: Ein Redakteur sieht den Button Dateien auswählen und hochladen nicht.

Folgende Einstellungen sind auf der Typo3-Wurzel korrekt gesetzt:

  • Unter “Dateispeicher” gibt es nur den Default-Dateispeicher “fileadmin/”
  • Unter “Verzeichnisfreigaben” gibt es eine Freigabe auf einen bestimmten Ordner (z.B. “fileadmin/zentren/wiesbaden”)
  • Die Verzeichnisfreigabe wurde korrekt dem Benutzer (oder der Benutzergruppe) zugeordnet

Trotzdem erscheint der Button Dateien auswählen und hochladen in der Ansicht des Redakteurs nicht.

Grund: Es wurde kein Default-Upload-Ordner für den Redakteur angegeben. Dazu unter dem Benutzer / Benutzergruppe, Reiter “Optionen” bei TSconfig diese Einstellungen machen:

options.defaultUploadFolder = 1:/zentren/wiesbaden/

Die 1: steht dabei für die uid des Dateispeichers (fileadmin)

Für Suchmaschinen: Typo3 Upload Button fehlt. Backend Typo3 missing upload button. Button for fileupload missing Typo3 Backend. Redakteur kann Dateien nicht hochladen. Upload von Dateien im Backend nicht möglich. Typo3 upload-Button ausgeblendet. Bei Redakteuren ist der Upload-Button im Backend verschwunden. “Select & upload files” button not showing for non-admin users. Missing “Select & upload files” button for editors. Redakteur Dateien auswählen und hochladen.

Typo3 PowerMail Finisher Beispiel

$
0
0

Viele Jahre lang war Typo3 Formhandler das “Schweizer Messer” für uns in Sachen Formulare. Gerade die Möglichkeit, verschieden Hooks / Finisher und Preprocessoren zu implementieren machte Formhandler zu einer perfekten Basis aller komplizieren Wünsche und Anforderungen.

Eines Tages überraschte uns ein rotes Warnschild auf der Formhandler-Webseite, dass Formhandler nicht weiter entwickelt wird. Zeit sich nach Alternativen umzuschauen.

PowerMail hatten wir ehrlich gesagt über Jahre vernachlässigt: Es wirkte eher wie ein “Formularwerkzeug für Redakteure” und schien eher unflexibel und ungestaltbar. Aber weit gefehlt: Seit langer Zeit bietet auch PowerMail verschiedene Finisher – und spätestens seit der Umstellung auf Fluid und Bootstrap gibt es eigentlich keine Ausreden mehr.

Hier ein kurzes Beispiel für einen möglichen Ansatz, mit vielen verschiedenen PowerMail-Formularen umzugehen, die unterschiedliche Konfigurationen und Finisher aufrufen sollen.

Für Suchmaschinen: PowerMail Finisher nur für bestimmte Formulare. Eigene Mail-Funktion PowerMail. PowerMail Finisher Beispiel mit mehreren Formularen.

PowerMail Finisher: Aufruf des eigenen Finishers

Zunächst muss der Finisher “scharf” geschaltet werden. Das geht mit wenigen Zeilen TypoScript Setup:

plugin.tx_powermail.settings.setup {
   finishers {
      1 {
         class = Meine\Extension\Finisher\PowerMailFinisher
      }
   }
}

Danach werden ALLE Anfragen NACH dem Versand der E-Mail zusätzlich noch an unseren Finisher geschickt. Für den Fall, dass die Daten VOR dem Versand verändert werden sollen, gibt es übrigens auch einen PowerMail DataProcessor

Problem: Leider lässt sich so aber nicht steuern, wann und wo der Finisher nicht aufgerufen werden soll. Klar: Page-Conditions wären eine Möglichkeit:

[PIDinRootline = 123]
   plugin.tx_powermail.settings.setup.finishers.1 >
[global]

Nur leider: Spätestens, wenn das Formular auf eine anderer Seite kopiert wird gibt es ein Problem.

PowerMail Finisher: Konfiguration für einzelne Formulare

Hier gehen wir einen anderen Weg: Per TypoScript Setup definieren wir für jedes PowerMail-Formular beliebige Variablen und Einstellungen, die wir später verwenden wollen. KEY ist dabei die UID des PowerMail-Formulars (NICHT die tt_content.uid !). Lassen wir eine Key aus, wird später auch der Finisher abgebrochen.

plugin.tx_powermail.settings.setup.finishers.1.config {
 
   # KEY ist die uid des PowerMail-Formulars (NICHT tt_content.uid)
 
   # Konfiguration für das PowerMail-Formular mit der uid=1
   1 {
      beispiel = wert
      noch_ein_beispiel {
         was = immer
         ...
      }
   }
 
   # Konfiguration für das PowerMail-Formular mit der uid=2
   2 {
      ...
   }
 
   # Formular Nr. 3 ist ein normales Kontakt-Formular. 
   # Wir lassen hier einfach die Konfiguration aus.
 
   # Konfiguration für das PowerMail-Formular mit der uid=4
   4 {
      ...
   }
}

PowerMail Finisher

Der PowerMail Finisher selbst übernimmt dann die Auswertung und ggf. den Abbruch des Finishings, falls es keine Konfiguration für das PowerMail-Formular mit der aktuellen uid gibt:

namespace Meine\Extension\Finisher;
 
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Utility\DebuggerUtility;
 
class PowerMailFinisher extends \In2code\Powermail\Finisher\AbstractFinisher {
 
   /**
    * @var \In2code\Powermail\Domain\Repository\MailRepository
    * @inject
    */
   protected $mailRepository;
 
   /**
    * @var \TYPO3\CMS\Extbase\Object\ObjectManager
    * @inject
    */
   protected $objectManager;
 
   public function myFinisher() {
 
      // Settings und Konfigurationen 
      $settings = $this->getSettings();
      $configuration = $this->getConfiguration();  
 
      // Ein cObject gibt es auch    
      $cObjData = $this->contentObject->data;
 
      // Beispiel: Gerenderte Mail holen
      $mail = $this->getMail();
 
      // Beispiel für den Zugriff auf FlexForm-Werte
      $ffService = GeneralUtility::makeInstance( \TYPO3\CMS\Extbase\Service\FlexFormService::class );
      $ffData = $ffService->convertFlexFormContentToArray( $cObjData['pi_flexform'] );
 
      // Die eigentliche uid des PowerMail-Formulars
      $powerMailFormUid = $settings['main']['form'];
 
      // Die spezielle Konfiguration für dieses Formular, falls vorhanden 
      $mailformConfig = $configuration[$powerMailFormUid];
 
      // Wenn keine Konfiguration vorhanden, dann Abbruch!
      if (!$mailformConfig) return;
 
      // Zugriff auf Formular-Daten
      $formData = $this->mailRepository->getVariablesWithMarkersFromMail($mail);
 
	  //
	  // und jetzt: Austoben!!
	  // 
 
      return true;
   }
 
}

Typo3 eID Dispatcher für Typo3 ab 7.6

$
0
0

Hier ein funktionierender eID Dispatcher Bootstrap für Typo3 ab Version 7.6, der auch das TSFE setzt und den Frontend-User (fe_user) initialisiert:

<?php
 
use \TYPO3\CMS\Core\Core\Bootstrap;
use \TYPO3\CMS\Core\Utility\ArrayUtility;
use \TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use \TYPO3\CMS\Core\Utility\GeneralUtility;
use \TYPO3\CMS\Frontend\Utility\EidUtility;/**/
 
/**
 * Gets the Ajax Call Parameters
 */
$_gp = \TYPO3\CMS\Core\Utility\GeneralUtility::_POST();
$_gp = \TYPO3\CMS\Extbase\Utility\ArrayUtility::arrayMergeRecursiveOverrule(
	$_gp,
	\TYPO3\CMS\Core\Utility\GeneralUtility::_GET()
);
 
$ajax = array();
$ajax['arguments']	= $_gp;
$ajax['vendor'] 	= 'Nng';
$ajax['extensionName'] 	= 'Nnfesubmit';
$ajax['pluginName'] 	= 'Pi1';
$ajax['controller'] 	= 'Eid';
$ajax['action'] 	= 'processRequest';
 
 
/**
 * @var $TSFE \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
 */
$TSFE = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController', $TYPO3_CONF_VARS, 0, 0);
$GLOBALS['TSFE'] = $TSFE;
 
\TYPO3\CMS\Frontend\Utility\EidUtility::initLanguage();
\TYPO3\CMS\Frontend\Utility\EidUtility::initTCA();
// Get FE User Information
$TSFE->initFEuser();
$TSFE->initUserGroups();
// Important: no Cache for Ajax stuff
$TSFE->set_no_cache();
 
$TSFE->checkAlternativeIdMethods();
$TSFE->determineId();
$TSFE->initTemplate();
$TSFE->getConfigArray();
\TYPO3\CMS\Core\Core\Bootstrap::getInstance();
 
$TSFE->cObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer');
$TSFE->settingLanguage();
$TSFE->settingLocale();
 
 
/**
 * Initialize Database
 */
$TSFE->connectToDB();
 
/**
 * @var $objectManager \TYPO3\CMS\Extbase\Object\ObjectManager
 */
$objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Extbase\Object\ObjectManager');
 
/**
 * Initialize Extbase bootstap
 */
$bootstrapConf['extensionName'] = $ajax['extensionName'];
$bootstrapConf['pluginName']	= $ajax['pluginName'];
 
$bootstrap = new \TYPO3\CMS\Extbase\Core\Bootstrap();
$bootstrap->initialize($bootstrapConf);
$bootstrap->cObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer');
 
/**
 * Build the request
 */
$request = $objectManager->get('TYPO3\CMS\Extbase\Mvc\Request');
 
$request->setControllerVendorName($ajax['vendor']);
$request->setcontrollerExtensionName($ajax['extensionName']);
$request->setPluginName($ajax['pluginName']);
$request->setControllerName($ajax['controller']);
$request->setControllerActionName($ajax['action']);
$request->setArguments($ajax['arguments']);
 
 
//$ajaxDispatcher = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('Nng\Nnsubscribe\Controller\EidController');
//echo $ajaxDispatcher->processRequestAction();
 
$response = $objectManager->get('TYPO3\CMS\Extbase\Mvc\ResponseInterface');
$dispatcher = $objectManager->get('TYPO3\CMS\Extbase\Mvc\Dispatcher');
$dispatcher->dispatch($request, $response);
 
echo $response->getContent();

[Typo3 scheduler]: Task failed to execute successfully. You are not allowed to access the given folder (msg#4.0.127)

$
0
0

Problem:
Beim Ausführen von Scheduler-Tasks (Planer) mit Datei-Zugriffen auf das FAL schlägt die Ausführung fehl. Das Protokoll gibt dazu folgende Fehlermeldung:

[scheduler]: Task failed to execute successfully. 
You are not allowed to access the given folder: "..." (msg#4.0.127)

Lösung: Der Benutzer _cli_scheduler braucht noch eine Dateifreigabe auf das angegebene Verzeichnis. Dazu einfach in der Typo3-Root eine entsprechende Verzeichnisfreigabe anlegen (z.B. auf “fileadmin/”) und dem Benutzer _cli_scheduler zuweisen.

Typo3: JSON Beispiel JS, TypoScript, Controller

$
0
0

Hier ein vollständiges Beispiel für einen JSON Dispatcher, der ein JavaScript-Objekt im Frontend als JSON an einen Controller im Backend sendet und dann ein JSON zurück bekommt.

Für Suchmaschinen: JSON von JavaScript in PHP auslesen. JSON per Post an Typo3 Controller Backend senden. method=POST, JSON dispatcher für Typo3. Per JavaScript Objekt aus dem Typo3 Backend laden und parsen.

1. Per TypoScript Setup wird über den page-Type eine neuer Ausgabe-Typ für das JSON definiert:

json_beispiel = PAGE
json_beispiel {
   typeNum = 9901
   config {
      disableAllHeaderCode = 1
      xhtml_cleaning = 0
      admPanel = 0
      additionalHeaders = Content-type: text/plain
      no_cache = 1
      contentObjectExceptionHandler = 0
   }
   10 = USER_INT
   10 {
      userFunc = TYPO3\CMS\Extbase\Core\Bootstrap->run
      extensionName = Beispiel
      pluginName = Beispiel
      vendorName = Vendor
      controller = Controllername
      switchableControllerActions {
         Controllername {
            1 = getJson
         }
      }
   }
}

2. Der Controller nimmt das JSON aus dem Frontend entgegen und sendet ein JSON zurück:

/**
 * JSON im Controller laden
 *
 * @return void
 */
public function getJsonAction () {
 
   $gp = json_decode(file_get_contents('php://input'), true);
 
   // Hier dann was machen...
   $result = ['result'=>'1234'];
   echo json_encode($result, JSON_UNESCAPED_UNICODE);
 
}

3. Und so sieht die Abfrage per JavaScript im Frontend (jQuery) aus:

var url = 'index.php?id=XXX&type=9910';
var data = {beispiel:[10,20,30]};
 
 
$.ajax({
    type: "POST",
    url: url,
    data: JSON.stringify(data),
    success: function (data) {
        func( data );
    },
    error: function (errMsg) {
        alert('Fehler beim Aufruf des Backend.');
    }
});

Typo3: Per JS prüfen, ob fe_user im Frontend eingeloggt ist

$
0
0

Manchmal möchte man im Frontend prüfen, ob die fe_user-Session des Benutzers noch gültig ist und dann automatisch ausloggen. Das ist vor allem beim Single-Page-Applications (SPA) sehr hilfreich.

TypoScript Setup:

plugin.tx_myextension.settings {
   pidLogout = 344
}
 
logincheck = PAGE
logincheck {
 
   typeNum = 7780
   config {
      disableAllHeaderCode = 1
      xhtml_cleaning = 0
      admPanel = 0
      additionalHeaders = Content-type: text/plain
      no_cache = 1
      contentObjectExceptionHandler = 0
   }
 
   10 = COA_INT
   10 {
      20 = FLUIDTEMPLATE
      20.template = TEXT
      20.template.value = "login":{f:security.ifAuthenticated(then:1, else:0)},"redirect":"{f:security.ifAuthenticated(else:'{f:uri.page(pageUid:settings.pidLogout)}')}"
      20.settings < plugin.tx_myextension.settings
      stdWrap.wrap = {|}
   }
}

JavaScript (jQuery). page-id anpassen!

$(function() {
   setInterval( function () {
      $.getJSON('index.php?id=XXX&type=7780').done(function ( data ) {
         if (!data.login) {
            window.location = data.redirect;
         }
      });
   }, 10 * 1000);
});

Eigenes Mail-Template für core form-Extension Typo3 8 tx_form

$
0
0

Kurzanleitung zum Verwenden eigener Mail-Templates für die form-Extension unter Typo3 8 LTS.
Möchte man ein eigenes Mail-Template für die schöne Form-Extension von Typo3 anlegen, helfen ein paar Zeilen Typoscript zusammen mit einer eigenen yaml-Konfiguration.

1. Per TS-Setup einen neuen Pfad für das yaml-setup definieren:

plugin.tx_form {
    settings {
        yamlConfigurations {
            100 = fileadmin/templates/extensions/formframework/setup.yaml
        }
    }
}

2. In der Yaml-Datei (setup.yaml) den Pfad zum Template überschreiben:

TYPO3:
  CMS:
    Form:
      mixins:
        finishersEmailMixin:
          options:
            templatePathAndFilename: 'fileadmin/templates/extensions/formframework/Email/{@format}.html'

3. Template-Datei (hier: fileadmin/templates/extensions/formframework/Email/Html.html) anlegen:

{namespace formvh=TYPO3\CMS\Form\ViewHelpers}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
   <title></title>
   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
   <meta name="format-detection" content="telephone=no">
</head>
<body>
 
   <table width="600" cellpadding="0" cellspacing="0" border="0">
      <formvh:renderAllFormValues renderable="{form.formDefinition}" as="formValue">
         <tr>
            <td width="600" valign="top" align="left">{formvh:translateElementProperty(element: formValue.element, property: 'label')}</td>
            <td width="600" valign="top" align="left">
               <f:if condition="{formValue.value}">
                  <f:then>
                     <f:if condition="{formValue.isMultiValue}">
                        <f:then>
                           <table cellspacing="0" border="0">
                              <f:for each="{formValue.processedValue}" as="value">
                                 <tr>
                                    <td>{value}</td>
                                 </tr>
                              </f:for>
                           </table>
                        </f:then>
                        <f:else>
                           <table cellspacing="0" border="0">
                              <tr>
                                 <td>{formValue.processedValue}</td>
                              </tr>
                           </table>
                        </f:else>
                     </f:if>
                  </f:then>
                  <f:else>
                     -
                  </f:else>
               </f:if>
            </td>
         </tr>
      </formvh:renderAllFormValues>
   </table>
</body>
</html>

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

$
0
0

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.

Basics

Als Erstes erstellen wir eine Extension die alle Templates, Konfigurationsdateien, etc. enthält.

Im Beispiel werden wir diese your_custom_extension nennen.
Beispiel der Ordnerstruktur der Extension:

├── Classes
├── Configuration
│   ├── TypoScript
│   │   ├── constants.txt
│   │   └── setup.txt
│   └── Yaml
│       ├── BaseSetup.yaml
│       └── FormEditorSetup.yaml
├── Documentation
├── Resources
│   ├── Private
│   │   ├── Frontend
│   │   │   └── Partials
│   │   │       └── YourCustomElement.html
│   │   └── Language
│   │       └── Backend.xlf
│   └── Public
│       ├── Icons
│       │   ├── Extension.svg
│       │   └── your_custom_element_icon.svg
│       └── JavaScript
│           └── Backend
│               └── FormEditor
│                   └── YourCustomElementViewModel.js
├── Tests
├── composer.json
├── ext_emconf.php
├── ext_localconf.php
└── ext_typoscript_setup.txt

 

YAML

Da die Konfiguration der Extension in YAML geschrieben wird, wird das ganze wie folgt definiert:

# Configuration/Yaml/BaseSetup.yaml

TYPO3:
  CMS:
    Form:
      prototypes:
        standard:
          formEditor:
            formEditorPartials:
              FormElement-YourCustomElement: 'Stage/SimpleTemplate'

          formElementsDefinition:
            Form:
              renderingOptions:
                templateRootPaths:
                  100: 'EXT:your_custom_extension/Resources/Private/Frontend/Templates/'
                partialRootPaths:
                  100: 'EXT: your_custom_extension/Resources/Private/Frontend/Partials/'
                layoutRootPaths:
                  100: 'EXT: your_custom_extension/Resources/Private/Frontend/Layouts/'

            YourCustomElement:
              __inheritances:
                10: 'TYPO3.CMS.Form.mixins.formElementMixins.YourCustomElementMixin'
      mixins:
        formElementMixins:
          YourCustomElementMixin:
            __inheritances:
              10: 'TYPO3.CMS.Form.mixins.formElementMixins.FormElementMixin'

 

Zu diesem Zeitpunkt geben wir unserem Element ein Template das in der Stage Area des Form-Editors benutzt wird FormElement-YourCustomElement. Weitere Informationen gibt es hier: https://docs.typo3.org/typo3cms/extensions/form/ApiReference/Index.html#stage-simpletemplate

In den meisten Fällen reicht das  Stage/SimpleTemplate aus.

Bei renderingOptions definieren wir unsere Pfade zu Templates, Layouts und / oder Partials, die zum Rendern im Frontend benötigt werden.

Registrieren wir nun unser neues Custom Element unterhalb formElementsDefinition mit dem Namen des Elements. Dieser sollte einzigartig sein, da es von einer anderen Extension ersetzt bzw. überschrieben werden könnte.
In diesem Beispiel erstellen wir einen Custom Mixin für dieses Element, welches von TYPO3.CMS.Form.mixins.formElementMixins.FormElementMixin erbt (mit der Verwendung des Stage/SimpleTemplate reicht dieses Mixin aus). Natürlich können auch andere Mixins verwendet werden.

Nachdem wir unser Frontend definiert haben, kommen wir nun zur Konfiguration des Form Editors:

# Configuration/Yaml/FormEditorSetup.yaml

TYPO3:
  CMS:
    Form:
      prototypes:
        standard:
          formEditor:
            dynamicRequireJsModules:
              additionalViewModelModules:
                - 'TYPO3/CMS/YourCustomExtension/Backend/FormEditor/YourCustomElementViewModel'

            formEditorPartials:
              FormElement-YourCustomElement: 'Stage/SimpleTemplate'

          formElementsDefinition:
            YourCustomElement:
              formEditor:
                label: 'formEditor.elements.YourCustomElement.label'
                group: custom
                groupSorting: 1000
                iconIdentifier: 't3-form-icon-your-custom-element'
      mixins:
        formElementMixins:
          YourCustomElementMixin:
            __inheritances:
              10: 'TYPO3.CMS.Form.mixins.formElementMixins.FormElementMixin'

Die Konfiguration könnte im Gegensatz zur einfachen Konfiguration des Form Editors etwas anders ausssehen. Hier wurden schon einige Einstellungen vorgenommen.
Nehmen wir die wichtigen Zeilen etwas genauer unter die Lupe.

Registriere das Element für das „Neues Element erstellen“ mit diesem Code-Snippet:

formElementsDefinition:
  YourCustomElement:
    formEditor:
      label: 'formEditor.elements.YourCustomElement.label'
      group: custom
      groupSorting: 1000
      iconIdentifier: 't3-form-icon-your-custom-element'
  • Derkey der beim label benutzt wird, ist der Key aus der Sprachdatei
  • group und groupSorting sollten selbsterklärend sein
  • Das Icon iconIdentifier muss mit Hilfe der IconFactory (EXT:/ext_localconf.php) registriert werden und sollte eine SVG-Datei sein

Der schwerste Teil war, herauszufinden, wie man ein Viewmodel für die Stage Area definiert. Dafür gibt es hier ein Code-Snippet, damit in der Stage Area alles einwandfrei angezeigt werden kann (Label des Elements, etc.):

formEditor:
  dynamicRequireJsModules:
    additionalViewModelModules:
      - 'TYPO3/CMS/YourCustomExtension/Backend/FormEditor/YourCustomElementViewModel'

Das verweist auf ein JavaScript Viewmodel innerhalb unserer Extension, welches sämtliche Informationen enthält und das Rendern in der Stage auslöst.

TypoScript

Das war bis hierher sehr viel YAML…..

Damit ext:form es auch erkennt, müssen wir es nun auch registrieren.

Ein Vorschlag wäre  ext_typoscript_setup.txt zu benutzen (ROOT-Level unserer Extension).

# ext_typoscript_setup.txt

module.tx_form {
    settings {
        yamlConfigurations {
            40 = EXT:your_custom_extension/Configuration/Yaml/BaseSetup.yaml
            50 = EXT:your_custom_extension/Configuration/Yaml/FormEditorSetup.yaml
        }
    }
    view {
        partialRootPaths {
            40 = EXT:your_custom_extension/Resources/Private/Backend/Partials/
        }
    }
}

Das hilft uns zwar im Backend, aber das Frontend braucht auch ein paar Definitionen. Dafür benutzen wir  Configuration/TypoScript/setup.txt :

# Configuration/TypoScript/setup.txt

plugin.tx_form {
    settings {
        yamlConfigurations.40 = EXT:your_custom_extension/Configuration/Yaml/BaseSetup.yaml
    }

    view {
        partialRootPaths.100 = EXT:your_custom_extension/Resources/Private/Frontend/Partials/
    }
}

Das war es nun auch für TypoScript.

Sprachdatei

Um die Sprachdatei für das Backend zu überschreiben, müssen wir diese innerhalb von ext_localconf überschreiben:

# ext_localconf.php

// register language file for backend
    $GLOBALS['TYPO3_CONF_VARS']['SYS']['locallangXMLOverride']['EXT:form/Resources/Private/Language/Database.xlf'][] = 'EXT:your_custom_extension/Resources/Private/Language/Backend.xlf'

Hier sollte das Label etc. stehen, wie schon weiter oben erwähnt.

Layout / Template / Partial

Man könnte nun Fluid-Layouts, Templats oder Partials für das Rendering im Frontend benutzen. Wie man diese erstellt, kann man in der Dokumentation nachschauen.

JavaScript

Dieses Code-Snippet ist erforderlich damit eurer Custom Form Element mit allen Features in der „Stage Area“ richtig angezeigt wird.

// Resources/Public/JavaScript/Backend/FormEditor/YourCustomElementViewModel.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') === 'YourCustomElement') {
                    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);
});

Eine Zeile muss hier noch angepasst werden:

if (args[0].get('type') === 'YourCustomElement') { // benutze hier den Namen des Elements
    getFormEditorApp().getViewModel().getStage().renderSimpleTemplateWithValidators(args[0], args[1]);
}



Quelle: GitHub englisches Tutorial

Typo3 tx_form: Eigenes Formularelement erstellen / custom form element

$
0
0

Versuch einer Anleitung für Dummies

(oder Normalsterbliche, die einfach nur einen Job zu erledigen haben)

Vor einigen Tagen haben wir einen Beitrag veröffentlicht, wie man ein die Typo3 Core Extension tx_form um ein eigenes Formularelement erweitern kann.

Die Typo3 Extension tx_form ist zwei Dingen vorbildlich: Der modularen und konsequent objektorientierten Architektur. Und im bisher unerreichten Verwirrungsfaktor für Normalsterbliche. Ich weiß nicht, wie viele Stunden wir im Ordner sysext/form verbracht haben, um zu verstehen, welches mixin von welchem übergeordneten mixin per __inheritances welche Konfigurations-Häppchen erbt.

Genauso unverständlich und eine echte Motivationsbremse ist es für viele Typo3-Entwicklern, dass tx_form auf eine weitere Konfigurationssprache setzt. TypoScript, TCA und FlexForm-XML? Alles alte Hasen, da geht noch einer. Also jetzt noch YAML dazu. Zwei spaces statt tab. Unlesbare Dateien und kaum brauchbare Editoren. Und was die Erweiterbarkeit angeht noch ziemlich buggy. Na dann, lasst uns mal einsteigen.

1. Entscheide Dich für einen Namen

Jedes Formular-Element braucht einen eindeutige Bezeichner / Namen. Entscheide Dich jetzt und notiere den Namen für Dein Formular-Element. Vielleicht möchtest Du ein Formular-Element, mit dem man eine Sternebewertung im Frontend machen kann. Dann nenne Dein Formularelement „Sterne„. Oder man soll ein Emoji wählen können. Dann nenne es „Emoji„.

Nenne es nicht „Checkbox„, „Text„, „DatePicker“ oder irgendetwas anderes, was es vielleicht schon geben könnte.

In diesem Beispiel werden wir es Emoji nennen. Immer, wenn Du ein gelbes Emoji im Quelltext oder Dateinamen siehst, ersetzt Du es mit Deinem eigenen Bezeichner.

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 extname durch den Ordner-Namen Deiner Extension, in der Du arbeitest.
Ersetze das Wort Emoji im Dateinamen durch Deinen Bezeichner.

extname
│
├── Configuration
│   ├── TypoScript
│   │   └── setup.txt
│   └── Yaml
│       └── FormSetup.yaml
├── Resources
│   ├── Private
│   │   └── FormFramework
│   │       └── Partials
│   │           └── Emoji.html
│   └── Public
│       ├── Icons
│       │   └── Emoji-icon.svg
│       └── JavaScript
│           └── Backend
│               └── FormEditor
│                   └── EmojiViewModel.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

Die Zahl 1534503706 durch den aktuellen Timestamp ersetzen. Den Extension-Namen extname durch den Namen des Extension-Ordners ersetzen.


# Einstellungen für das Frontend
plugin.tx_form.settings.yamlConfigurations {
   1534503706 = EXT:extname/Configuration/Yaml/FormSetup.yaml
}
# Einstellungen für das Backend
module.tx_form.settings.yamlConfigurations {
   1534503706 = EXT:extname/Configuration/Yaml/FormSetup.yaml
}

Configuration/Yaml/FormSetup.yaml

Das Emoji im Code durch Deinen Bezeichner ersetzen (s. Schritt 1).
Den Extension-Namen Extname durch den Namen des Extension-Ordners ersetzen, aber mit großem Anfangsbuchstaben bzw. upperCamelCase-Schreibweise!.
Den Extension-Namen extname durch den Namen des Extension-Ordners ersetzen, aber mit kleinem Anfangsbuchstaben!.
Wenn Du mehrere Extension hast, die Formularfelder einfügen, dann muss die 125 im Quelltext eindeutig sein. Auch hier könntest Du einfach den aktuellen Timestamp verwenden.


TYPO3:
  CMS:
    Form:
      prototypes:
        standard:

          # -----------------------------------------------------------------------------------
          # Darstellung des Formularelementes im Backend:
          # In der Übersicht / Listenansicht, mittlere Spalte

          formEditor:

            # Für Darstellung im Backend: JS-Dateien/Module registrieren, die per requireJS
            # eingebunden werden. tx_form sucht in genau diesem Pfad nach den JS-Dateien:
            # 'EXT:..../Resources/Public/JavaScript/Backend/FormEditor/......js 
            dynamicRequireJsModules:
              additionalViewModelModules:
                - 'TYPO3/CMS/Extname/Backend/FormEditor/EmojiViewmodel'
            
            # Für Darstellung im Backend: Welches Fluid-Template verwenden?
            # Hier einfach das Standard-Template von tx_core
            formEditorPartials:
              FormElement-Emoji: 'Stage/SimpleTemplate'

          
          formElementsDefinition:

            # ---------------------------------------------------------
            # Für Ausgabe im Frontend: Zusätzliche Pfade, die für Rendern des Feldes
            # durchsucht werden sollen. Der numerische Key muss eindeutig sein 

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

            # ---------------------------------------------------------
            # Darstellung der Formularfelder im Backend
            # Detailansicht mit Formularfeldern in der rechten Spalte
                  
            Emoji:
            
              # Erbt die Standard-Darstellung und Felder, z.B. "Label" und "Description"
              # siehe SYSEXT:form/Configuration/Yaml/FormEditorSetup.yaml
              __inheritances:
                10: 'TYPO3.CMS.Form.mixins.formElementMixins.FormElementMixin'

              # Überschrift (erscheint als Titel in Übersicht und über dem Formular)
              formEditor:
                label: 'Dein Formularelement'
                group: custom
                groupSorting: 1010

                # Dieses Icon wird in der ext_localconf.php registriert
                iconIdentifier: 'Emoji-icon'
                
                # Defaults für die Formularfelder
                predefinedDefaults:
                  properties:
                    test: ''

                # Hier können eigene Formularfelder definiert werden
                editors:
                  # 200 wurde von FormElementMixin geerbt und enhält das Feld "Label"
                  # 230 wurde von auch geerbt und enhält das Feld "Description"
                  # 700 enthält die Angaben für Spaltenbreiten xs, sm, ... beim Einfügen in ein Row-Element
                  # 800 ist die required-Checkbox (Pflichtfeld)
                  300:
                    identifier: 'test'
                    templateName: 'Inspector-TextEditor'
                    label: 'Test'
                    propertyPath: 'properties.test'

Resources/Private/FormFramework/Partials/Emoji.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/Emoji-icon.svg

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


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


// Resources/Public/JavaScript/Backend/FormEditor/EmojiViewmodel.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') === 'Emoji') {
                    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(
        't3-form-Emoji-icon',
        \TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider::class,
        ['source' => 'EXT:extname/Resources/Public/Icons/Emoji-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:extname/Configuration/Typoscript/setup.txt">

Installation Typo3 unter AMPPS

$
0
0

Spickzettel für verschiedene Problem, die bei der Installation von Typo3 8 unter AMPPS (Mac OSX El Capitan) mit PHP 7.1 entstanden sind. Als SMTP-Server diente ein externer Server bei HostEurope, der als SMTP-Zieladresse für die lokale postfix Konfiguration angegeben wurde.


PDF / AI Konvertierung zu PNG/JPG funktioniert nicht

Wenn im Install-Tool keine Vorschau-Bilder (Thumbnails) für PDF- oder AI-Dateien generiert werden, könnte der Grund das Fehlen von ImageMagick oder Ghostscript sein. Oder der Pfad zu Ghostscript wird in ImageMagick nicht gefunden. Leider gibt sich Typo3 hier sehr bedeckt, was die genaue Fehlerursache ist.

Lösungen:
1. Per Terminal mit HomeBrew ImageMagick und Ghostscript neu installieren. Danach testen – Neustart des Servers ist nicht erforderlich.

brew update && brew reinstall ghostscript && brew reinstall imagemagick --with-ghostscript

2. Kein Erfolg? Bei ImageMagick 6 muss evtl. die policy.xml angepasst werden. Wieder direkt testen – Neustart des Servers ist nicht erforderlich.

sudo nano /etc/ImageMagick-6/policy.xml

Diese Zeile auskommentieren:


Diese ändern:


Diese am Ende einfügen:


3. Hartnäckiges Problem? Die delegates.xml von ImageMagick suchen. Befindet sich z.B. unter /usr/local/Cellar/imagemagick/7.0.8-12/etc/ImageMagick-7/delegates.xml oder /usr/local/etc/ImageMagick-7/delegates.xml. Dort nach dem Aufruf von „gs“ suchen: &quot;gs&quot; im XML durch den absoluten Pfad zu „gs“ ersetzen: &quot;/usr/local/bin/gs&quot;. Der Pfad kann im Termin durch diese Eingabe ermittelt werden:

which gs

4. Immer noch kein Erfolg? Mit einem kurzen PHP-Script prüfen, ob identify einen Fehler meldet. Danach dann gezielt Google befragen:

&1", $result, $return);
  print_r($result);
  print_r($data);

TER Typo3 Repository: Update nicht möglich

Beim Versuch, über den Extension Manager die Liste der Typo3 Extensions aus dem TER (Typo3 Extension Repository) zu aktualisieren erscheint die Fehlermeldung „Aktualisieren der Erweiterungsliste: Could not access remote resource https://repositories.typo3.org/mirrors.xml.gz“.
Grund dafür war hier leider nicht eine einfache und in vielen Foren beschriebene Fehlkonfiguration von PHP (z.B. fehlendes PHP curl-Modul, allow_url_open = 0/Off oder allow_url_include = Off), sondern eine Änderung des Sicherheitsstandards bei OpenSSL und cURL.

Lösung:
1. Per Terminal mit HomeBrew OpenSSL installieren

brew install openssl

2. In der php.ini diese Zeile am Ende einfügen (Pfad evtl. anpassen)

openssl.cafile=/usr/local/etc/openssl/cert.pem

3. In der php.ini darauf achten, dass diese Zeilen nicht auskommentiert sind und existieren:

extension=curl.so
extension=openssl.so

4. Die cacert.pem von https://curl.haxx.se/docs/caextract.html downloaden und in ein Verzeichnis spielen, dass von PHP erreicht werden kann. Im Beispiel habe ich es unter /Applications/AMPPS/php-5.6/etc/ abgelegt. Dann am Ende der php.ini diese Zeile einfügen:

curl.cainfo = /Applications/AMPPS/php-5.6/etc/cacert.pem

5. Apache neu starten (direkt über das AMPPS Interface)


Scheduler/Crobjob unter AMPPS einrichten

Um den Scheduler (Planer) unter AMPPS zum Laufen zu bekommen, nutzt man am einfachsten das kostenlose Tool Cronnix. Dort muss zur Ausführung der richtige Pfad angegeben werden – sowohl zur PHP als auch dem Scheduler-Skript, z.B.

/Applications/AMPPS/php/bin/php /Pfad/Zum/Projekt/typo3/cli_dispatch.phpsh scheduler

Mailversand über PHP mail() funktioniert nicht

Typo3 versendet keine Mails. Dazu gibt es zwei mögliche Lösungsansätze.
Falls es nur um Formhandler geht, diesen Beitrag lesen.
Einfacher Test, um zu prüfen, ob der mail()-Befehl funktioniert:

' . "\r\n" .
		'Reply-To: ' . $empfaenger . "\r\n" .
		'X-Mailer: PHP/' . phpversion();

	$status = mail($empfaenger, $betreff, $nachricht, $header, "-f".$empfaenger);
	echo $status ? "Mail versendet." : "Mail konnte nicht gesendet werden.";
?>

Erste Lösung: SMTP für Versand nutzen

In der LocalConfiguration.php den Abschnitt „MAIL“ mit einem externen SMTP-Server bestücken:

'MAIL' => [
     'transport' => 'smtp',
     'transport_smtp_password' => 'xxxxxxxxxxxx',
     'transport_smtp_server' => 'mail.xxxxxxxxxx.de:25',
     'transport_smtp_username' => 'wp-xxxxxxxxxx',
 ],

Zweite Lösung: postfix für den Versand konfigurieren

Diese Lösung behebt das Problem an der Wurzel und konfiguriert den bei Mac vorinstallierten postfix/sendmail zum Versand der Mails über einen externen SMTP-Dienst. In diesem Beispiel nutzen wir einen Mailserver bei HostEurope (Webpack, Virtual Server etc.). Die Zugangsdaten entsprechen den identischen Daten, die auch im Programm Mac „Mail“ eingegeben werden.

1. Die Datei /etc/postfix/master.cf bearbeiten und folgenden Zeilen am Ende ergänzen.
Unter relayhost den HostEurope MailServer eintragen.

relayhost=mail.deineDomain.de:25
smtp_sasl_auth_enable=yes
smtp_sasl_password_maps=hash:/etc/postfix/sasl_passwd
smtp_use_tls=yes
smtp_tls_security_level=encrypt
smtp_sasl_security_options =

2. In dem Verzeichnis /etc/postfix/ eine Datei sasl_passwd anlegen und folgenden Inhalt einfügen.
deineDomain, wpXXXXXX-user und passwort durch Deine Mail-Zugangsdaten beim Host ersetzen.

mail.deineDomain.de	wpXXXXXXX-user:passwort

3. Im Terminal nacheinander folgende Kommandos ausführen:

sudo postmap /etc/postfix/sasl_passwd
sudo postfix stop && sudo postfix start
echo "Dies ist eine Testmail" | mailx -s "Test" deine@adresse.de

Danach sollte eine Mail versendet werden. Falls nicht, lässt sich der Status des lokalen Mail-Queues mit folgender Eingabe prüfen:

mailq

Um den Mail-Versand in einer Textdatei zu loggen, richte ich gerne noch ein Logfile ein. Diese Anpassungen kommt in die php.ini von AMPPS. Der Benutzername „99grad“ muss natürlich angepasst werden:

mail.log = /Users/99grad/Desktop/mail.log

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

$
0
0

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.

Mit wenigen Zeilen Script bekommt man das Löschen der autoload-Datei auch über den Typo3 „Cache leeren“ Blitz im Backend gelöst:

In die Datei ext_localconf.php der eigenen Extension einen Hook registrieren, der beim Aufruf des „Cache leeren“ ausgeführt wird:

$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['clearCachePostProc'][] = 'Deine\Extension\Hooks\ClearCacheHook->clearAutoloadCache';

Die Datei Classes/Hooks/ClearCacheHook.php anlegen mit diesem Code:

<php
namespace Deine\Extension\Hooks;

use TYPO3\CMS\Core\Core\ClassLoadingInformation;

class ClearCacheHook {

    /**
     * Löscht die autoload-Dateien, wenn der Typo3-Blitz
     * geklickt wird.
     *     
     * @param array $params
     */
   public function clearAutoloadCache ( array $params ) {
      ClassLoadingInformation::dumpClassLoadingInformation();
   }
   
}

Und dann? Naja… dann eben (leider) noch ein Mal – zum letzten Mal – im Install-Tool den „dump autoload“ machen.

Für Suchmaschinen: rebuild typo3 autoload cache using typo3 lightning-Button. Typo3 Cache für Klassen-Namen per Klick auf Typo3-Blitz löschen. Über Typo3 „Alle caches leeren“ auch autoload-Datei neu aufbauen. Autoload-Dateien werden nicht gelöscht, wenn Cache geleert wird. Wie autoload-Datei in Typo3 neu aufbauen. Eigene Classes in Typo3 registrieren. Register custom php Classes in Typo3. Extension classes are not loaded after clearing cache.

Viewing all 20 articles
Browse latest View live