sys_category: Systemkategorien in Datensätzen der eigenen Extension verfügbar machen

Teil 2: Systemkategorien in Datensätzen der eigenen Extension verfügbar machen

Leider lassen sich die Kategorien nicht mit dem Extension Builder direkt in die neue Extension integrieren. Stattdessen legt man ein ein Feld als „Verweis“ an, Verbindet diesen Verweis aber nicht mit einem anderen Model. Wenn es möglich sein soll, mehrere Kategorien auszuwählen, nennt man das Feld „categories“.

Modellierung der Beziehung zu den Kategorien im Extbase-Model

Nun bearbeitet man das Model, das kategorisiert werden soll, bei mir lw_pinboard/Classes/Domain/Model/Message.php

In der Regel ist es ja möglich, einem Datensatz mehrere Kategorien zuzuweisen. Und natürlich kann auch eine Kategorie viele Datensätze enthalten. Deshalb handelt es sich um eine m:n Beziehung. Diese lässt sich in Extbase wie folgt modelieren.

Das Feld muss ein ObjectStorage sein:

/**
 * category
 * 
 * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\LW\LwPinboard\Domain\Model\Category>
 */
protected $categories = null;

man darf nicht vergessen, den ObjectStorage im Konstruktor des Models zu initialisieren, denn sonst kommt es zu Fehlermeldungen.

public function __construct()
{
	$this->setCategories(new \TYPO3\CMS\Extbase\Persistence\ObjectStorage);
}

Nun müssen neben dem klassischen Getter und Setter auch noch ein Adder und Remover zum Model hinzugefügt werden:

/**
 * Returns the categories
 * 
 * @return $categories
 */
public function getCategories()
{
	return $this->categories;
}

/**
 * Sets the category
 * 
 * @param  \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\LW\LwPinboard\Domain\Model\Category> $categories
 * @return void
 */
public function setCategories(\TYPO3\CMS\Extbase\Persistence\ObjectStorage $categories)
{
	$this->categories = $categories;
}

/**
 * Adds a category
 * 
 * @param  \LW\LwPinboard\Domain\Model\Category $category
 * @return void
 */
public function addCategory(\LW\LwPinboard\Domain\Model\Category $category) {
	$this->categories->attach($category);
}

/**
 * Removes a category
 * 
 * @param  \LW\LwPinboard\Domain\Model\Category $category
 * @return void
 */
public function removeCategory(\LW\LwPinboard\Domain\Model\Category $category) {
	$this->categories->detach($category);
}

Anpassung des TCA zum Anzeigen und Ändern der Kategorien im Backend

Nun muss noch das TCA der Tabelle des Models Message angepasst werden, in meinem Fall: lw_pinboard/Configuration/TCA/tx_lwpinboard_domain_model_message.php

Das Feld categories wird wie folgt in den columns angepasst:

'categories' => [
	'exclude' => true,
	'label' => 'LLL:EXT:lw_pinboard/Resources/Private/Language/locallang_db.xlf:tx_lwpinboard_domain_model_message.category',
	'config' => [
		'type' => 'inline',
		'foreign_table' => '',
		'minitems' => 0,
		'maxitems' => 1,
		'appearance' => [
			'collapseAll' => 0,
			'levelLinksPosition' => 'top',
			'showSynchronizationLink' => 1,
			'showPossibleLocalizationRecords' => 1,
			'showAllLocalizationLink' => 1
		],
	],
],

Zusätzlich muss das Feld noch kategorisiert werden. Dazu vor dem return in der selben Datei folgendes aufrufen:

\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::makeCategorizable(
	'LW.' . $_EXTKEY,
	'tx_lwpinboard_domain_model_message',
	'categories'
);

Die Kategorien im eigenen Controller der Extension

Nun kann man z.B. im Controller eine Ansicht mit nur den Nachrichten einer Kategorie konfigurieren: lw_pinboard/Classes/Controller/MessageController.php

/**
 * action list
 * 
 * @return void
 */
