Eine eigene TYPO3 Extension (Extbase/Fluid) mit System Kategorien erstellen (Teil 2)

In diesem Teil verknüpfen wir unsere TYPO3 Extension, die wir in Teil 1 der Reihe erstellt haben, mit den System Kategorien von TYPO3.

Der Extension Builder hat unsere Extension, die wir in Teil 1 erstellt haben, in dem Verzeichnis
„typo3conf -> ext“
abgespeichert. In unserem Fall ist der Ordnername der Extension „ha_kategorieext“ analog zu unserem angegebenen Extension Key. Folgende Struktur hat uns der Extension Builder darin angelegt:

  • Classes
  • Configuration
  • Documentation.tmpl (kann gelöscht werden)
  • Resources
  • Tests (kann gelöscht werden)
  • ext_emconf.php
  • ext_icon.gif
  • ext_localconf.php
  • ext_tables.php
  • ext_tables.sql
  • ExtensionBuilder.json (kann gelöscht werden)

TYPO3 System Kategorien integrieren

Jetzt wird es Zeit unsere TYPO3 Extension zu bearbeiten.

NeuerInhaltController.php (Classes -> Controller)

Aktueller Code:

public function listAction() {
        $neuerInhalts = $this->neuerInhaltRepository->findAll();
        $this->view->assign('neuerInhalts', $neuerInhalts);
    }

Ersetzen durch:

public function listAction() {
        $demand = $this -> createDemandObjectFromSettings($this -> settings);
        $entries = $this -> neuerInhaltRepository -> findDemanded($demand);
        $this -> view -> assign('neuerInhalts', $entries);
    }

Und zusätzlich hinzufügen:

protected function createDemandObjectFromSettings($settings) {
        $demand = $this->objectManager->get('Vekategorieext\\HaKategorieext\\Domain\\Model\\NeuerInhalt'); // Neuer Inhalt ist der Dateiname vom Domain Modell -> Classes -> Domain -> Model
        $demand->setCategories($settings['categories']);
        return $demand;
    }

NeuerInhalt.php (Classes -> Domain -> Model)

Aktueller Code:

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

Ändern in:

public function setCategories($categories) {
        $this->categories = $categories;
    }

NeuerInhaltRepository.php (Classes -> Domain -> Repository)

Aktueller Code:

protected $defaultOrderings = array(
        'sorting' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING
    );

Ersetzen durch:

public function findDemanded($demand) {
        $query = $this -> createQuery();
        $query -> getQuerySettings() -> setRespectStoragePage(FALSE);
        $query -> setOrderings($this -> createOrdering());
        $constraints = $this -> createConstraintsFromDemand($query, $demand);
        if (!empty($constraints)) {
            $query -> matching(
            $query -> logicalAnd($constraints)
        );
        }
        return $query -> execute();
    }
        
        
    protected function createConstraintsFromDemand(\TYPO3\CMS\Extbase\Persistence\QueryInterface $query, $demand) {
        $constraints = array();
        
        $categories = $demand -> getCategories();
        if ((!empty($categories))) {
            $categoryConstraints = array();
            $categories = \TYPO3\CMS\Core\Utility\GeneralUtility::intExplode(',', $categories, TRUE);
            foreach ($categories as $category) {
                $categoryConstraints[] = $query -> contains('categories', $category);
            }
            $constraints = $query -> logicalOr($categoryConstraints);
        }
        return $constraints;
    }
        
    protected function createOrdering() {
        $orderings = array('sorting' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING);
        return $orderings;
    }

Flexform hinzufügen

ext_tables.php

Am Ende hinzufügen:

$extensionName = strtolower(\TYPO3\CMS\Core\Utility\GeneralUtility::underscoredToUpperCamelCase($_EXTKEY));
$pluginName = strtolower('Fekategorieext');
$pluginSignature = $extensionName.'_'.$pluginName;

$TCA['tt_content']['types']['list']['subtypes_excludelist'][$pluginSignature] = 'layout,recursive,select_key,pages';
$TCA['tt_content']['types']['list']['subtypes_addlist'][$pluginSignature] = 'pi_flexform';
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPiFlexFormValue($pluginSignature, 'FILE:EXT:'.$_EXTKEY . '/Configuration/FlexForms/flexform.xml');

FlexForms Ordner erstellen (Configuration -> FlexForms)

