Typo3 eID Dispatcher für Typo3 ab 7.6

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:

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 Backend-User (if logged in)
 */
$GLOBALS['BE_USER'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Core\Authentication\BackendUserAuthentication');
$GLOBALS['BE_USER']->start();

/**
 * 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 PowerMail Finisher Beispiel

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 Button „Dateien auswählen und hochladen“ fehlt im Backend bei Redakteuren

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 bootstrap_grids Header rendern

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: TCA Default-Werte dynamisch setzen, per TSConfig oder Script

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

Hier ein Beispiel, wie die Extension tx_news für eine Jobbörse „mißbraucht“ werden kann: In einem bestimmten Ast des Seitenbaums (pid = 118) werden verschiedene Labels für den News-Datensatz geändert bzw. ausgeblendet, um für den Redakteur eine möglichst klare Darstellung zu erreichen. Dieses Script muss in die page TSconfig:

[PIDinRootline = 118]
   TCEFORM.tx_news_domain_model_news {
      title.label = Stellenname
      teaser.label = Arbeitgeber und Ort
      istopnews.disabled = 1
      author.disabled = 1
      author_email.disabled = 1
      datetime.disabled = 1
      archive.disabled = 1
   }
   TCAdefaults.tx_news_domain_model_news {
      type = 2
   }
[global]

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_tables.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.


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;
         }
      }
   }
   
      
}

Grunt auf Mac installieren

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 hreflang-Metatag per TypoScript erstellen

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 = 
            }
            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 = ||  || || || || || || || ||
               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
            }
         }
      }
   }
}

Typo3 DCE – Dynamic Content Elements – Spickzettel


Ü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:



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

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 page / pages_language_overlay um eigenes Feld erweitern, mit slide per TypoScript vererben

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
    }
}