public function listAction()
{
	$arguments = $this->request->getArguments();
	$category = 0;
	if($arguments && $arguments['cat']) {
		$category = intval($arguments['cat']);
	}
	if ($category != 0) {
		$messages = $this->messageRepository->findByCategory($category);
	} else {
		$messages = $this->messageRepository->findAll();
	}
	$categoryList = $this->categoryRepository->findAll();
	$this->view->assign('messages', $messages);
	$this->view->assign('categoryList', $categoryList);
}

Die Methode findByCategory ist nicht standardmäßig in einem Repository vorhanden, sondern muss noch implementiert werden. Auf keinen Fall darf man die Magic Methode findByCategories nutzen. Diese liefert nämlich die falschen Daten und ggf keine Fehlermeldung und das kommt so: TYPO3 speichert im Feld categories in der Datenbank bei einer m:n Beziehung die ANZAHL der Kategorien. Wenn nun Mein Datensatz zwei Kategorien hat, steht hier also eine 2. Wenn ich nun nach Nachrichten in der Kategorie mit uid 2 suche und die Magic Methode findByCategories nutze, so liefert mir nun Extbase alle Nachrichten zurück, die zu zwei Kategorien zugewiesen wurden.

Methode findByCategory im Repository der Message implementieren

Also editieren wir nun noch das Repository unseres eigenen Datensatzes, hier der Message: lw_pinboard/Classes/Domain/Repository/MessageRepository.php

/**
 * Finds an object matching the given identifier.
 *
 * @param int $categoryid The identifier of the category to find Messages from
 * @return object The matching object if found, otherwise NULL
 * @api
 */
public function findByCategory($categoryid) {
	$query = $this->createQuery();
	$query->matching($query->contains('categories', $categoryid));
	return $query->execute();
}

sys_category: Systemkategorien in eigener Extension einbinden und erweitern

Seit Version 6.0 bietet TYPO3 systemeigene Kategorien an, die sich komfortabel in eigene Extensions integrieren lassen.

Teil 1: Systemkategorien in eigener Extension einbinden und erweitern

Leider ist deren Integration nicht ganz trivial. Die beste Verfügbare Anleitung zum integrieren der Systemkategorien in eine eigene Extension (engl) habe ich bisher auf Github gefunden. daher hier eine Anleitung, wie man vorgehen kann.

Es gibt in der Systemextension Extbase, zu finden unter TYPO3ROOT/typo3/sysext/extbase bereits ein vorbereitetes Model und Repository für die System Category. Diese muss man in seiner eigenen Extension nun nur erweitern und das geht so:

in my_extension/Classes/Domain/Model/Category.php ablegen mit folgendem Inhalt:

<?php
namespace LW\LwPinboard\Domain\Model;

class Category extends \TYPO3\CMS\Extbase\Domain\Model\Category {}

analog das Repository unter my_extension/Classes/Domain/Repository/CategoryRepository.php

<?php
namespace LW\LwPinboard\Domain\Repository;

class CategoryRepository extends \TYPO3\CMS\Extbase\Domain\Repository\CategoryRepository {}

Wenn man keine zusätzlichen Anforderungen an die Funktionalität hat, kann man die Klassen von Category Model und Repository erstmal unverändert lassen. Damit Extbase weiß, in welcher Datenbanktabelle es schauen muss, muss man nun noch per TypoScript ein Mapping durchgeführt werden. Dies geht z.B. in my_extension/Configuration/TypoScript/setup.ts mit:

plugin.tx_myextension.persistence.classes {
	ABC\MyExtension\Domain\Model\Category {
		mapping {
			recordType = 0
			tableName = sys_category
		}
	}
}

Nun sind die Kategorien generell in der Extension verfügbar. Man könnte diese z.B. im Controller an das View hängen, um eine Liste aller Kategorien auszugeben:

Dazu muss man im eigenen Controller der Extension, bei mir my_extension\Classes\Controller\MessageController.php zunächst das CategoryRepository  hinzufügen und injecten:

 /**
 * @var \ABC\MyExtension\Domain\Repository\CategoryRepository
 * @inject
 */
protected $categoryRepository = null;

Nun kann in der entsprechenden Action das Repository so wie jedes andere auch abgefragt werden, z.B:

$categoryList = $this->categoryRepository->findAll();
$this->view->assign('categoryList', $categoryList);

Wir können nun eine Liste von System Kategorien per FLUID anzeigen, schön, aber wir wollten doch unsere Messages kategorisieren.

Dazu weiter mit Teil 2

TYPO3 8.7 LTE Erweiterung manuell deinstallieren


Oops, an error occurred!

Es kann passieren, dass eine inkompatible oder fehlerhafte Erweiterung (Extension) dafür sorgt, dass das ganze TYPO3 Backend und selbst das Install Tool nicht mehr ansprechbar sind. Mir ist das z.B. passiert, nachdem ich versucht habe, die Extension blog_example zu installieren. Ok zugegeben, sie wurde auch schon lange nicht mehr gepflegt, das hatte ich übersehen.

TYPO3 zeigte dann nur noch einen hübschen roten Kasten mit der Fehlermeldung „Oops, an error occurred! Class ‚Tx_Extbase_Utility_Extension‘ not found“ an.

In so einem Fall ist es natürlich nicht möglich, die Erweiterung über den Extensionmanager zu deaktivieren. Wenn man aber FTP Zugang auf den Server hat, ist das kein Problem.

In folgender Datei: TYPO3ROOT/typo3conf/PackageStates.php den Eintrag der fehlerhaften Extension löschen, in diesem Fall:

    'blog_example' => [
        'packagePath' => 'typo3conf/ext/blog_example/',
    ],

Welches Template wird aktuell verwendet?

Bei der Entwicklung oder Anpassung eines WordPress Designs (WordPress Theme) kann es teils recht nervig sein, herauszufinden, welches Template / welche Templates aktuell verwendet werden. Das 
kostenlose Plugin Show Current Template löst dieses Problem für mich sehr gut.

Welcher Webdesigner hat nicht schon test weise xxxx oder ähnliches in diverse Templates von Themes geschrieben nur um rauszufinden, welches Template nun aktuell verwendet wird.

Wer ein Standard WordPress Theme verwendet und zu diesem ein eigenes Child-Theme geschrieben hat, hat zusätzlich das Problem, dass das Template aus dem übergeordneten Theme oder dem eigenen Child-Theme kommen kann.

Es gibt diverse Lösungen, die unter anderem auch Stackexchange diskutiert werden (englisch): 
How do you find out which template page is serving the current page?

Das kostenlose Plugin Show Current Template von Jotaki Taisuke löst dieses Problem auf sehr elegante Weise. Es ist zwar nicht auf deutsch übersetzt, verwendet aber nicht viel Sprache. Es funktioniert auch mit 5.0.3 problemlos.

Nach der Installation des Plugins „Show Current Template“ im Plugin Bereich des WordPress Backends erscheint in der oberen schwarzen Leiste bei Ansicht einer Seite des Blogs das Haupt-Themplate sowie Informationen zu den verwendeten Subtemplates. Das sieht dann z.B. so aus:

WordPress Widget in anderen Bereich verschieben

Viele WordPress Themes haben mehr als einen Widget-Bereich (z.B. für Sidebar, Footer, etc). Beim Deaktivieren und wieder Aktivieren eines Themes können nun die Widgets in den falschen Bereich verrutschen.

Anfangs habe ich in so einem Fall das Widget im falschen Bereich gelöscht und im korrekten wieder angelegt, aber es geht viel einfacher!

  1. Im Customizer unterhalb des Widgets auf „Umordnen“ klicken.
  2. Auf den Button zum Verschieben Drücken
  3. Neuen Bereich auswählen, „Verschieben“ Drücken, Veröffentlichen nicht vergessen.