Im FlexForms Ordner eine flexform.xml erstellen (Configuration -> FlexForms -> flexform.xml)

Inhalt:

<T3DataStructure>
    <meta>
        <langDisable>1</langDisable>
    </meta>
    <sheets>
        <sDEF>
            <ROOT>
                <TCEforms>
                    <sheetTitle>title</sheetTitle>
                </TCEforms>
                <type>array</type>
                <el>
                    <settings.categories>
                        <TCEforms>
                          <exclude>1</exclude>
                          <label>Kategorien:</label>
                          <config>
                            <type>select</type>
                            <autoSizeMax>50</autoSizeMax>
                            <foreign_table>sys_category</foreign_table>
                            <foreign_table_where> AND sys_category.sys_language_uid IN (-1, 0) ORDER BY sys_category.title ASC</foreign_table_where>
                            <maxitems>9999</maxitems>
                            <renderMode>tree</renderMode>
                            <size>10</size>
                            <treeConfig>
                                <appearance>
                                    <expandAll>1</expandAll>
                                    <showHeader>1</showHeader>
                                </appearance>
                                <parentField>parent</parentField>
                            </treeConfig>
                          </config>
                        </TCEforms>
                    </settings.categories>
                </el>
            </ROOT>
        </sDEF>
    </sheets>
</T3DataStructure>

setup.txt (Configuration -> TypoScript)

Das komplette CSS_DEFAULT_STYLE kann gelöscht werden

Aktueller Code:

plugin.tx_hakategorieext_fekategorieext {
    view {
        templateRootPaths.0 = {$plugin.tx_hakategorieext_fekategorieext.view.templateRootPath}
        partialRootPaths.0 = {$plugin.tx_hakategorieext_fekategorieext.view.partialRootPath}
        layoutRootPaths.0 = {$plugin.tx_hakategorieext_fekategorieext.view.layoutRootPath}
    }
    persistence {
        storagePid = {$plugin.tx_hakategorieext_fekategorieext.persistence.storagePid}
    }
}

Ändern zu:

plugin.tx_hakategorieext_fekategorieext {
    view {
        templateRootPaths.0 = {$plugin.tx_hakategorieext_fekategorieext.view.templateRootPath}
        partialRootPaths.0 = {$plugin.tx_hakategorieext_fekategorieext.view.partialRootPath}
        layoutRootPaths.0 = {$plugin.tx_hakategorieext_fekategorieext.view.layoutRootPath}
    }
    persistence {
        storagePid = {$plugin.tx_hakategorieext_fekategorieext.persistence.storagePid}
    }
    mvc {
        callDefaultActionIfActionCantBeResolved = 1
    }
}

Extension aktivieren

That’s it! Zum Schluß müssen wir nur noch unsere TYPO3 Extension im Extension Manager aktivieren. Das Statische TypoScript einbinden und schon kann man die System internen Kategorien von TYPO3 nutzen.

* Werbung/Affiliate Link

