Beiträge von npostnik

TYPO3: ViewHelper für Frontend-Links aus Scheduler-Tasks

Vor ein paar Monaten habe ich bereits darüber geschrieben, wie man aus z.B. einem Task, der E-Mails versendet, TYPO3 konform Links ins Frontend generieren kann. Nun habe ich das ganze in einen ViewHelper ausgelagert, damit man noch eleganter Links in Standalone-Templates generieren kann.

Hinwein: ich musste den Vendor und den Extensionnamen ändern, daher ist das nicht der tatsächlich funktionierende Code. Wenn es in der eigenen Extension nicht auf Anhieb klappt, dann Vendor und Extensionname anpassen.

Aufruf im Mail-Template:

{namespace my = My\Extension\ViewHelper}
[...]
<p><my:fe.link pageUid="{targetPageUid}" pluginName="Event" pluginArguments="{event: event}">zur Webseite mit Parameter</my:fe.link></p>
[...]

Und das ist der ViewHelper, abzulegen in ViewHelper/Fe/LinkViewHelper.php:

<?php
<?php
namespace My\Extension\ViewHelper\Fe;
 
class LinkViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractTagBasedViewHelper {
 
	/**
	 * @var string
	 */
	protected $tagName = 'a';
 
	/**
	 * Arguments initialization
	 *
	 * @return void
	 */
	public function initializeArguments() {
		$this->registerUniversalTagAttributes();
		$this->registerTagAttribute('name', 'string', 'Specifies the name of an anchor');
		$this->registerTagAttribute('rel', 'string', 'Specifies the relationship between the current document and the linked document');
		$this->registerTagAttribute('rev', 'string', 'Specifies the relationship between the linked document and the current document');
		$this->registerTagAttribute('target', 'string', 'Specifies where to open the linked document');
	}
 
	/**
	 * @param int $pageUid
	 * @param string $pluginName
	 * @param array $pluginArguments
	 * @return string content
	 */
	public function render($pageUid, $pluginName = NULL, $pluginArguments = NULL) {
		$this->initTSFE();
		$cObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\ContentObject\\ContentObjectRenderer');
 
		$additionalParams = '';
		if(isset($pluginArguments) && is_array($pluginArguments) && isset($pluginName)) {
			foreach($pluginArguments as $key => $value) {
 
				$namespace = \TYPO3\CMS\Core\Utility\GeneralUtility::camelCaseToLowerCaseUnderscored($pluginName);
				if($value instanceof \TYPO3\CMS\Extbase\DomainObject\AbstractDomainObject) {
					if ($value->getUid() !== NULL) {
						$additionalParams.= '&tx_extension_'.$namespace.'['.$key.']='.$value->getUid();
					}
				} else {
					$additionalParams.= '&tx_extension_'.$namespace.'['.$key.']='.$value;
				}
			}
		}
 
		$uri = $cObj->typolink_URL(array('parameter' => $pageUid, 'additionalParams' => $additionalParams, 'forceAbsoluteUrl' => 1));
 
		$this->tag->addAttribute('href', $uri, FALSE);
		$this->tag->setContent($this->renderChildren());
		$this->tag->forceClosingTag(TRUE);
		return $this->tag->render();
	}
 
	protected function initTSFE($id = 1, $typeNum = 0) {
		\TYPO3\CMS\Frontend\Utility\EidUtility::initTCA();
		if (!is_object($GLOBALS['TT'])) {
			$GLOBALS['TT'] = new \TYPO3\CMS\Core\TimeTracker\NullTimeTracker;
			$GLOBALS['TT']->start();
		}
		$GLOBALS['TSFE'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\Controller\\TypoScriptFrontendController',  
			$GLOBALS['TYPO3_CONF_VARS'], $id, $typeNum);
		$GLOBALS['TSFE']->connectToDB();
		$GLOBALS['TSFE']->initFEuser();
		$GLOBALS['TSFE']->determineId();
		$GLOBALS['TSFE']->initTemplate();
		$GLOBALS['TSFE']->getConfigArray();
 
		if (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('realurl')) {
			$rootline = \TYPO3\CMS\Backend\Utility\BackendUtility::BEgetRootLine($id);
			$host = \TYPO3\CMS\Backend\Utility\BackendUtility::firstDomainRecord($rootline);
			$_SERVER['HTTP_HOST'] = $host;
		}
	}
}
?>

