Beiträge der Kategorie TYPO3

Foundation Block-Grid mit Gridelements

Ich mag Foundation, unter anderem weil ich das Block Grid so toll finde. Und so kann man mit Gridelements ein Block-Grid im Frontend (mit einer hübschen Backend-Ausgabe) realisieren.

Zunächst man braucht man ein Gridelement mit nur einer Content-Spalte. Da schmeißt man dann alle Inhaltselemente rein und sie werden automatisch in Spalten ausgegeben. In diesem Fall hab ich das Gridelement in einer Datei konfiguriert.

tx_gridelements.setup.blockgrid {
	title = Blocks
	description = Inhalte automatisch auf mehrere Spalten verteilen
	icon = EXT:my_extension/Resources/Public/Icons/columns-3.png
	flexformDS = FILE:EXT:my_extension/Configuration/FlexForms/Gridelements/Blockgrid.xml
	config {
		colCount = 1
		rowCount = 1
		rows {
			1 {
				columns {
					1 {
						name = Inhalt
						colPos = 55
					}
				}
			}
		}
	}
}

Im Flexform habe ich zwei Felder konfiguriert – large, medium und small. Darin gibt man die Anzahl der Elemente für die jeweilige Auflösung an. Default sind es 3 Large, 2 Medium und 1 Small.

Die Ausgabe erfolgt durch ein Fluid-Template. Wie die Konfiguration dazu aussieht, findet man schnell im Internet – einfach nach „gridelements fluid“ suchen. Damit ich keinen eigenen ViewHelper schreiben muss, um auf variable Array-Indizes zuzugreifen, habe ich Vhs verwendet. Jedes Content-Element aus der Spalte wird in <div class="column"></div> gewrappt.

{namespace v=FluidTYPO3\Vhs\ViewHelpers}
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
      xmlns:ce="http://typo3.org/ns/TYPO3/CMS/FluidStyledContent/ViewHelpers" data-namespace-typo3-fluid="true">
<div class="row small-up-{data.flexform_large} medium-up-{data.flexform_medium} large-up-{data.flexform_large}">
    <f:for each="{data.tx_gridelements_view_children}" as="content">
        <div class="column">
            <f:format.raw>
                <v:variable.get name="data.tx_gridelements_view_child_{content.uid}" />
            </f:format.raw>
        </div>
    </f:for>
</div>
</html>

So weit passt schonmal das Frontend. Im Backend kann man ein wenig mit CSS tricksen. Ich habe bewusst als colPos 55 gewählt. Diese Zahl wird ins Template reingeschrieben, und macht es so möglich, ein spezielles CSS darauf anzuwenden. Man definiert also ein Backend CSS und schreibt da folgendes rein (Scss):

.t3-page-ce-wrapper[data-colpos='55'] {
  .t3-page-ce[data-uid] {
    width: 46%;
    float: left;
 
    &:nth-child(2n) {
      clear: both;
    }
  }
}

Damit werden die Content Element im Backend in zwei Spalten dargestellt. Theoretisch kann man da auch Breakpoints definieren, der Phantasie sind keine Grenzen gesetzt.

So was wie MenuItemProcFunc in Content Element „Menü“ mit Fluid Styled Content

Früher, in den Zeiten von css_styled_content konnte man in das Inhaltselement „Menü“ mittels itemArrayProcFunc eigene Menü-Items einhängen. Das funktioniert nach wie vor mit HMENU und sieht so aus:

1 = TMENU
1 [...]
2 < .1
2 {
	wrap = <ul>|</ul>
	itemArrayProcFunc = My\Extension\Hooks\MenuItemArrayProcessor->process
}

In der Funktion kann man dann z.B. Items aus der eigenen Extension ins Menü hängen, damit es so aussieht als wären es Seiten.

Das hat mit css_styled_content gut funktioniert, da dort das Rendering des Inhaltselemente (unter anderem Menü) ebenfalls mit TypoScript gemacht wurde. Also wenn man den TypoScriptObjectBrowser richtig bedienen kann, dann findet man auch schnell raus, wo man den Code einsetzen muss.

Nun stand ich vor einem Problem (nein, falsch – Herausforderung). In fluid_styled_content ist das Rendering der Content Element komplett über Fluid. So gibt es z.B. einen ViewHelper, der für „Menü ausgewählter Seiten“ die Seiten holt. Die Ausgabe geschieht dann mit Fluid. Nix TypoScript!

Ich habe folgendes implementiert: Falls eine bestimmte Seiten-ID in der Liste vorkommt (es ist meine Ziel-Detailseite), dann schmeiss ich einen weiteren ViewHelper an, der mit die Items mit Titel und Parameter ermittelt. Das Rendering dann wieder mit Fluid.