Kommentare

  • Bernd
    07.12.2017 - 09:47 Uhr

    Sehr ausführlich aufgebaut und nett geschrieben. M,it der Anleitung kann ich zwar diese eine Extension nachbauen, jedoch würde ich gerne wissen, warum man die einzelnen Schritte macht und was die einzelnen Sachen bewirken.
    Natürlich versteht man das meiste durch den Code.. Aber trotzdem wäre eine textliche Übersetzung eine nette Ergänzung. Dann könnte man lernen statt einfach nur zu kopieren. 🙂
    Trotzdem Danke für diesen ausführlichen Beitrag. Hat mir sehr weiter geholfen. Typo3 ist ja kleider kaum dokumentiert.. und selbst wenn etwas dokumentiert ist, ist das oft veraltet.

    Antworten
    • Markus
      07.12.2017 - 12:10 Uhr

      Hallo Bernd, vielen dank für deinen Kommentar. Manchmal ist weniger mehr. 😉 Die Seite kennst du? https://docs.typo3.org/

      Antworten
  • Oliver
    02.02.2018 - 09:55 Uhr

    Mit der Zeile $TCA[‚tt_content‘][‚types‘][‚list‘][’subtypes_excludelist‘][$pluginSignature] = ‚layout,recursive,select_key,pages‘; in der ext_tables.php entfernst du ja quasi die Datensatzsammlung. Wenn ich die Zeile entferne, erscheint die Datensatzsammlung wieder im Backend, hat aber keine Auswirkung auf die Anzeige im Frontend. Lässt sich das in deiner Beispiel-Extension. irgendwie einfach kombinieren – die Auswahl der Datensatzsammlung und die der Systemkategorien?

    Antworten
    • Markus
      02.02.2018 - 13:27 Uhr

      Hallo Oliver,

      dafür wären ein paar Zeilen mehr Code nötig das das auch im Frontend greift. Nur das Feld aktivieren reicht hier leider nicht.
      Grundsätzlich würde ich es über Flexform lösen.
      Vielleicht hilft dir der Artikel weiter: https://www.derhansen.de/2016/02/how-extbase-determines-storagepid.html

      Antworten
      • Oliver
        06.02.2018 - 15:43 Uhr

        Hallo Markus, zunächst mal vielen Dank für deine Antwort. Könntest du vielleicht ein etwas detaillierteres Beispiel für Nicht-Programmiercracks geben?

      • Markus
        07.02.2018 - 20:23 Uhr

        Hallo Oliver,

        schau mal hier, habe dazu einen Artikel erstellt.

  • Oliver
    09.02.2018 - 10:30 Uhr

    Hallo Markus,

    sehr cool! Werd ich gleich mal ausprobieren. Wird mit Sicherheit auch einigen Integratoren, die mit Extension-Programmierung nicht so viel am Hut haben, helfen und das Leben erleichtern 🙂

    Antworten
  • Dominik
    19.03.2018 - 16:36 Uhr

    Hallo Markus,
    ich habe für ca. 10 Stunden versucht, eine Extension zusammen mit einem Plugin zu erstellen und anstädig zu benutzen. Ich habe jedoch nur fehlerhafte Tutorials gefunden und deines ist das einzige, was komplett fehlerfrei und ohne Probleme mir geholfen hat. Gute Anleitung!
    Danke!!

    Antworten
    • Markus
      19.03.2018 - 19:54 Uhr

      Hallo Dominik,

      vielen Dank für dein Feedback! Freut mich dir geholfen zu haben.

      Antworten
  • Christine
    13.03.2019 - 10:46 Uhr

    @Oliver:
    Folgendermaßen lässt sich die Kombination „Datensatzsammlung“ und „Kategorien“ recht einfach realsieren (zumindest in TYPO3 7.6):

    In der Datei NeuerInhaltRepository.php (Classes -> Domain -> Repository) statt
    $query -> getQuerySettings() -> setRespectStoragePage(FALSE);
    neu:
    $query -> getQuerySettings() -> setRespectStoragePage(TRUE);

    UND zusätzlich folgendes beachten:

    Bei der Entwicklung einer eigenen Extension muss folgendes bedacht werden: ab TYPO3 Version 7 überschreibt die Deklaration von plugin.tx_extensionname.persistence.storagePid den Wert im Feld „Datensatzsammlung“. Dazu muss nicht einmal ein Wert für storagePid angegeben werden! Damit der Wert in „Datensatzsammlung“ nicht überschrieben wird, ändern wir die Angaben im Typoscript (Constants und Setup) folgendermaßen:

    In Configuration/TypoScript/setup.txt ändern:
    „plugin.tx_extensionname_pluginname“ zu „plugin.tx_extensionnamen“

    In Configuration/TypoScript/constants.txt ändern: „plugin.tx_extensionname_pluginname“ zu „plugin.tx_extensionname“

    Der Extension Builder generiert das TypoScript direkt für das einzelne Plugin. Obwohl das im Grunde funktioniert, ändern wir den Pfad auf eine allgemeine Extension-Konfiguration ab. Ein Vorteil ist, dass die Einträge im Feld Datensatzsammlung nicht länger von storagePid überschrieben werden.
    TYPO3 bzw. Extbase (das dieser Extension zugrundeliegende Framework) sucht nach Speicherorten in einer festgelegten Reihenfolge. Plugin-spezifische Konfigurationen überschreiben dabei stets die Werte im Feld Datensatzsammlung. Dazu muss für storagePid in tx_extensionname_pluginname nicht einmal ein Wert hinterlegt sein – es genügt schon die grundsätzliche Deklaration.

    Antworten

Schreibe einen Kommentar

Erforderliche Felder sind entsprechend markiert.

Wird nicht veröffentlicht.