pt_extlist Daniel Lienert & Michael Knoll pt_extlist Agenda für heute Teil I :: pt_extlist Übersicht Teil II :: pt_extlist für Integratoren • TypoScript Konfiguration • Einbindung als Seiteninhaltselement • Templates und Partials Teil III :: pt_extlist für Entwickler • Architektur & Komponenten • Lifecycles • pt_extlist erweitern pt_extlist Komponenten pt_extlist Schränkt Auswahl der Elemente ein (SQL: where) Sortiert Elemente (SQL: order by) Listdaten Daten der Abfrage (gefiltert, sortiert, „gepaged“) Aggregate Aggregate der Daten Liemitiert Anzahl (SQL: limit) pt_extlist Agenda für heute Teil I :: pt_extlist Übersicht Teil II :: pt_extlist für Integratoren • TypoScript Konfiguration • Einbindung als Seiteninhaltselement • Templates und Partials Teil III :: pt_extlist für Entwickler • Architektur & Komponenten • Lifecycles • pt_extlist erweitern pt_extlist TypoScript, Flexform & Co PT_EXTLIST FÜR INTEGRATOREN pt_extlist Einbinden des Plugins • Wie bisher auch: 1. Liste in TypoScript definieren 2. Liste per FlexForm als Seiteninhalt einbinden pt_extlist Einbinden des Plugins 2 • Neu: Listen‐Konfigurationen werden automatisch erkannt: pt_extlist Einbinden im Cached Mode • Liste wird gecached – Gleiche URLs führen zu gecachten Aufrufen • „Zweiter“ Plugin‐Typ für gecachte Version pt_extlist Einbinden im Cached Mode • Vorteil: extlist auch für Frontend‐Listen verwendbar. • Nachteil: Soll der Benutzer auf die Liste einwirken, kann nur EINE Liste (sprich Komponenten zu einem Listidentifier) auf einer Seite eingesetzt werden. pt_extlist TypoScript Prototypen • Prototyp ist erweiterte „Default‐ Konfiguration“ – Keine Default‐Werte in PHP Code – Alle Konfiguration in TypoScript • Zeigt Konfigurationsmöglichkeiten auf • Macht Konfiguration einfacher und transparent • Zerteilt in flexible Bausteine pt_extlist plugin.tx_ptextlist.prototype.filter { TypoScript Prototypen 2 string { filterClassName = Tx_PtExtlist_Domain_Model_Filter_StringFilter partialPath = Filter/String/StringFilter defaultValue = accessGroups = • Wo befinden sich Prototypen? – Im Filesystem: Configuration/TypoScript/BaseConfig/Prototype breadCrumbString = TEXT – Im TS‐Baum: breadCrumbString { # Fields that can be used are 'label' and 'value' plugin.tx_ptextlist.prototype dataWrap = {field:label} equals {field:value} } • Wie wird Prototyp verwendet? } 11 < plugin.tx_ptextlist.prototype.filter.string 11 { filterIdentifier = allFields label = All defined Fields fieldIdentifier = * } pt_extlist TypoScript Konfiguration • plugin.tx_ptextlist • Konfiguration findet sich unter „settings“ pt_extlist TypoScript Konfiguration 2 • plugin.tx_ptextlist.settings pt_extlist TypoScript Konfiguration 3 • plugin.tx_ptextlist.settings.listConfig • Namensraum für Listenkonfiguration • Jede Liste bekommt List‐Identifier pt_extlist TypoScript Konfiguration 4 • [...].<listIdentifier>.backendConfig (neu!) – Benutzung von Prototypen für einfache Konfiguration (hier: Backend‐Prototyp „typo3“): backendConfig < plugin.tx_ptextlist.prototype.backend.typo3 pt_extlist TypoScript Konfiguration 5 • [...].<listIdentifier>.fields (früher „data“) Backend: SQL Backend: extbase Zugriff auf ein Objektelement Zugriff auf ein komplettes Objekt pt_extlist TypoScript Konfiguration 6 • [...].<listIdentifier>.columns (wie früher) pt_extlist TypoScript Konfiguration 6 / 2 • [...].columns.<column>.cellCSSClass – Dynamische Definition der CSS Classe einer Zelle: columns { 5 { cellCSSClass { renderObj = COA RenderObj { 10 = TEXT 10.value = greenBox 10.if { value.data = field:sumOpen equals = 0 } } … pt_extlist TypoScript Konfiguration 7 • [...].<listIdentifier>.filters (einige Änderungen!) – Prototypen für jeden Filtertyp – Alle Filter mit Auswahlfunktion haben vorkonfiguriertes RenderObjekt renderObj = TEXT renderObj { dataWrap = {field:allDisplayFields} ({field:rowCount}) } pt_extlist TypoScript Konfiguration 8 • [...].<listIdentifier>.aggregateData (neu!) aggregateData { # methods: sum, min, max, avg sumPhone { fieldIdentifier = phone method = sum scope = page special = } } • method: sum/avg/max/min • scope (Neu): page / query (default: page) • special: special SQL Query pt_extlist TypoScript Konfiguration 8 / 2 • [...].<listIdentifier>.aggregateRow aggregateRows { 10 { phoneColumn { aggregateDataIdentifier = sumPhone, avgPhone, maxPhone, minPhone renderObj = TEXT renderObj.dataWrap ( Min.: <b>{field:minPhone}</b><br /> ) } } } pt_extlist Templates & Partials • Wo finde ich die Templates & Partials – Templates befinden sich in Resources/Private/Templates/ – Partials befinden sich in Resources/Private/Partials/ pt_extlist Templates & Partials 2 • Verwendung von FLUID Syntax: – ViewHelper: <f:viewHelperName attrib= “value“> – Variablen: {object.property} • Weitere Hilfe: Extbase & FLUID Cheatsheet pt_extlist Templates & Partials 3 • Verfügbare Objekt in Templates werden im Header angegeben: … Here is a list of objects / variables that can be accessed in this template: Tx_PtExtlist_Domain_Configuration_ConfigurationBuilderconfig Tx_PtExtlist_Domain_Model_List_Header_ListHeaderlistHeader Tx_PtExtlist_Domain_Model_List_RowlistCaptions Tx_PtExtlist_Domain_Model_List_ListDatalistData Tx_PtExtlist_Domain_Model_List_ListDataaggregateRows A instance of the configurationbuilder A instance with header information. A row with captions for every column. A collection of rows. A collection of aggregateRows pt_extlist Templates & Partials 4 • Templates sind per Konvetion von Controller und Action abhängig: ListController‐>listAction() Æ Resources/Private/Templates/List/list.html • Eigener Controller Æ per TS „überschreibbar“: plugin.tx_ptextlist.settings .controller .<CONTROLLER NAME WITHOUT „CONTROLLER“> .<ACTION NAME WITHOUT „ACTION“> .template = path_to_template pt_extlist Verwendung von Partials in Columns • FLUID Templates können für das Rendering von Tabellenzellen verwendet werden • TS‐Konfiguration: 30 { label = Country columnIdentifier = country fieldIdentifier = country_en, capital, tld renderTemplate = EXT:pt_extlist/Configuration/ TypoScript/Demolist/ Demolist_Typo3_02.hierarchicStructure.html } pt_extlist Verwendung von Partials in Columns 2 • Zugriff auf Listen‐Werte im Partial / Template <ul> <f:for each="{data}" as="dataRow"> <li><b><f:format.html>{dataRow.country_en} </f:format.html></b> <ul> <li>City: {dataRow.capital}</li> <li>TLD: {dataRow.tld}</li> </ul> </li> </f:for> </ul> pt_extlist Export Exports werden über eigene Templates und Views realisiert. Konfigurationen unter Export plugin.tx_ptextlist.settings.export { exportConfigs { csvExport < plugin.tx_ptextlist.prototype.export csvExport { viewClassName = Tx_PtExtlist_View_Export_CsvListView fileExtension = csv } fluidTemplateExport < plugin.tx_ptextlist.prototype.export fluidTemplateExport { viewClassName = Tx_PtExtlist_View_Export_FluidListView fileExtension = txt templatePath = typo3conf/ext/pt_extlist/Resources/Private/Templat es/Export/export.html } } } pt_extlist Dokumentation pt_extlist Beispiele • Demolisten im Paket • Sammlung der Beispiele und Funktionen: http://ry25.extlist.devel.intern.punkt.de pt_extlist Agenda für heute Teil III :: pt_extlist für Entwickler • Architektur & Komponenten • Lifecycles • pt_extlist erweitern pt_extlist Agenda für heute Teil II :: pt_extlist für Entwickler • Architektur & Komponenten • Lifecycles • pt_extlist erweitern pt_extlist Architektur, Komponenten, Erweiterung PT_EXTLIST FÜR ENTWICKLER pt_extlist Architektur pt_extlist Architektur 2 • Architekturziele: – Portierung auf Extbase Framework – Möglichkeit der Nutzung von Domain Objects – Entkopplung von Logik und Controllern – Austauschbarkeit von Komponenten pt_extlist Komponenten • Data Backend – „Anschluss“ an Datenquelle – Erzeugung von datenquellenspezifischen Anfragen (SQL, Extbase QueryObject) – Übertragung in pt_extlist eigenes Datenformat (DataMapper) – Berücksichtigt dabei Filter, Pager, Sorter... pt_extlist Komponenten 2 • Configuration Builder – Objekte für (TypoScript‐)Konfiguration – Verschmelzen von Prototypen und aktueller Konfiguration – Überprüfung auf Konsistenz – Erzeugen von hilfreichen Fehlermeldungen zur Konfiguration pt_extlist Komponenten 3 • Filter, Sorter, Pager – Wie früher auch: Beeinflussung der angezeigten Daten hinsichtlich • WHERE (Filter) • SORT BY (Sorter) • LIMIT (Pager) – Neu: • Klare Trennung von Controller und Logik • Abhängigkeiten sind in einem Durchlauf aufgelöst pt_extlist Komponenten 4 • Mapper, RenderChain, ListDataStructureM – Mapper: Abbildung der Datenquellen‐spezifischen Datenstruktur (Array, Objekte) auf Listen‐Struktur – RenderChain: Hintereinander verknüpfbare Renderer zur Darstellung der Listen‐Struktur – ListDataStructure: Container für Listendaten • Zeilen (rows) • Spalten (cols) pt_extlist Komponenten 5 • (M)VC Stack – Abstrakter Controller als ActionController • Enthält alle notwendigen pt_extlist Komponenten • Erzeugt diese aber nicht – Abstrakte View als Basisklasse für Views • Überschreiben von Templates / Partials in TS möglich – FLUID Templates und Partials für Rendering • Eigene Viewhelper (z.B. für Generierung von Links) pt_extlist pt_extlist Lifecycle Controller::_construct() Build FieldConfiguration Controller::resolveViewObjectName( ) LifecycleManagerFactory:: getInstance() Build DataMapper Controller::callAction() SessionPersistenceMananagerFactor y::getInstance() Build DataSource Builder QueryInterpreter ListFactory::createList($dataBackend, $configuration) ConfigurationBuilderFactory:: getInstance($listIdentifier) Build PagerCollection RendererChain::renderList($listData) DataBackendFactory:: createDataBackend($configuration) Build ListeHeader View::render() Build FilterboxCollection pt_extlist Namespaces Idee: Nutze Pfade in GP Vars und Session als Namespace Æ Automatisches Mapping der Parameter pt_extlist Object Lifecycle 1. TYPO3 Seitenaufruf 7. Lifcycle Manager wird beendet 6. Lifcycle Manager schreibt Objektdaten in Session 2. Lifecycle Manager wird gestartet Benutze Object‐ Namespace 3. Session‐persistentes Objekt wird erzeugt 3.1. Objekt‐Daten werden aus Session in Objekt geschrieben 5. Lifcycle Manager bekommt Endsignal 4. Objektdaten werden verändert pt_extlist Object Lifecycle 2 • ObjectNamespace – Objekt‐Typ + Objekt‐Identifier • Beispiel: tx_ptextlist.filters.filterbox1.countryFilter • ObjectData – Array‐Werte, die persistiert werden sollen pt_extlist Konzepte & Paradigmen • Factories zur Objekterzeugung – Reduzierungen der Abhängigkeiten – Trennung von Erzeugung und Logik – Bessere Testbarkeit – Dynamische Ermittlung der konfigurierten Klassen pt_extlist Konzepte & Paradigmen 2 • Erweiterungen von Extbase – Eigene Abstrakte Controller • Alle default Werte in allen Controllern verfügbar – Eigene Abstrakte View • Überschreibung von Templates und Partials durch TS pt_extlist Query Object • Idee: Kapseln von DB‐Anfragen in Objekt • Vorteile: – Unabhängigkeit von Datenquelle (SQL, Extbase) – Mehr Sicherheit • SQL Injection – Einheitliche Schnittstelle für Komponenten • constraints, limits, sorting... pt_extlist Query Object 2 pt_extlist Query Object 3 pt_extlist Query Object 4 • Beispielcode Query‐Erzeugung: protected function buildFilterCriteria( Tx_PtExtlist_Domain_Configuration_Data_Fields_FieldConfig $fieldIdentifier) { $filterValue = '%'.$this->filterValue.'%‘; $criteria = Tx_PtExtlist_Domain_QueryObject_Criteria::like( $this->fieldName, $filterValue); return $criteria; } pt_extlist Query Object 5 • Beispielcode Übersetzung: public function getWhereClauseFromFilter (Tx_PtExtlist_Domain_Model_Filter_AbstractFilter $filter) { $whereClauseFromFilter = $this->queryInterpreter->getCriterias( $filter->getFilterQuery()); return $whereClauseFromFilter; } pt_extlist Eigene Erweiterungen: Filter • Es gibt 3 Basisklassen für Filter: – AbstractFilter: Basisklasse aller Filter – AbstractSingleValueFilter: Basisklasse für Filter ohne Zugriff auf Daten – AbstractOptionsFilter: Basisklasse für Filter mit Zugriff auf Listendaten (Auswahlfilter) pt_extlist Eigene Erweiterungen: Filter 2 • Zu implementierende Funktionen: – SingleValueFilter: • buildFilterCriteria($fieldIdentifier) • Erzeugt ein Filter‐Kriterium für Filterwert – OptionsFilter: • getOptions() • Gibt auswählbare Optionen zurück pt_extlist Eigene Erweiterungen: Filter 3 • Optional zu implementierende Optionen – Session‐Persistenz: • Wenn „mehr als nur ein Wert“ in der Session gespeichert werden soll. • Beispiel: TimeSpan Filter: Von‐ und Bis‐Wert muss gespeichert werden – Breadcrumbs: • Eigene Funktion für die Ausgabe der Breadcrumbs pt_extlist Beispiel: TimeSpanFilter • Funktion: Filter soll Werte von Start bis Stopp filtern – Beispiel: Zeit von 1.1.2010 – 31.12.2010 • Benötigte Filter‐Werte: – FilterValueFrom – FilterValueTo pt_extlist Beispiel: TimeSpanFilter 2 • Session‐Initialisierung: protected function initFilterBySession() { $this->filterValueFrom = array_key_exists( 'filterValueFrom', $this->sessionFilterData) ? $this->sessionFilterData['filterValueFrom'] : $this->filterValueFrom; $this->filterValueTo = array_key_exists( 'filterValueTo', $this->sessionFilterData) ? $this->sessionFilterData['filterValueTo'] : $this->filterValueTo; } pt_extlist Beispiel: TimeSpanFilter 3 • Session‐Persistierung: public function persistToSession() { return array( 'filterValueFrom' => $this->filterValueFrom, 'invert' => $this->invert, 'filterValueTo' => $this->filterValueTo ); } pt_extlist Beispiel: TimeSpanFilter 4 • GP‐Vars auslesen: protected function initFilterByGpVars() { if (array_key_exists( 'filterValueFrom', $this->gpVarFilterData)) { $this->filterValueFrom = $this->gpVarFilterData['filterValueFrom']; } if (array_key_exists( 'filterValueTo', $this->gpVarFilterData)) { $this->filterValueTo = $this->gpVarFilterData['filterValueTo']; } } pt_extlist Beispiel: TimeSpanFilter 5 • Filter‐Criteria erzeugen: protected function buildFilterCriteria($fieldIdentifier) { if ($this->filterValueFrom == ''||$this->filterValueTo == '') { return NULL; } // ... // $criteria1 = Tx_PtExtlist_Domain_QueryObject_Criteria:: greaterThanEquals($fieldName, $this->filterValueFrom); $criteria2 = Tx_PtExtlist_Domain_QueryObject_Criteria:: lessThanEquals($fieldName, $this->filterValueTo); $criteria = Tx_PtExtlist_Domain_QueryObject_Criteria:: andOp($criteria1, $criteria2); return $criteria; } pt_extlist Beispiel: TimeSpanFilter 6 • Breadcrumbs erzeugen: protected function getFieldsForBreadcrumb() { $parentArray = parent::getFieldsForBreadCrumb(); $parentArray['fromValue'] = $this->filterValueFrom; $parentArray['toValue'] = $this->filterValueTo; return $parentArray; } • Verwendung in TS: breadCrumbString { dataWrap = {field:label} is between {field:fromValue} and {field:toValue} } pt_extlist Beispiel: TimeSpanFilter 7 • TS Prototype: dateRange { filterClassName =Tx_PtExtlist_Domain_Model_Filter_TimeSpFilter partialPath = Filter/Range/DateRangeFilter defaultValue = accessGroups = breadCrumbString = TEXT breadCrumbString { dataWrap = {field:label} is between {field:fromValue} and {field:toValue} } } pt_extlist Eigene Erweiterungen: Renderer • Möglichkeit, eigene Renderer zu schreiben • Renderer sind in Chain angeordnet – Werden nacheinander abgearbeitet – Eingangsdatenstruktur = Ausgangsdatenstruktur RendererChain ListDataStructure Renderer 1 ... Renderer n ListDataStructure pt_extlist Eigene Erweiterungen: Renderer 2 pt_extlist 3rd Party‐Extensions • Möglichkeiten der Einbindung: – Als eigenes Content‐Element (trivial) – Als Widget (noch nicht implementiert) – Durch Verwendung von Objekten (hier gezeigt) pt_extlist 3rd Party‐Extensions 2 • listContext – Hält alle relevanten Objekte bereit – Kann mit beliebiger Konfiguration für – Beliebige ListIdentifier erzeugt werden – „Herzstück“ der externen Verwendung von pt_extlist pt_extlist 3rd Party‐Extensions 3 pt_extlist 3rd Party‐Extensions 4 • Erzeugung eines ExtlistContexts aus TS‐array Tx_PtExtlist_ExtlistContext_ExtlistContextFactory:: getContextByCustomConfiguration( $listConfigurationArray, $listIdentifier); pt_extlist 3rd Party‐Extensions 5 • Rendern einer Liste (PHP) public function listAction() { $this->extListContext->getPagerCollection()-> setItemsPerPage($this->getItemsPerPage); $this->view->assign('listData', $this->extListContext->getRenderedListData()); $this->view->assign('pagerCollection', $this->extListContext->getPagerCollection()); $this->view->assign('pager', $this->extListContext->getPager()); } pt_extlist 3rd Party‐Extensions 6 • Rendern einer Liste (FLUID‐Template) <div class="tx-yag-items"> <f:for each="{listData}" key="rowIndex" as="listRow"> <f:render partial="{config.itemListConfig.imageThumbPartial}" arguments="{config: config, image: listRow.image.value, rowIndex: listRow.specialValues.absoluteRowIndex, pager: pager, pagerCollection:pagerCollection}" /> </f:for> </div> pt_extlist 3rd Party‐Extensions 7 • Rendern einer Liste (FLUID‐Partial) <div class="tx-yag-thumb-innerframe"> <div><extlist:link.action action="show" controller="Item" arguments="{itemUid: rowIndex}"> <yag:image item="{image}" resolutionName="thumb" /> </extlist:link.action></div> </div> pt_extlist pt_extlist ViewHelper • Image – Sorting :: Rendert Bilder für Sortierung • Link – Action :: Rendert Link für Actionn – Sorting :: Rendert Linkf für Sortierung • Namespace – FormElementName :: Rendert Formularnamen nach NS – GPArrayViewHelper :: Rendert Argument Array • Uri – Action :: Fügen state‐hash hinzu, wenn in Cache‐Mode pt_extlist