(mehr …)

Manuelle Sortierung für „Menü ausgewähler Seiten“

Falls man eine Liste von Seiten mit dem Content Element Menü ausgewählter Seiten (Menu of selected pages), werden die Seiten im Moment in TYPO3 7.6.11. automatisch nach ID sortiert und nicht wie erwartet nach der angegebenen Sortierung im Backend. Ich habe dazu im nur einen Bug-Tracker-Eintrag gefunden, aber es gibt offensichtlich noch keinen Patch. Da es für mich nicht in Frage kommt, am Core Code Änderungen vorzunehmen, habe ich es mit einem ViewHelper gelöst.

Das ist der ViewHelper:

class SortPageMenuViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper {
 
    /**
     * @param array $order
     * @param array $pages
     * @param string $variableName
     */
    public function render($order, $pages, $variableName = 'pages')
    {
        $pagesSorted = array();
        foreach($order as $pageUid) {
            $pagesSorted[] = $pages[$pageUid];
        }
        if (TRUE === $this->templateVariableContainer->exists($variableName)) {
            $this->templateVariableContainer->remove($variableName);
        }
        $this->templateVariableContainer->add($variableName, $pagesSorted);
    }
}

und so verwendet man ihn in Menu/Type-0.html:

<ce:menu.list pageUids="{pageUids}" as="pages">
    <f:if condition="{pages}">
        <my:sortPageMenu order="{pageUids}" pages="{pages}" variableName="pages" />
        <ul class="ce-menu ce-menu-0">
            <f:for each="{pages}" as="page">
                <li>
                    <f:link.page pageUid="{page.uid}">
                        <f:if condition="{page.nav_title}">
                            <f:then>
                                {page.nav_title}
                            </f:then>
                            <f:else>
                                {page.title}
                            </f:else>
                        </f:if>
                    </f:link.page>
                </li>
            </f:for>
        </ul>
    </f:if>
</ce:menu.list>

Tags:

Geschrieben in TYPO3 | Kommentare deaktiviert für Manuelle Sortierung für „Menü ausgewähler Seiten“

News-Kategorie auf Detailansicht in Kategoriebaum hervorheben

Folgendes Setup: Seite mit News-Plugins: Links ein Kategoriebaum, rechts die dadurch gefilterte Listenansicht. Dann gibt es da noch eine Detailseite, auf der dann das Plugin für die Detailansicht ist. Nun will mein Kunde auf der Detailansicht links ebenfalls den Kategoriebaum haben und dabei soll die aktuelle Kategorie der News hervorgehoben sein. Und das funktioniert so:

Die Extension news ist ziemlich genial – es gibt dort Signals, die aus dem Controller aufgerufen werden und so das Manipulieren von Daten möglich machen. Dann muss man nur eine eigene Klasse registrieren (ext_localconf.php)

$signalSlotDispatcher = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\SignalSlot\\Dispatcher');
$signalSlotDispatcher->connect(
    'GeorgRinger\\News\\Controller\\CategoryController',
    'listAction',
    'My\\Extension\\Signals\\CategoryController', // fully your choice
    'listActionSlot', // fully your choice
    TRUE
);

Und dann entsprechend die Funktion implementieren. In meinem Fall war es etwas komplizierter, da jede News mehreren Kategorien zugewiesen wurde und die Kategorien verschachtelt waren. Da ich nur eine Kategorie hervorheben kann, habe ich mich dann dafür entschieden, die Kategorie ohne Unterkategorien zu wählen.

/**
 * get current news item category and set in overwrite demand
 *
 * @param array $categories
 * @param array $overwriteDemand
 * @param array $demand
 * @param array $extendedVariables
 */
public function listActionSlot($categories, $overwriteDemand, $demand, $extendedVariables)
{
	$newsArguments = GeneralUtility::_GET('tx_news_pi1');
	$newsUid = (int)$newsArguments['news'];
 
	if($newsUid > 0) {
		/** @var $db TYPO3\CMS\Core\Database\DatabaseConnection */
		$db = $GLOBALS['TYPO3_DB'];
 
		$result = $db->exec_SELECT_mm_query(
			'sys_category.*',
			'sys_category',
			'sys_category_record_mm',
			'tx_news_domain_model_news',
			'AND tablenames = \'tx_news_domain_model_news\' AND fieldname=\'categories\' AND uid_foreign = '.$newsUid
		);
		$parentUids = array();
		$uids = array();
		while($row = $db->sql_fetch_assoc($result)) {
			$parentUids[] = $row['parent'];
			$uids[] = $row['uid'];
		}
		/* find category that is not a parent */
		$categoryUid = array_shift(array_diff($uids, $parentUids));
		return [
			'categories' => $categories,
			'overwriteDemand' => ['categories' => $categoryUid],
			'demand' => $demand,
			'extendedVariables' => $extendedVariables
		];
	}
	return [
		'categories' => $categories,
		'overwriteDemand' => $overwriteDemand,
		'demand' => $demand,
		'extendedVariables' => $extendedVariables
	];
}