Geschrieben in TYPO3 | Kommentare deaktiviert für TYPO3: ViewHelper für Frontend-Links aus Scheduler-Tasks

Datum in Sublime umformatieren

Für ein Projekt brauchte ich ein paar Demo-User, die ich mir mit dem Fake Name Generator habe erstellen lassen. Das Format für Geburtsdatum in der Datei ist dd/mm/yyyy, meine Datenbank erfordert aber yyyy-mm-dd. Da ich mit Sublime entwickele und es dort die Möglichkeit gibt, Suchen und Ersetzen auch mit regulären Ausdrücken durchzuführen, kann man es so machen.

Suchen und Ersetzen, dann RegEx aktivieren.
Find What: (\d{1,2})/(\d{1,2})/(\d{4})
Replace With: ${3}-${2}-${1}

Geschrieben in default | Kommentare deaktiviert für Datum in Sublime umformatieren

Erfolgserlebnis

Nach jahrelanger Arbeit mit TYPO3 habe ich heute endlich verstanden, wie die Syntax für die Types und Palettendefinition im TCA sich zusammensetzt. Das tolle an TYPO3 ist, dass man das Backend sehr gut customizen kann. Man kann Felder beliebig anornden, gruppieren, umbenennen etc. Natürlich habe ich schonmal Formulare für neue Backend-Elemente konfiguriert, aber bisher meist das TCA vom Extension Builder erstellen lassen und dann nur noch geringfügig angepasst. Heute habe ich endlich verstanden, wie man Paletten unabhängig von Feldern definieren kann:
Das in types: --palette--;Datum;dates
Und das in palettes: 'dates' => array('showitem' => 'begin_date, begin_time, --linebreak--, end_date, end_time', 'canNotCollapse' => '1'),
Wie man Tabs definiert, wusste ich vorher auch schon
--div--;Registrierung, registration_date
Heute hats nochmal richtig Klick gemacht – nun steht absolut umwerfenden Backend-Formularen nichts mehr im Weg.

TYPO3: Edit-Links im eigenen Backend-Modul

In TYPO3 gibt existieren ja bereits einige Möglichkeiten, um Datensätze zu bearbeiten oder zu löschen. Manchmal reichen die normalen Ansichten nicht aus und man entwickelt ein Backend-Modul. Um nicht alle Formulare zum bearbeiten und erstellen von Datensätzen (inkl. Validierung!) neu zu implementieren, gibt es eine Möglichkeit aus dem eigenen Backend-Modul links zu den „normalen“ Funktionen in TYPO3 zu setzen. So habe ich z.B. eine Reihe von Veranstaltungen, die ich in meinem Backend-Modul anzeigen möchte. Sobald der Datensatz einer Veranstaltung bearbeitet werden soll, reichen mir für die Bearbeitung die TYPO3-Bordmittel.

Ein bisschen Suche hat ergeben, dass es eine solche Möglichkeit natürlich gibt – Artikel auf docs.typo3.org. Die Vorgehensweise ist folgende: man schreibt einen ViewHelper, der die Links generiert. Der Code für den ViewHelper ist auf der verlinkten Seite aber unvollständig: es gibt eine Extension namens „examples“, die sich über den Extension Manager installieren lässt und in der Datei \Documentation\Examples\ViewHelpers\Be\EditLinkViewHelper.php den Code des kompletten ViewHelpers enthält.

Wenn man die Extension „examples“ installiert und testet, dann stellt man schnell fest, dass sie buggy ist. Der Link an sich funktioniert, aber der Link zurück liefert den Fehler „invalid form/module token“. Außerdem ist es eigentlich nicht schön, dass man die returnUrl im Template setzen muss, meistens will man ja nur dahin zurück, wo man hergekommen ist. Also habe ich den ViewHelper angepasst: Die ReturnUrl wird automatisch gesetzt und das moduleToken ebenfalls.

public function render($parameters, $returnUrl = '') {
	$uri = 'alt_doc.php?' . $parameters;
	if (!empty($returnUrl)) {
		$uri .= '&returnUrl=' . rawurlencode($returnUrl);
	} else {
		$returnUrl = 'mod.php?M='.$_GET['M'].'&moduleToken='.$_GET['moduleToken'];
		$uri .= '&returnUrl=' . rawurlencode($returnUrl);
	}
 
	$this->tag->addAttribute('href', $uri);
	$this->tag->setContent($this->renderChildren());
	$this->tag->forceClosingTag(TRUE);
	return $this->tag->render();
}