Und so klappts dann bei mir 🙂

Tags: , ,

Geschrieben in TYPO3 | Kommentare deaktiviert für News-Kategorie auf Detailansicht in Kategoriebaum hervorheben

TYPO3 Kommandozeile

Ich suche mich jedesmal tot und merken kann ich mir so was auch nicht…

Referenzindex per Kommandozeile aufbauen:
typo3/cli_dispatch.phpsh lowelevel_refindex -c

Tags: ,

Geschrieben in TYPO3 | Kommentare deaktiviert für TYPO3 Kommandozeile

TYPO3 Random Content nach Kategorie ausgeben

Für mein aktuelles Projekt musste ich folgende Aufgabenstellung lösen und ich finde, dass ich eine elegante Lösung dafür gefunden habe. Auf der Startseite sollen in mehreren Spalten Inhalte zufällig ausgegeben werden. Damit die Benutzer bestimmen können, in welchen Spalten welche Inhalte ausgegeben werden, habe ich global Kategorien angelegt (ich nenne sie hiermal Kat1, Kat2, Kat3). In einem Storage-Ordner können nun beliebige Inhalte abgelegt werden und einer (oder mehreren Kategorien) zugewiesen werden. Für die Ausgabe habe ich ein Plugin erstellt, dort kann man die Kategorie für die Ausgabe definieren. Nun wird es interessant: Wie kann man die Inhalte einer bestimmten Kategorie im Plugin auslesen und bei der Ausgabe das normale Rendering der TYPO3 Content Elemente nutzen?

Inspiriert von diesem Beitrag Variierender Content anhand der System Kategorien habe ich folgendes Vorgehen gewählt.

In der Show-Funktion des Controllers erstelle ich die Konfiguration und erzeuge die Ausgabe mithilfe des Content Renderers. Ich definieren mein Plugin auf die übliche Art und Weise in ext_localconf.php und ext_tables.php, setze zusätzlich die Storage Pid in den Settings:

plugin.tx_myext {
	persistence {
		storagePid = {$randomContentStorage}
	}
	settings {
		storagePid = {$randomContentStorage}
	}
}

Die die Auswahl der Kategorie im Plugin nehme ich ein Flexform (das ist nur der relevante Teil davon):

<settings.category>
    <TCEforms>
        <exclude>1</exclude>
        <label>LLL:EXT:ewwald/Resources/Private/Language/locallang_db.xlf:ff.category</label>
        <config>
            <type>group</type>
            <internal_type>db</internal_type>
            <allowed>sys_category</allowed>
            <size>1</size>
            <maxitems>1</maxitems>
            <minitems>0</minitems>
            <show_thumbs>1</show_thumbs>
            <wizards>
                <suggest>
                    <type>suggest</type>
                </suggest>
            </wizards>
        </config>
    </TCEforms>
</settings.category>

Dann erstelle ich eine Klasse RandomContentController mit meiner Show Funktion:

public function showAction()
{
    $conf = [
        'table' => 'tt_content',
        'select.' => [
            'pidInList' => $this->settings['storagePid'],
            'join' => 'sys_category_record_mm ON tt_content.uid = sys_category_record_mm.uid_foreign',
            'groupBy' => 'uid',
            'where' => 'sys_category_record_mm.uid_local = '.(int)$this->settings['category'].' AND sys_category_record_mm.tablenames = \'tt_content\'',
            'max' => '1',
            'orderBy' => 'rand()'
        ]
    ];
    $html = $GLOBALS['TSFE']->cObj->cObjGetSingle('CONTENT', $conf);
    return $html;
}

Das wars! Keine Models und Repositories, keine Templates. Die Inhaltselemente werden wie andere Inhaltselemente ausgegeben.

Tags: ,

Geschrieben in TYPO3 | Kommentare deaktiviert für TYPO3 Random Content nach Kategorie ausgeben

TYPO3 Multisite / Multidomain und Verlinkung untereinander