Geschrieben in TYPO3 | Kommentare deaktiviert für TYPO3: Edit-Links im eigenen Backend-Modul

TYPO3: Frontend Links aus Backend Modul

Aus einem Task sollen Links zu Seiten generiert und per E-Mail verschickt werden. Wenn man den Fluid ViewHelper verwendet, dann werden Links ins Backend generiert. Es ist in dem Fall nicht das gewünschte Verhalten, aber sinnvoll. Sehr viel habe ich leider nicht dazu gefunden: einem Beitrag auf wissen.netzhaut.de und einen Beitrag im Forum auf typo3.net, der sich auf den Artikel vorher bezieht. Der Artikel auf netzhaut.de enthält noch die alten Klassennamen, diese müssen daher auf Namespaces angepasst werden. Weiterhin habe ich die Funktion umbenannt und noch ein paar Dinge verschönert. In meinem Fall nutze ich den Code in einem Scheduler-Task. Das ist meine Lösung:

class SendReminderTask extends \TYPO3\CMS\Scheduler\Task\AbstractTask {
	public function execute() {
		[...]
 
		$this->initFrontend();
 
		foreach($documents as $document) {
			[...]
 
			$cObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\ContentObject\\ContentObjectRenderer');
			$linkConf = array(
				'parameter' => $this->extConf['targetPageUid'],
				'forceAbsoluteUrl' => 1,
				'additionalParams' => \TYPO3\CMS\Core\Utility\GeneralUtility::implodeArrayForUrl(NULL, array(
					'tx_myextension[action]' => 'extend',
					'tx_myextension[document]' => $document->getUid(),
					'tx_myextension[hash]' => $document->getHash(),
				)),
				'linkAccessRestrictedPages' => 1
			);
			$link = $cObj->typolink_URL($linkConf);
 
			[...]
		}
 
		return TRUE;
	}
 
	/*
	 * init frontnend to render frontend links in task
	 */
	protected function initFrontend() {
		$id = 1;
		$type = 0;
		if (!is_object($GLOBALS['TT'])) {
			$GLOBALS['TT'] = new \TYPO3\CMS\Core\TimeTracker\TimeTracker;
			$GLOBALS['TT']->start();
		}
		$GLOBALS['TSFE'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\Controller\\TypoScriptFrontendController',  $GLOBALS['TYPO3_CONF_VARS'], $id, $typeNum);
		$GLOBALS['TSFE']->connectToDB();
		$GLOBALS['TSFE']->initFEuser();
		$GLOBALS['TSFE']->determineId();
		$GLOBALS['TSFE']->initTemplate();
		$GLOBALS['TSFE']->getConfigArray();
 
		if (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('realurl')) {
			$rootline = \TYPO3\CMS\Backend\Utility\BackendUtility::BEgetRootLine($id);
			$host = \TYPO3\CMS\Backend\Utility\BackendUtility::firstDomainRecord($rootline);
			$_SERVER['HTTP_HOST'] = $host;
		}
	}
}

Geschrieben in TYPO3 | Kommentare deaktiviert für TYPO3: Frontend Links aus Backend Modul

TYPO3: feine kleine Unterschiede bzgl. TCA und FAL

Für eine neue Extension erstellte ich mit dem Extension-Builder einen Datentyp, in dem Dateien referenziert werden. Die verwendete TYPO3 Version ist die aktuellste, also 6.2.11. Folgendes TCA wurde mir für das Feld generiert:

[...]
'file' => array(
	'exclude' => 1,
	'label' => 'LLL:EXT:nocdocuments/Resources/Private/Language/locallang_db.xlf:tx_nocdocuments_domain_model_document.file',
	'config' => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getFileFieldTCAConfig(
		'file',
		array('maxitems' => 1),
		'*'
	),
),
[...]

Im Backend wird das Feld anzeigt, ich kann eine Datei auswählen, die sofort in der Vorschau erscheint, dann speichere ich… und die Dateireferenz ist weg. Ein Blick in die Datenbank: In der Tabelle sys_file_refence wird eine Zeile eingetragen, aber dann scheinbar gleich wieder gelöscht, uid_foreign ist 0, die meisten anderen Felder leer. Komisch. Die Konfiguration sieht ja richtig aus. Vielleicht liegt es ja an der TYPO3 Version. Also kopierte ich die Extension in eine andere TYPO3-Instanz (6.2.4). Wenn ich dort den Dialog zur Dateiauswahl aufrufe, dann bekomme ich keine Dateien zur Auswahl, obwohl im Ordner ja einige drin sind. Habe mir den Funktionsaufruf angeschaut von getFileFieldTCAConfig, dort ist der Default-Wert für $allowedFileExtensions “. Also ersetzte ich ‚*‘ durch “, und siehe da es klappt.

Der feine kleine Unterschied: wenn $allowedFileExtensions nicht gültig ist, kann man in TYPO3 6.2.11 eine Datei auswählen, die Referenz wird gespeichert und dann direkt gelöscht. Unter TYPO3 6.2.4 kann ich die Datei mit der falschen Dateiendung gar nicht erst auswählen.

Geschrieben in TYPO3 | Kommentare deaktiviert für TYPO3: feine kleine Unterschiede bzgl. TCA und FAL

Aktuelles Jahr mit Fluid ausgeben

Bisher habe ich immer den TypoScript-Weg verwendet, um immer die aktuelle Jahreszahl im Footer auszugeben.

lib.copyright = TEXT
lib.copyright {
	data = date:U
	strftime = %Y
	noTrimWrap = |© Natalia Postnikova ||
}

Viel eleganter ist es jedoch mit Fluid direkt im Template:

&copy; Copyright <f:format.date format="Y">now</f:format.date> by Natalia Postnikova

Geschrieben in TYPO3 | Kommentare deaktiviert für Aktuelles Jahr mit Fluid ausgeben

DCE: FAL Bilder mit Link

Wenn man im DCE Eingabetyp Bild auswählt, dann wird automatisch ein FlexForm generiert. Bald fällt aber auf, dass bei der Eingabe des Bildes die Felder Link und alternativer Text fehlen. Das kann schnell korrigiert werden, wenn man folgenden Schnipsel in das generierte XML in der Konfiguration des entsprechenden DCE-Feldes eingibt:

<config>
	[...]
	<foreign_types type="array">
		<numIndex index="2" type="array">
			<showitem>--palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette,--palette--;;filePalette</showitem>
		</numIndex>
	</foreign_types>
	[...]
</config>

Die Lösung und die Erklärung fand sich in den Mailinglisten. Entscheidend bei dem Schnipsel ist numIndex=“2″:

Index 2 = \TYPO3\CMS\Core\Resource\File::FILETYPE_IMAGE

Geschrieben in TYPO3 | Kommentare deaktiviert für DCE: FAL Bilder mit Link

Felder im Flexform mit TypoScript ausblenden

Es ist möglich, Felder in Backend-Formularen mit TypoScript im PageTSconfig zu konfigurieren. So können Felder umbenannt und ausgeblendet werden. Natürlich erwartet man dann ja auch, dass es genauso für Felder im FlexForm des Plugins gilt. Und TYPO3 enttäuscht mich nicht – es geht. Dieser Beitrag auf jweiland beschreibt wie. Nun wollte ich einige Felder im Flexform der Extension news ausblenden. Das folgende TypoScript ost eigentlich richtig, funktioniert aber nicht:

TCEFORM.tt_content.pi_flexform.news_pi1.additional {
	settings.tags.disabled = 1
	settings.topNewsFirst.disabled = 1
	settings.excludeAlreadyDisplayedNews.disabled = 1
	settings.disableOverrideDemand.disabled = 1
}

Wenn man etwas darüber nachdenkt, ist es ja auch logisch: In TypoScript gilt der Punkt als Trenner, somit bezieht sich das disabled nicht auf settings.tags sondern auf tags, das ein Unterobjekt von settings ist. Und das existiert natürlich nicht. Zum Glück ist es schon vor einiger Zeit ein paar Leuten aufgefallen und es gab einen Bug-Report dazu. Die Lösung: man kann Punkte, die Teil der Felddeklaration sind in TypoScript mit einem Backslash escapen. Somit sieht die funktionierende Konfiguration so aus:

TCEFORM.tt_content.pi_flexform.news_pi1.additional {
	settings\.tags.disabled = 1
	settings\.topNewsFirst.disabled = 1
	settings\.excludeAlreadyDisplayedNews.disabled = 1
	settings\.disableOverrideDemand.disabled = 1
}

Geschrieben in TYPO3 | Kommentare deaktiviert für Felder im Flexform mit TypoScript ausblenden