Ein Kunde hat eine Website laufen in Deutsch unter der Beispieldomain www.beispiel.de. Er möchte gerne eine englische Version dieser Seite unter einer anderen Domain laufen www.beispiel.eu. Die englischen Inhalte entsprechen nicht immer den deutschen, manche Seiten sind direkt übersetzt, manche Seiten existieren nicht. Und so hatte ich folgende Idee: Ich habe dem Seiten-Datensatz ein neues Feld eingefügt (tx_related_page), in das die Seite der anderen Sprache ausgewählt werden kann. Somit kann im Header hinter einem Flaggensymbol der Link zu der Seite in der anderen Sprache aus dem anderen Seitenbaum versteckt werden. Falls in dem Seiten-Datensatz kein Link hinterlegt ist, wird einfach der Link zur Root-Seite des anderen Seitenbaumes generiert. Mal anschaulich:
– ROOT DE
— Unterseite 1 (Gegenseite Subpage 1)
— Unterseite 2 (keine Gegenseite)
– ROOT EN
— Subpage 1 (Gegenseite Unterseite 1)
— Subpage 2 (keine Gegenseite)
Auf ROOT DE ist der Domain Record für www.beispiel.de und auf ROOT EN ist der Domain Record für www.beispiel.eu.
Auf Unterseite 1 wird die englische Flagge auf Subpage 1 verlinkt, Subpage verlinkt auf Unterseite 1. Da Unterseite 2 keine Gegenseite hat, wird ein Link zu ROOT EN generiert. Und von Subpage 2 ein Link zu ROOT DE.

Den Link in TypoScript zu erzeugen funktioniert so:

20 = IMAGE
20.file = {$assets}Public/Images/{$flagIcon}
20.stdWrap.typolink.parameter.data = field:tx_related_page
20.stdWrap.if.isTrue.data = page:tx_related_page
 
30 = IMAGE
30.file = {$assets}Public/Images/{$flagIcon}
30.stdWrap.typolink.parameter = {$oppositeRootPid}
30.stdWrap.if.isFalse.data = page:tx_related_page

Ohne RealURL hat das prima funktioniert. Dann hatte ich RealURL aktiviert und auf einmal bekam ich nur Links auf die Root-Seite des anderen Seitenbaums. Lange hab ich gesucht, was an der Konfiguration nicht stimmt, ich erspare euch das alles. Das ist die funktionierende Lösung:

Im Setup des Templates muss folgendes ergänzt werden, damit Links zwischen Domains generiert werden:
config.typolinkEnableLinksAcrossDomains = 1

Das nicht vergessen:
config.tx_realurl_enable = 1

In der RealURL Konfiguration müssen die ID der Root-Seiten für die Domains angegeben werden. Ich hatte es zuerst so wie im Beispiel im RealURL FAQ. Das klappt nicht! Aber folgende Konfiguration funktioniert:

$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['realurl'] = [
    '_DEFAULT' => [...]
];
$TYPO3_CONF_VARS['EXTCONF']['realurl']['www.beispiel.de'] = $TYPO3_CONF_VARS['EXTCONF']['realurl']['_DEFAULT'];
$TYPO3_CONF_VARS['EXTCONF']['realurl']['www.beispiel.de']['pagePath']['rootpage_id'] = 1;
 
$TYPO3_CONF_VARS['EXTCONF']['realurl']['www.beispiel.eu'] = $TYPO3_CONF_VARS['EXTCONF']['realurl']['_DEFAULT'];
$TYPO3_CONF_VARS['EXTCONF']['realurl']['www.beispiel.eu']['pagePath']['rootpage_id'] = 29;

Tags: , ,

Geschrieben in TYPO3 | Kommentare deaktiviert für TYPO3 Multisite / Multidomain und Verlinkung untereinander

Einträge in Liste in Zweiergruppen ausgeben

Folgende Aufgabenstellung: Mit Fluid sollen für eine Slideshow jeweils zwei Elemente einer Liste gruppiert (also in 1 Div eingeschlossen) ausgegeben werden. Als erstes muss am Anfang ein Slide geöffnet werden, wenn die Liste nicht leer ist. Nach dem letzten Element muss man den Slide schließen, egal wieviele Elemente in der Liste sind. Dazwischen muss man nach zwei Elementen den Slide schließen und wieder öffnen. Und sieht dann der Code aus:

<div class="video-slideshow">
	<div class="slick-slideshow" data-slick='{
			"adaptiveHeight": true
		}'>
		<div class="slide"><!-- Slide BEGIN -->
			<f:for each="{videos}" as="video" iteration="i">
				<f:render section="Video" arguments="{video: video, settings: settings}" />
				<f:if condition="{i.isLast}">
					<f:then>
						</div><!-- Slide END -->
					</f:then>
					<f:else>
						<f:if condition="{i.index} % 2">
							</div><div><!-- Slide -->
						</f:if>
					</f:else>
				</f:if>
			</f:for>
	</div><!-- slick-slideshow -->
</div><!-- video-slideshow -->

Ok, übersichtlich ist was anderes…

News-Liste durch Kategorie-Liste filtern

Wer zu ungeduldig ist, gleich nach unten scollen und den letzten Absatz lesen.

Folgendes Setup: Auf einer Seite befinden sich in einer Spalte das News-Plugin mit der Liste, in der Spalte nebendran das News-Plugin mit der Kategorieliste. Wenn nun eine Kategorie angeklickt wird in der Kategorie-Liste, dann möchten man, dass diese Kategorie in der Liste hervorgehoben wird und dass nur die News dieser Kategorie angezeigt werden. Das erste hat gut geklappt.

Nun hat sich die News-Liste trotz aller meiner Bemühungen von der in der URL gesetzten Ketegorie unbeindruckt gezeigt. Dabei war der Haken bei Disable override demand NICHT gesetzt. Ich hatte auch gegoogelt und nur einen Forums-Beitrag gefunden mit dem gleichen Problem, leider ohne Antwort. Ich hane angefangen mich durch den Code der News-Extension zu debuggen, um rauszufinden, wo der Parameter flöten gehen könnte.

In der Klasse NewsRepository Zeile 52 dann die Antwort:

// If "ignore category selection" is used, nothing needs to be done
if (empty($conjunction)) {
    return $constraint;
}

An dieser Stelle bricht das ab und der Filter wird nicht angewendet.

Lösung: im Backend-Formular des Plugins muss im Category mode am besten „Show items with selected categories (OR)“ eingestellt werden. Das ist alles!
2016-06-13 14-58-50

Bestimmt denken sich nun manche: Das steht doch genau so da…, wer lesen kann… , blablabla. Meine Antwort darauf: In erster Linie will ich ja keine Filterung, daher ist die erste Auswahl (zeige alle Kategorien) ja eigentlich richtig. Ich finde es eher verwirrend, dass obwohl ich keine Kategorien initial ausgewählt habe, alle angezeigt werden. Vielleicht ist mit diesem Beitrag doch mal jemandem geholfen.

TYPO3 Überschrift als RTE formatieren

Manchmal muss man auch Überschriften mit dem RTE formatieren können – Text fett oder kursiv auszeichnen z.B.

Dazu erstmal das TCA des Header-Felder auf Textarea mit RTE umstellen. Dieser Code wird in die Datei my_extension/Configuation/TCA/Overrides/tt_content.php eingefügt.

$GLOBALS['TCA']['tt_content']['columns']['header']['config']['type'] = 'text';
$GLOBALS['TCA']['tt_content']['columns']['header']['config']['cols'] = 40;
$GLOBALS['TCA']['tt_content']['columns']['header']['config']['rows'] = 3;
$GLOBALS['TCA']['tt_content']['columns']['header']['defaultExtras'] = 'richtext[]';
$GLOBALS['TCA']['tt_content']['palettes']['header'] = str_replace(
    'header;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:header_formlabel,',
    'header;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:header_formlabel;;richtext:rte_transform[mode=ts_css],',
    $GLOBALS['TCA']['tt_content']['palettes']['header']
);
 
$GLOBALS['TCA']['tt_content']['palettes']['headers'] = str_replace(
    'header;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:header_formlabel,',
    'header;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:header_formlabel;;richtext:rte_transform[mode=ts_css],',
    $GLOBALS['TCA']['tt_content']['palettes']['headers']
);

Damit wird der Header zu einem „normalen“ RTE Feld mit Standard-Konfiguration. Wenn das zu viel ist (und das nehme ich an), kann für das Header-Feld eine spezielle RTE-Konfiguration angelegt werden. Das muss ins PageTsConfig:

RTE.config.tt_content.header {
	showButtons (
		bold, italic, chMode
	)
	RTEHeightOverride = 100
}

Dann muss man nur dafür sorgen, dass die Formatierung auch ausgegeben wird. Falls man mit Fluid Styled Content arbeitet (absolut empfehlenswert), dann muss man im Partial Header/Header.html nur folgende Änderung vornehmen:

<h1><f:link.typolink parameter="{link}"><f:format.raw>{header}</f:format.raw></f:link.typolink></h1>

Tags: ,

Geschrieben in TYPO3 | Kommentare deaktiviert für TYPO3 Überschrift als RTE formatieren