138 3 3MB
German Pages 466 Year 2010
alexander EBNER patrick LOBACHER bernhard ULBRICH
TYPO3 EXTENSIONS PROFESSIONELLE FRONTEND- UND BACKENDPROGRAMMIERUNG
Mit
Extubndase Fluid
Ebner, Lobacher, Ulbrich TYPO3-Extensions
v
Bleiben Sie einfach auf dem Laufenden: www.hanser.de/newsletter Sofort anmelden und Monat für Monat die neuesten Infos und Updates erhalten.
Alexander Ebner Patrick Lobacher Bernhard Ulbrich
TYPO3-Extensions Professionelle Frontend- und Backend-Programmierung
Die Autoren: Alexander Ebner, München Patrick Lobacher, München Bernhard Ulbrich, München
Alle in diesem Buch enthaltenen Informationen, Verfahren und Darstellungen wurden nach bestem Wissen zusammengestellt und mit Sorgfalt getestet. Dennoch sind Fehler nicht ganz auszuschließen. Aus diesem Grund sind die im vorliegenden Buch enthaltenen Informationen mit keiner Verpflichtung oder Garantie irgendeiner Art verbunden. Autoren und Verlag übernehmen infolgedessen keine juristische Verantwortung und werden keine daraus folgende oder sonstige Haftung übernehmen, die auf irgendeine Art aus der Benutzung dieser Informationen – oder Teilen davon – entsteht. Ebenso übernehmen Autoren und Verlag keine Gewähr dafür, dass beschriebene Verfahren usw. frei von Schutzrechten Dritter sind. Die Wiedergabe von Gebrauchsnamen, Handelsnamen, Warenbezeichnungen usw. in diesem Buch berechtigt deshalb auch ohne besondere Kennzeichnung nicht zu der Annahme, dass solche Namen im Sinne der Warenzeichen- und Markenschutz-Gesetzgebung als frei zu betrachten wären und daher von jedermann benutzt werden dürften.
Bibliografische Information Der Deutschen Nationalbibliothek Die Deutsche Nationalbibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über http://dnb.d-nb.de abrufbar.
Dieses Werk ist urheberrechtlich geschützt. Alle Rechte, auch die der Übersetzung, des Nachdruckes und der Vervielfältigung des Buches, oder Teilen daraus, vorbehalten. Kein Teil des Werkes darf ohne schriftliche Genehmigung des Verlages in irgendeiner Form (Fotokopie, Mikrofilm oder ein anderes Verfahren) – auch nicht für Zwecke der Unterrichtsgestaltung – reproduziert oder unter Verwendung elektronischer Systeme verarbeitet, vervielfältigt oder verbreitet werden.
© 2010 Carl Hanser Verlag München Gesamtlektorat: Fernando Schneider Sprachlektorat: Sandra Gottmann, Münster-Nienberge Herstellung: Stefanie König Coverconcept: Marc Müller-Bremer, www rebranding.de, München Coverrealisierung: Stephan Rönigk Datenbelichtung, Druck und Bindung: Kösel, Krugzell Ausstattung patentrechtlich geschützt. Kösel FD 351, Patent-Nr. 0748702 Printed in Germany ISBN 978-3-446-41557-7 www hanser.de/computer
Inhalt
Teil I – Klassische Extensionprogrammierung 1 1.1 1.2 1.3 1.4 1.5
Grundlagen............................................................................................................... 3 Aufbau und Struktur von TYPO3 ............................................................................................3 Aufbau einer Extension............................................................................................................6 Arten und Einteilung von Extensions.......................................................................................7 Der Extension-Key...................................................................................................................8 TYPO3 Coding Guidelines ......................................................................................................9 1.5.1 Namespace ...............................................................................................................10 1.5.2 PHP-Regeln..............................................................................................................11 1.5.3 Dateistruktur.............................................................................................................12 1.5.4 PHP-Syntax ..............................................................................................................15 1.5.5 phpDoc .....................................................................................................................21 1.5.6 Changelog.................................................................................................................22
2 2.1
Eine Extension planen und entwickeln................................................................ 23 Extensions planen ..................................................................................................................23 2.1.1 Wir planen eine Blog-Extension...............................................................................24 Der Kickstarter.......................................................................................................................26 2.2.1 Die Datenbank..........................................................................................................28 2.2.2 Datenbanktabellen und Formulare – eine Erklärung ................................................34 2.2.3 Extend existing Tables .............................................................................................36 2.2.4 Frontend-Plug-ins.....................................................................................................37 2.2.5 Backend-Module ......................................................................................................40 2.2.6 Integrate in existing Modules ...................................................................................41 2.2.7 Clickmenu items.......................................................................................................41 2.2.8 Services ....................................................................................................................42 2.2.9 Static TypoScript code .............................................................................................43
2.2
V
Inhalt
2.3 2.4
3 3.1 3.2 3.3
3.4 3.5 4 4.1 4.2
4.3 4.4
VI
2.2.10 TSconfig................................................................................................................... 43 2.2.11 Die Extension erstellen............................................................................................. 44 Extension-Konfiguration mit ext_emconf.php....................................................................... 45 Die weiteren Dateien der Extension....................................................................................... 50 2.4.1 Verzeichnis doc........................................................................................................ 50 2.4.2 Verzeichnis mod#..................................................................................................... 50 2.4.3 Verzeichnis modfunc#.............................................................................................. 51 2.4.4 Verzeichnis pi#......................................................................................................... 52 2.4.5 Verzeichnis Static..................................................................................................... 52 2.4.6 Datei Changelog....................................................................................................... 53 2.4.7 Datei README.txt .................................................................................................. 53 2.4.8 Datei ext_icon.gif ..................................................................................................... 53 2.4.9 Datei ext_localconf.php ........................................................................................... 53 2.4.10 Datei ext_tables.php ................................................................................................. 53 2.4.11 Datei ext_tables.sql .................................................................................................. 54 2.4.12 Datei ext_tables_static+adt.sql ................................................................................. 55 2.4.13 Dateien Icon_tx_extkey_tabellenname.gif ............................................................... 56 2.4.14 Datei locallang xml .................................................................................................. 56 2.4.15 Datei locallang_db xml ............................................................................................ 56 2.4.16 Datei tca.php ............................................................................................................ 56 Backend-Module erstellen .................................................................................... 65 Module konfigurieren und im Hauptmenü anordnen ............................................................. 65 Einen eigenen Navigationsbaum erstellen ............................................................................. 69 Backend-Modul erstellen ....................................................................................................... 75 3.3.1 Das Modul initialisieren ........................................................................................... 75 3.3.2 Den Modulinhalt aufbauen....................................................................................... 79 3.3.3 Extension-Konfiguration über ext_conf_template.txt .............................................. 80 3.3.4 Backend-Formulare aufrufen ................................................................................... 82 3.3.5 Eine Datensatzliste mit Bearbeitungsfunktionen erstellen........................................ 84 3.3.6 Aufgabe: Module für Kommentare, Blog und Blogroll............................................ 90 Backend User Object – $BE_USER ...................................................................................... 91 Das Systemlog ....................................................................................................................... 92 Frontend-Plug-ins.................................................................................................. 95 Das Frontend-Plug-in im Überblick....................................................................................... 95 Feldinhalte für die Ausgabe aufbereiten .............................................................................. 103 4.2.1 Das Bild für Teaser Image...................................................................................... 104 4.2.2 Ausgabe des Haupttextes in der Listenansicht, wenn erwünscht........................... 105 4.2.3 Haupttext mit RTE formatieren.............................................................................. 105 4.2.4 Haupttext statt Teasertext anzeigen, falls dieser nicht verfügbar ist...................... 106 4.2.5 Verlinken des Autorennamens mit der Mail-Adresse des Autors.......................... 106 4.2.6 Kategorien als Namen anzeigen und verlinken (Relationen).................................. 107 HTML-Templates für das Plug-in........................................................................................ 109 Die Kommentarfunktion mit AJAX und eID ....................................................................... 114 4.4.1 Ausgabe vorhandener Kommentare ....................................................................... 115
Inhalt
4.5 4.6 4.7 5 5.1 5.2
5.3
4.4.2 Das Kommentarformular hinzufügen .....................................................................118 Was sind Hooks?..................................................................................................................123 Flexforms .............................................................................................................................125 4.6.1 Erzeugen der Flexform ...........................................................................................126 Das Plug-in pi2.....................................................................................................................132 Dokumentation und Abschluß ............................................................................ 133 Code dokumentieren mit extdeveval ....................................................................................133 Extension-Dokumentation schreiben....................................................................................134 5.2.1 Die Vorlage ............................................................................................................135 5.2.2 Der Aufbau der Dokumentation .............................................................................135 5.2.3 Vorlagenstile ..........................................................................................................136 5.2.4 Die Dokumentation verfassen ................................................................................136 Upload ins TER....................................................................................................................137
Teil II – Funktionsreferenz zur klassischen Extensionprogrammierung 6 6.1
6.2
Datenbank ............................................................................................................ 141 $GLOBALS['TYPO3_DB'] .................................................................................................141 6.1.1 exec_SELECTquery ...............................................................................................141 6.1.2 exec_SELECT_queryArray....................................................................................141 6.1.3 exec_SELECTgetRows ..........................................................................................142 6.1.4 exec_SELECT_mm_query.....................................................................................142 6.1.5 exec_INSERTquery................................................................................................143 6.1.6 exec_UPDATEquery..............................................................................................143 6.1.7 exec_DELETEquery...............................................................................................143 6.1.8 sql_fetch_assoc.......................................................................................................143 6.1.9 sql_fetch_row .........................................................................................................144 6.1.10 searchQuery............................................................................................................144 6.1.11 listQuery .................................................................................................................144 6.1.12 splitGroupOrderLimit.............................................................................................145 6.1.13 quoteStr ..................................................................................................................145 6.1.14 fullQuoteStr............................................................................................................145 6.1.15 fullQuoteArray .......................................................................................................146 6.1.16 escapeStrForLike....................................................................................................146 6.1.17 cleanIntArray..........................................................................................................147 6.1.18 cleanIntList.............................................................................................................147 6.1.19 debug_lastBuiltQuery.............................................................................................147 tslib_pibase ..........................................................................................................................148 6.2.1 pi_exec_query ........................................................................................................148 6.2.2 pi_getPidList ..........................................................................................................149 6.2.3 pi_getRecord ..........................................................................................................150 6.2.4 pi_prependFieldsWithTable ...................................................................................150
VII
Inhalt
VIII
6.3
cObj ..................................................................................................................................... 151 6.3.1 DBgetDelete........................................................................................................... 151 6.3.2 DBgetInsert ............................................................................................................ 151 6.3.3 DBgetUpdate.......................................................................................................... 152 6.3.4 enableFields ........................................................................................................... 153
7 7.1
Dateisystem.......................................................................................................... 155 t3lib_div............................................................................................................................... 155 7.1.1 dirname .................................................................................................................. 155 7.1.2 fixWindowsFilePath............................................................................................... 155 7.1.3 formatSize .............................................................................................................. 156 7.1.4 get_dirs................................................................................................................... 156 7.1.5 getAllFilesAndFoldersInPath................................................................................. 157 7.1.6 getFileAbsFileName............................................................................................... 158 7.1.7 getFilesInDir .......................................................................................................... 158 7.1.8 getURL................................................................................................................... 159 7.1.9 isAbsPath ............................................................................................................... 159 7.1.10 isAllowedAbsPath.................................................................................................. 159 7.1.11 mkdir ...................................................................................................................... 160 7.1.12 mkdir_deep............................................................................................................. 160 7.1.13 removePrefixPathFromList .................................................................................... 160 7.1.14 resolveBackPath..................................................................................................... 161 7.1.15 rmdir....................................................................................................................... 161 7.1.16 split_fileref ............................................................................................................. 162 7.1.17 tempnam................................................................................................................. 162 7.1.18 unlink_tempfile ...................................................................................................... 162 7.1.19 upload_copy_move ................................................................................................ 162 7.1.20 upload_to_tempfile ................................................................................................ 163 7.1.21 verifyFilenameAgainstDenyPattern ....................................................................... 163 7.1.22 writeFile ................................................................................................................. 164 7.1.23 writeFileToTypo3tempDir ..................................................................................... 164
8 8.1
Strings, Arrays und Umgebungsvariablen ........................................................ 165 Allgemeine Funktionen........................................................................................................ 165 8.1.1 _GET...................................................................................................................... 165 8.1.2 _GETset ................................................................................................................. 165 8.1.3 _GP ........................................................................................................................ 166 8.1.4 _POST.................................................................................................................... 166 8.1.5 callUserFunction .................................................................................................... 166 8.1.6 clientInfo ................................................................................................................ 167 8.1.7 compat_version ...................................................................................................... 167 8.1.8 compileSelectedGetVarsFromArray ...................................................................... 168 8.1.9 getHostname........................................................................................................... 168 8.1.10 getIndpEnv ............................................................................................................. 168 8.1.11 getThisUrl .............................................................................................................. 168 8.1.12 linkThisScript......................................................................................................... 169
Inhalt
8.2
8.1.13 linkThisUrl .............................................................................................................169 8.1.14 locationHeaderUrl ..................................................................................................169 8.1.15 makeInstance..........................................................................................................170 8.1.16 makeInstanceService ..............................................................................................170 8.1.17 rmFromList.............................................................................................................170 8.1.18 sysLog ....................................................................................................................171 String-Funktionen ................................................................................................................171 8.2.1 calcParenthesis .......................................................................................................171 8.2.2 cmpFQDN ..............................................................................................................171 8.2.3 cmpIP .....................................................................................................................172 8.2.4 convUmlauts...........................................................................................................172 8.2.5 csvValues ...............................................................................................................172 8.2.6 deHSCentities.........................................................................................................173 8.2.7 expandList ..............................................................................................................173 8.2.8 fixed_lgd ................................................................................................................173 8.2.9 fixed_lgd_pre .........................................................................................................174 8.2.10 formatForTextarea..................................................................................................174 8.2.11 generateRandomBytes............................................................................................174 8.2.12 get_tag_attributes ...................................................................................................175 8.2.13 htmlspecialchars_decode ........................................................................................175 8.2.14 implodeArrayForUrl...............................................................................................175 8.2.15 implodeAttributes...................................................................................................176 8.2.16 inList ......................................................................................................................176 8.2.17 int_from_ver...........................................................................................................177 8.2.18 intInRange ..............................................................................................................177 8.2.19 intval_positive ........................................................................................................178 8.2.20 isFirstPartOfStr.......................................................................................................178 8.2.21 md5int ....................................................................................................................178 8.2.22 milliseconds............................................................................................................179 8.2.23 modifyHTMLColor ................................................................................................179 8.2.24 modifyHTMLColorAll ...........................................................................................179 8.2.25 normalizeIPv6 ........................................................................................................180 8.2.26 removeXSS.............................................................................................................180 8.2.27 revExplode .............................................................................................................180 8.2.28 rm_endcomma ........................................................................................................181 8.2.29 shortMD5 ...............................................................................................................181 8.2.30 split_tag_attributes .................................................................................................181 8.2.31 splitCalc..................................................................................................................182 8.2.32 strtolower................................................................................................................183 8.2.33 strtoupper................................................................................................................183 8.2.34 substUrlsInPlainText ..............................................................................................183 8.2.35 testInt......................................................................................................................184 8.2.36 trimExplode............................................................................................................184 8.2.37 uniqueList...............................................................................................................185 8.2.38 validEmail ..............................................................................................................185 8.2.39 validIP ....................................................................................................................185
IX
Inhalt
8.3
8.4
9 9.1 9.2
9.3
10 10.1
X
8.2.40 validIPv4 ................................................................................................................ 186 8.2.41 validIPv6 ................................................................................................................ 186 Array-Funktionen................................................................................................................. 186 8.3.1 addSlashesOnArray................................................................................................ 186 8.3.2 array_merge ........................................................................................................... 187 8.3.3 array_merge_recursive_overrule............................................................................ 187 8.3.4 array2json............................................................................................................... 188 8.3.5 array2xml ............................................................................................................... 188 8.3.6 arrayToLogString ................................................................................................... 189 8.3.7 explodeUrl2Array .................................................................................................. 190 8.3.8 inArray ................................................................................................................... 190 8.3.9 print_array.............................................................................................................. 190 8.3.10 removeArrayEntryByValue.................................................................................... 191 8.3.11 slashArray .............................................................................................................. 191 8.3.12 view_array.............................................................................................................. 192 8.3.13 xml2array ............................................................................................................... 192 8.3.14 xml2tree ................................................................................................................. 193 8.3.15 xmlGetHeaderAttribs ............................................................................................. 194 String-Funktionen in Frontend-Plug-ins .............................................................................. 195 8.4.1 calcAge .................................................................................................................. 195 8.4.2 checkEmail............................................................................................................. 195 8.4.3 codeString .............................................................................................................. 195 8.4.4 encryptEmail .......................................................................................................... 196 8.4.5 HTMLcaseshift ...................................................................................................... 196 8.4.6 keywords ................................................................................................................ 196 8.4.7 linebreaks ............................................................................................................... 197 8.4.8 processParams ........................................................................................................ 197 8.4.9 uniqueHash............................................................................................................. 198 8.4.10 URLqMark ............................................................................................................. 198 Bilder .................................................................................................................... 199 Einbinden............................................................................................................................. 199 Bearbeiten ............................................................................................................................ 200 9.2.1 Bild umrechnen (fürs Web optimieren).................................................................. 200 9.2.2 Abmessungen ändern ............................................................................................. 201 9.2.3 Zuschneiden ........................................................................................................... 201 9.2.4 Graustufen.............................................................................................................. 202 Erzeugen .............................................................................................................................. 203 9.3.1 Bild in bestehendes Bild einfügen.......................................................................... 203 9.3.2 Text erzeugen......................................................................................................... 204 AJAX im Frontend ............................................................................................... 205 eID ....................................................................................................................................... 205 10.1.1 Konfiguration ......................................................................................................... 205 10.1.2 Basisdatei ............................................................................................................... 206
Inhalt 10.2
Zusammenspiel AJAX & eID ..............................................................................................206 10.2.1 Aufbau der XML-Response....................................................................................206 10.2.2 AJAX-Request und Verarbeitung...........................................................................207
11 11.1
Frontend-Plug-ins ................................................................................................ 209 Cache ...................................................................................................................................209 11.1.1 cacheExpires...........................................................................................................209 11.1.2 clearPageCacheContent..........................................................................................209 11.1.3 clearPageCacheContent_pidList.............................................................................209 11.1.4 get_cache_timeout..................................................................................................210 11.1.5 set_cache_timeout_default .....................................................................................210 11.1.6 set_no_cache ..........................................................................................................210 Content-Elemente.................................................................................................................211 11.2.1 cImage ....................................................................................................................211 11.2.2 cleanFormName .....................................................................................................211 11.2.3 cObjGet ..................................................................................................................211 11.2.4 cObjGetSingle ........................................................................................................212 11.2.5 currentPageUrl........................................................................................................212 11.2.6 fileResource............................................................................................................213 11.2.7 getImgResource......................................................................................................213 11.2.8 getSlidePids............................................................................................................213 11.2.9 gifBuilderTextBox..................................................................................................214 11.2.10 stdWrap ..................................................................................................................214 Links ....................................................................................................................................215 11.3.1 baseUrlWrap...........................................................................................................215 11.3.2 getMailTo ...............................................................................................................215 11.3.3 getTypoLink ...........................................................................................................216 11.3.4 getTypoLink_URL .................................................................................................216 11.3.5 http_makelinks .......................................................................................................217 11.3.6 imageLinkWrap......................................................................................................217 11.3.7 mailto_makelinks ...................................................................................................218 11.3.8 pi_getPageLink.......................................................................................................218 11.3.9 pi_linkToPage ........................................................................................................218 11.3.10 pi_linkTP................................................................................................................219 11.3.11 pi_linkTP_keepPIvars ............................................................................................219 11.3.12 pi_linkTP_keepPIvars_url ......................................................................................219 11.3.13 pi_openAtagHrefInJSwindow ................................................................................220 11.3.14 prefixLocalAnchorsWithScript...............................................................................220 Listen ...................................................................................................................................220 11.4.1 pi_list_browseresults ..............................................................................................221 11.4.2 pi_list_linkSingle....................................................................................................222 11.4.3 pi_list_makelist ......................................................................................................222 11.4.4 pi_list_modeSelector ..............................................................................................223 11.4.5 pi_list_searchBox ...................................................................................................223
11.2
11.3
11.4
XI
Inhalt 11.5
11.6
11.7
11.8
XII
JavaScript............................................................................................................................. 224 11.5.1 additionalHeaderData............................................................................................. 224 11.5.2 additionalJavaScript ............................................................................................... 224 11.5.3 JSeventFuncCalls ................................................................................................... 225 11.5.4 minifyJavaScript .................................................................................................... 225 11.5.5 quoteJSvalue .......................................................................................................... 226 11.5.6 rawUrlEncodeJS..................................................................................................... 226 11.5.7 setJS ....................................................................................................................... 227 11.5.8 wrapJS.................................................................................................................... 227 CSS ...................................................................................................................................... 228 11.6.1 additionalCSS......................................................................................................... 228 11.6.2 additionalHeaderData............................................................................................. 228 11.6.3 pi_getClassName.................................................................................................... 229 11.6.4 pi_setClassStyle ..................................................................................................... 229 11.6.5 setCSS .................................................................................................................... 229 Mehrsprachigkeit ................................................................................................................. 230 11.7.1 getLLL ................................................................................................................... 230 11.7.2 pi_getLL................................................................................................................. 230 11.7.3 readLLfile............................................................................................................... 231 Umgebungsvariablen und allgemeine Funktionen ............................................................... 232 11.8.1 absRefPrefix........................................................................................................... 232 11.8.2 additionalHeaderData............................................................................................. 232 11.8.3 all ........................................................................................................................... 232 11.8.4 anchorPrefix ........................................................................................................... 233 11.8.5 applicationData ...................................................................................................... 233 11.8.6 ATagParams........................................................................................................... 233 11.8.7 baseUrl ................................................................................................................... 234 11.8.8 baseUrlWrap .......................................................................................................... 234 11.8.9 beUserLogin........................................................................................................... 234 11.8.10 clientInfo ................................................................................................................ 234 11.8.11 content.................................................................................................................... 235 11.8.12 defaultBodyTag...................................................................................................... 235 11.8.13 domainStartPage .................................................................................................... 235 11.8.14 extTarget ................................................................................................................ 236 11.8.15 fePreview ............................................................................................................... 236 11.8.16 id ........................................................................................................................... 236 11.8.17 imagesOnPage........................................................................................................ 237 11.8.18 intTarget ................................................................................................................. 237 11.8.19 lang......................................................................................................................... 237 11.8.20 lastImageInfo ......................................................................................................... 238 11.8.21 loginUser................................................................................................................ 238 11.8.22 no_cache................................................................................................................. 238 11.8.23 page ........................................................................................................................ 239 11.8.24 printError................................................................................................................ 239 11.8.25 rootLine.................................................................................................................. 240 11.8.26 siteScript ................................................................................................................ 240
Inhalt 11.8.27 tmpl->config, tmpl->setup......................................................................................241 11.8.28 type.........................................................................................................................241 11.8.29 TYPO3_CONF_VARS ..........................................................................................241 11.8.30 uniqueString ...........................................................................................................242 11.9 Konfiguration mit Flexforms ...............................................................................................242 11.9.1 Erstellen einer Plug-in_Flexform ...........................................................................242 11.9.2 Auslesen der Formulardaten...................................................................................243 11.10 Konfiguration mit TypoScript ..............................................................................................244 11.11 Konfiguration im Extension-Manager..................................................................................244 12 12.1 12.2
13 13.1
13.2
13.3 13.4 13.5
Frontend-User & Sessions .................................................................................. 245 Frontend-User ......................................................................................................................245 12.1.1 Daten des aktuell angemeldeten Users ...................................................................245 Sessions................................................................................................................................246 12.2.1 Daten speichern ......................................................................................................246 12.2.2 Daten auslesen........................................................................................................246 12.2.3 Warenkorb aufbauen ..............................................................................................246 Backend & Services............................................................................................. 249 Eigene Flexforms .................................................................................................................249 13.1.1 Mehrsprachigkeit....................................................................................................250 13.1.2 Tabs ........................................................................................................................251 13.1.3 Elemente.................................................................................................................252 13.1.4 Flexform-Daten im Frontend..................................................................................256 Backend-Module..................................................................................................................257 13.2.1 Dokumententypen für $this->doc ...........................................................................257 13.2.2 TypoScript einer Seite auslesen..............................................................................257 13.2.3 AJAX im Backend..................................................................................................257 Services................................................................................................................................259 cli .........................................................................................................................................259 Debugging............................................................................................................................260 13.5.1 debug ......................................................................................................................260 13.5.2 debug_ordvalue ......................................................................................................261 13.5.3 debug_trail..............................................................................................................261 13.5.4 debugRows .............................................................................................................261 13.5.5 devLog....................................................................................................................262
Teil III – Extbase und Fluid 14 14.1
Der neue Weg der Extension-Programmierung ................................................ 265 Grundlagen der objektorientierten Programmierung............................................................267 14.1.1 Klassen und Objekte...............................................................................................267 14.1.2 Vererbung von Klassen ..........................................................................................271
XIII
Inhalt
14.2
15 15.1 15.2 15.3 15.4
15.5
15.6
15.7
16 16.1
XIV
14.1.3 Kontrollierte Vererbung – abstrakte und finale Klassen......................................... 273 14.1.4 Sichtbarkeiten: public, private und protected ......................................................... 274 14.1.5 Interfaces................................................................................................................ 275 14.1.6 Type Hints.............................................................................................................. 277 14.1.7 Statische Methoden und Eigenschaften.................................................................. 277 14.1.8 Namespaces............................................................................................................ 278 Neue Konzepte..................................................................................................................... 279 14.2.1 Domain Driven Design........................................................................................... 280 14.2.2 Model-View-Controller.......................................................................................... 281 14.2.3 Modellierung.......................................................................................................... 282 14.2.4 Gemeinsamens Vokabular – Ubiquitous Language................................................ 282 14.2.5 Die Elemente des Modells...................................................................................... 285 Ein Rundgang durchs System............................................................................ 287 Installation von Extbase und Fluid....................................................................................... 287 Installation der Extension blog_example ............................................................................. 289 Datenstruktur im Blog-Example .......................................................................................... 291 Namenskonventionen........................................................................................................... 293 15.4.1 Verzeichnis- und Dateinamen ................................................................................ 294 15.4.2 Klassennamen ........................................................................................................ 294 15.4.3 Controller und Actions ........................................................................................... 295 Die Dateistruktur im Extension-Root-Verzeichnis .............................................................. 295 15.5.1 Die Datei ext_emconf.php...................................................................................... 296 15.5.2 Die Datei ext_tables.php ........................................................................................ 297 15.5.3 Die Datei ext_localconf.php................................................................................... 301 15.5.4 Die Dateien ext_tables.sql und ext_icon.gif ........................................................... 302 Die Verzeichnisstruktur ....................................................................................................... 302 15.6.1 Das Verzeichnis Classes......................................................................................... 303 15.6.2 Das Verzeichnis Configuration .............................................................................. 304 15.6.3 Das Verzeichnis Module ........................................................................................ 305 15.6.4 Das Verzeichnis Resources .................................................................................... 305 15.6.5 Weitere Verzeichnisse............................................................................................ 305 Der prinzipielle Ablauf ........................................................................................................ 305 15.7.1 Aufruf des Dispatchers (Schritt 1).......................................................................... 306 15.7.2 Aufruf des Controllers (Schritt 2)........................................................................... 309 15.7.3 Ansprechen des Respositorys (Schritt 3)................................................................ 309 15.7.4 Zurückliefern der Blog-Objekte (Schritt 4) ............................................................ 309 15.7.5 Das Objekt wird dem View zugeordnet (Schritt 5) ................................................ 311 15.7.6 Rückgabe der Template-Ausgabe an den Controller (Schritt 6)............................. 313 15.7.7 Rückgabe der Ausgabe an den Dispatcher (Schritt 7) ............................................ 314 15.7.8 Rückgabe der Ausgabe an TYPO3 (Schritt 8)........................................................ 314 Entwicklung eines eigenen Plug-ins.................................................................. 315 Aufbau einer minimal funktionstüchtigen Extension........................................................... 315 16.1.1 Extension-Key........................................................................................................ 315 16.1.2 Verzeichnisse anlegen ............................................................................................ 316
Inhalt
16.2 16.3 16.4
16.5 16.6 16.7 16.8
16.9 16.10 16.11 16.12
16.13
16.14 16.15 16.16 16.17 16.18
16.1.3 Die Datei ext_emconf.php......................................................................................316 16.1.4 Die Dateien ext_localconf.php und ext_tables.php ................................................317 16.1.5 Einrichten eines Standard-Controllers ....................................................................318 16.1.6 Installieren der Extension und das erste Erfolgserlebnis ........................................319 Hinzufügen eines Views.......................................................................................................320 Entitäten einführen ...............................................................................................................322 Daten persistieren (Datenspeicher).......................................................................................324 16.4.1 Datenbankstruktur – die Datei ext_tables.sql .........................................................325 16.4.2 Datenbankstruktur – das TCA ................................................................................329 Anlegen eines Repositorys ...................................................................................................333 Anlegen einer neuen Action.................................................................................................335 16.6.1 Anlegen der Action addAction() ............................................................................336 Daten per Formular eingeben und auswerten .......................................................................337 Objekte aus dem Repository entfernen.................................................................................338 16.8.1 Zufügen der Action delete in der Konfiguration.....................................................338 16.8.2 Anpassen der Template-Datei index.html...............................................................338 Update von Objekten............................................................................................................339 16.9.1 Edit- und Update-Action hinzufügen......................................................................339 Der Query-Manager .............................................................................................................341 Eingabevalidierung ..............................................................................................................343 Validatoren...........................................................................................................................343 16.12.1 Vordefinierte Validatoren.......................................................................................343 16.12.2 Eigene Validatoren .................................................................................................344 16.12.3 Ausgabe der Fehler.................................................................................................347 16.12.4 Optionale Argumente .............................................................................................347 Relationen zu anderen Tabellen ...........................................................................................348 16.13.1 Erweiterung des TCA .............................................................................................348 16.13.2 Die Domain-Klasse Tx_Simpleblog_Domain_Model_Post ...................................349 16.13.3 Registrieren der Actions in der Datei ext_localconf.php ........................................350 16.13.4 Erstellung des Post-Controllers ..............................................................................350 16.13.5 Neue Templates und Template-Änderungen ..........................................................353 16.13.6 Ändern der Blog-Identity........................................................................................354 16.13.7 Aufruf der Extension im Frontend..........................................................................356 Relationen zu anderen Tabellen m:n ....................................................................................356 Mehrsprachigkeit zufügen....................................................................................................361 Konfiguration mittels TypoScript ........................................................................................363 Backend-Module mit Extbase ..............................................................................................365 Der Extbase-Kickstarter .......................................................................................................366 16.18.1 Installation des Extbase-Kickstarters......................................................................367 16.18.2 Überblick über den Arbeitsbereich .........................................................................368 16.18.3 Eingabe der Extension-Konfiguration ....................................................................369 16.18.4 Modellierung ..........................................................................................................370 16.18.5 Anlegen des Post-Objekts.......................................................................................372 16.18.6 Anlegen des Tag-Objekts .......................................................................................372 16.18.7 Relationen festlegen ...............................................................................................373
XV
Inhalt 16.19 Weitere Extbase-Interna....................................................................................................... 374 16.19.1 StoragePid .............................................................................................................. 374 16.19.2 MVC-Request ........................................................................................................ 376 16.19.3 FlashMessages realisieren ...................................................................................... 377 17 17.1 17.2
17.3
17.4
17.5
17.6 17.7
Die Fluid-Template-Engine.................................................................................. 379 Vorbereitung ........................................................................................................................ 380 Basissyntax und einfache Ausgabe ...................................................................................... 382 17.2.1 Arrays..................................................................................................................... 382 17.2.2 Objekte................................................................................................................... 383 Fluid ViewHelper-Syntax .................................................................................................... 384 17.3.1 Namespace (Namensraum)..................................................................................... 384 17.3.2 Argumente.............................................................................................................. 385 ViewHelper-Übersicht ......................................................................................................... 387 17.4.1 alias ........................................................................................................................ 387 17.4.2 base ........................................................................................................................ 388 17.4.3 cObject ................................................................................................................... 388 17.4.4 count....................................................................................................................... 389 17.4.5 cycle ....................................................................................................................... 389 17.4.6 debug...................................................................................................................... 390 17.4.7 else ......................................................................................................................... 390 17.4.8 for........................................................................................................................... 390 17.4.9 form........................................................................................................................ 391 17.4.10 format..................................................................................................................... 402 17.4.11 groupedFor ............................................................................................................. 406 17.4.12 if ........................................................................................................................... 407 17.4.13 image...................................................................................................................... 408 17.4.14 layout...................................................................................................................... 409 17.4.15 link ......................................................................................................................... 409 17.4.16 render ..................................................................................................................... 414 17.4.17 renderFlashMessages ............................................................................................. 414 17.4.18 section .................................................................................................................... 415 17.4.19 then......................................................................................................................... 415 17.4.20 translate .................................................................................................................. 415 17.4.21 uri ........................................................................................................................... 416 Erstellen eines eigenen ViewHelpers................................................................................... 416 17.5.1 Der Dummytext-ViewHelper ................................................................................. 417 17.5.2 Zugriff auf die übergebenen Argumente ................................................................ 418 17.5.3 Zufügen von Argumenten ...................................................................................... 419 17.5.4 Tag-basierende ViewHelper................................................................................... 419 17.5.5 Der Variablen-Container ........................................................................................ 420 Verwendung von Fluid in klassischen Extensions ............................................................... 421 Layouts und Partials............................................................................................................. 423
Register............................................................................................................................ 427
XVI
Vorwort Das letzte Jahr war voll von Veränderungen und Neuerungen, die es nicht ganz leicht machten, dieses Buch zu vollenden. Ich danke daher unserem Lektor Fernando Schneider für seine Engelsgeduld mit uns. Besonderer Dank gebührt Börni, der sich in einer Nachtund-Nebel-Aktion ins Boot gewuchtet hat, um mit Patrick und mir dieses Projekt zu meistern. Seine Engagement und seine Ideen haben dem Buch den richtigen Impuls gegeben. Ich danke Pat für die vielen guten Ideen und die Rolle als treibende Kraft in so vielen Aspekten meiner beruflichen und auch privaten Laufbahn. Ich danke ebenso meinen Eltern und meiner Großmutter für ihren Rückhalt. Auch meinen Kolleginnen und Kollegen bei FTI, Chris, Bogomip, Matthias, Vivian, Silke, Nanni, Mirja, Emilios, Murat, Alf, Marita und allen anderen möchte ich meinen Dank aussprechen, haben sie mir doch im vergangenen Jahr ein neues berufliches, aber auch freundschaftliches Zuhause gegeben, in dem ich mich pudelwohl fühle. Meinen Teil widme ich meinem Großvater. Das hier hätte Dir gefallen.
Alexander Ebner
Dieses Buch hat eine lange und vielleicht auch etwas schwere Geburt hinter sich. Aber es hat sich durchaus gelohnt, so lange damit zu warten. Nur so hatten wir die Chance die Themen Extbase & Fluid hineinzunehmen, die im ursprünglichen Manuskript nicht vorgesehen waren, da diese hoch spannenden Technologien zu jenem Zeitpunkt noch nicht zur Verfügung standen. Allein dieser Umstand, so unsere Hoffnung, wird manchem Leser die lange Wartezeit im Nachhinein vielleicht ein wenig versüßen.
XVII
Vorwort Mein Dank geht natürlich auch an meinen Freund Alex, der dieses Projekt trotz widriger Umstände und meiner Gängeleien bestens gemeistert hat, und auch Börni, den wir komplett ins kalte Wasser schmissen, indem wir ihn fragten, ob er sich nicht zu uns gesellen will. Er hat seinen Erstling mit Bravour gemeistert. Es hat mir sehr viel Spaß gemacht, dieses Projekt mit Euch zu stemmen. Vor allem danke ich Fernando, unserem geschätzten Lektor. Er hat stets an uns und dieses Buch geglaubt und es so überhaupt noch möglich gemacht. Mein größter Dank allerdings gebührt der Liebe meines Lebens – meiner Frau Marina. Ohne Ihre Geduld und Ihren Glauben an mich und meine Arbeit hätte ich auch dieses Buch sicherlich nie zu Ende bringen können. Unzählige Stunden hat Sie (wieder einmal) auf mich verzichtet und ist vielleicht nun, da dieses Buch das Licht der Welt erblickt hat, etwas stolz. Und wenn sich auch am Ende nur eine kurze Erwähnung im Vorwort dazu findet – bei jedem Buchstabe, bei jedem Satz und bei jeder Seite waren meine Gedanken stets auch bei Dir.
Patrick Lobacher
Zunächst einmal möchte ich meinen beiden Autorenkollegen Patrick und Alex für das große Vertrauen danken, das sie in mich hatten – auf ihre ganz unkomplizierte und lockere Art und Weise haben sie mich mit ins Boot genommen. Alleine hätte ich mir das sicherlich nie zugetraut - vielen vielen Dank dafür! Es war für mich ein sehr spannendes, lehrreiches aber vor allem auch schönes erstes Buchprojekt. Mein größter Dank gilt aber natürlich meiner geliebten Frau Silvi. Sie hat mich von Anfang an zu hundert Prozent unterstützt und hat immer daran geglaubt, dass ich diese Aufgabe schaffen werde. Von unserer ohnehin schon knappen gemeinsamen Zeit hat sie mir an vielen Tagen und Wochenenden den Rücken vollkommen frei gehalten – ohne diese Unterstützung, mein Bär, hätte ich es sicher nie geschafft! Und schließlich widme ich dieses Buch unserer süßen Maus Marie. Auch sie musste viele viele Stunden auf ihren Papa verzichten und hat es sogar gelernt, die Tür zum Büro geschlossen zu lassen. Vielleicht findet ja auch sie eines Tages Gefallen an TYPO3 – ich arbeite daran ;-)
Bernhard Ulbrich
XVIII
I Teil I – Klassische Extensionprogrammierung
1 1 1.1
Grundlagen
Aufbau und Struktur von TYPO3 Um Extensions für TYPO3 entwickeln zu können, müssen Sie über den grundsätzlichen Aufbau von TYPO3 Bescheid wissen. Dazu gehört zum Beispiel, in welcher Reihenfolge TYPO3 die einzelnen Schritte, die nötig sind, um eine Webseite zu erstellen, abarbeitet. Der schematische Aufbau geht vom Webbrowser aus. Damit rufen Sie entweder das Backend oder das Frontend auf. Beide greifen wiederum auf die Extensions zu, die in dem System installiert sind. Selbst das CMS ist als Extension realisiert. Alle Extensions greifen über die Extension-API auf den TYPO3-Kern (Core) zu. Dieser beinhaltet nur die grundlegenden Funktionen. Der Kern, wie auch alle Extensions, sind in der Programmiersprache PHP geschrieben. Als Basis dienen ein Webserver (z.B. Apache, lighttpd, IIS) und eine Datenbank (z.B. MySQL, Oracle, PostreSQL). Es ist möglich, die TYPO3-Extension-API zu umgehen und beispielsweise Datenbankzugriffe nativ in PHP zu schreiben. Aber dieses „Zu-Fuß-Gehen“ ist nicht empfehlenswert. Über die API stehen Ihnen weitere Features wie Abstraktion, Validierungen etc. zur Verfügung. Um beim Beispiel Datenbankzugriff zu bleiben, über die API-Funktionen kann eine Extension auf verschiedenen Datenbanksystemen verwendet werden. Wenn Sie die mysql-Funktionen von PHP direkt verwenden, wird Ihre Extension auch nur mit MySQL zusammenarbeiten. Daher ist die API ein sehr wichtiger Schritt im Ablauf. Sehr interessant ist allerdings, was im Einzelnen denn nun genau passiert, wenn eine Webseite im Frontend aufgerufen wird. Jeder Aufruf im Frontend beginnt mit der Datei index.php im Rootverzeichnis (DocumentRoot). Ganz egal, ob Sie eine Seite tief im Seitenbaum aufrufen und wie viele Parameter Sie der URL anhängen, am Ende rufen Sie doch nur diese eine Datei auf. Das gilt auch beim Einsatz von Extensions wie realURL und CoolURI, die semantische URLs erzeugen. Durch die Direktiven der .htacces-Datei wird dennoch auf die index-php zugegriffen. In dieser ist der Pfad zur TypoScript-Library (PATH_tslib) hinterlegt, die damit inkludiert wird. Als Nächstes wird die Datei in-
3
1 Grundlagen dex_ts.php aus der Extension cms eingebunden, die den Rest der Ablaufsteuerung übernimmt. Ist diese nicht verfügbar, quittiert der Server die Anfrage mit einer Fehlermeldung und widmet sich anderen Dingen. In der index_ts.php kommt es zu folgendem Ablauf im Frontend-Rendering-Prozess: 1. Die Umgebungsparameter wie Betriebsystem, Webserver und Art der PHP-Unterstützung werden ermittelt. 2. Die Pfade zum typo3conf- und t3lib-Verzeichnis werden bestimmt. 3. Der Time-Tracker (PATH_t3lib.’class.t3lib_timetrack.php) startet. Der Time-Tracker loggt die Parse-Zeiten und Kommentare. Diese werden im Admin-Panel zur Verfügung gestellt. 4. Die obligatorischen Klassen _t3lib_div, die diverse allgemeine Funktionen zur Verfügung stellt, und t3lib_extmgm, die das Extension-Handling durchführt, werden geladen. 5. Nun beginnt die Konfigurationsphase. Es wird eine Standardkonfiguration aus PATH_t3lib.config_default.php geladen. Dann wird die eigentliche Konfigurationsdatei typo3conf/localconf.php aufgerufen. Als Letztes werden noch die Konfigurationen aus den Extensions geladen. Diese befinden sich in den ext_ localconf.php-Dateien in den jeweiligen Extension-Verzeichnissen. Der Datenbankzugriff aufgrund der Konfiguration wird überprüft. Ist auch die Extension cms korrekt geladen, kann es weiter gehen. 6. Wird als GET- oder POST-Parameter die eID übergeben, wird diese nun ausgewertet. Dazu ist ein Ausstiegspunkt definiert, der den Frontend-Rendering-Prozess abbricht. Der eID-Parameter kommt beispielsweise bei AJAX-Requests zum Tragen, wenn nicht die komplette Seite, sondern nur Teile des Inhalts benötigt werden. Der Parameter beinhaltet die eine Klasse, die an dieser Stelle aufgerufen wird und die restliche Ausgabe erledigt. Diese Klasse lädt die eID-Helper-Klasse nach, die eine Datenbankunterstützung zur Verfügung stellt und den möglichen Frontend-User definiert. 7. Wird der Vorgang nicht durch einen eID-Prozess abgebrochen, wird er fortgesetzt, indem folgende Frontend-Bibliotheken geladen werden:
PATH_tslib.’class.tslib_fe.php’
Klasse für das TypoScript-basierte Frontend
PATH_tslib.’class.tslib_page.php’
Klasse für die Seitenfunktionen
PATH_tslib.’class.tslib_userauth.php’
Klasse für die Authentifizierung von FE-Usern
PATH_tslib.’class.tslib_feuserauth.php’
Klasse für die Frontend-Session und das Login
PATH_tslib.’class.tslib_fe.php’
Klasse für die Template-Verarbeitung
PATH_tslib.’class.tslib_cs.php’
Klasse für die Zeichenkonvertierung von und zu UTF-8
4
1.1 Aufbau und Struktur von TYPO3 8. Initialisierung und Befüllung des $TSFE-Objektes (TypoScript-Frontend). Erste Werte, mit denen es befüllt wird, sind einige GBVars (GET-/POST-Variablen): id, type, no_cache, cHash, jumpurl, MP und RDCT. 9. Bei gesetztem RDCT-Parameter wird mittels des zugehörigen MD5-Hashwertes der entsprechende Link aus der Datenbank geholt und eine Weiterleitung dahin ausgelöst. 10. Die Kompression wird aktiviert, sofern die Gzip-Kompression in der Variablen $TYPO3_CONF_VARS[’FE’][’compressionLevel] gesetzt ist. 11. Initialisierung des Frontend-Users. Dazu wird die Session ausgelesen und überprüft,
ob der User sich neu einloggen muss. 12. Überprüfung des Cookies auf den Wert preBeUser. Ist dieser gesetzt, wird geprüft, ob ein Backend-User angemeldet ist, der dann initialisiert wird. Ist dies erfolgreich geschehen, werden weitere Klassen für BE-Funktionalitäten nachgeladen:
PATH_tslib.’class.tslib_befunc.php’
Klasse für Standardfunktionen des Backends.
PATH_tslib.’class.tslib_userauthgroup.php’
Klasse zur Authentifizierung und Initialisierung von BE-Usergroups
PATH_tslib.’class.tslib_beauthuser.php’
Klasse zur Authentifizierung von BE-Usern
PATH_tslib.’class.tslib_beauthuser.php’
Klasse zur Authentifizierung von BE-Usern (TSFE-spezifisch) 13. Wurde ein Workspace-Preview angefordert, wird dieses nun initialisiert. 14. Bestimmung der Page-ID (pid). Da jedes Element, jeder Datensatz einer pid zugeordnet ist, ist sie die zentrale Komponente im Rendering-Prozess. 15. Einlesen der $TCA (Table Configuration Array). Das TCA definiert die (veränderbaren) Datenbanktabellen und ihre Beziehung untereinander. Darüber hinaus definiert sie die Darstellung der einzelnen Formularelemente der Felder im Backend und im FEEditing. 16. Verfügbarkeit der Seite im Cache wird geprüft. 17. Überprüfung, ob das config-Array existiert. Gegebenenfalls wird es nachgeladen. 18. POST-Variablen werden in einen vorher definierten Zeichensatz konvertiert. 19. Setzen der Sprache im Frontend und einstellen der Locales (Datumsformat, Zeit, Währung etc.) 20. Ist JumpUrl aktiviert und die aktuelle Seite per TypoScript-Typolink als externe Seite definiert, wird nun die ZielURL ermittelt. Die Weiterleitung selbst wird erst in Schritt 27 erfolgen. Dadurch ist es möglich, Statistiken zu erhalten, wie oft beispielsweise ein Link angeklickt wurde. Die JumpUrl-Konfiguration erfolgt im Setup des Templates: config.jumpurl_enable = 1 (oder 0) config.jumpurl_mailto_disable = 0 (oder 1)
5
1 Grundlagen 21. Verarbeitung der Formulardaten. Dies schließt Formulare im Frontend sowie E-MailFormulare mit ein. 22. Die Seite wird generiert, aber noch nicht ausgegeben. Ist sie bereits im Cache vorhanden, wird die Version aus dem Cache verwendet, ansonsten wird sie neu gerendert, also zusammengebaut. 23. Einfügen weiterer Files. Beispielsweise Dateien, die über PHP_SCRIPT_INT definiert wurden (includeLibs). 24. Wurde keine JumpUrl definiert, erfolgt nun der Output der Seite. Alle Inhalte und Skripte werden im $TSFE-Objekt zusammengefügt und über echo ausgegeben. Wurde allerdings die Gzip-Komprimierung aktiviert, werden die Inhalte nur zusammengefügt, aber noch nicht ausgegeben. Das erfolgt dann in Schritt 31. 25. Die mögliche Frontend-Session, die in Schritt 11 ermittelt wurde, wird abgespeichert. 26. Die Statistik wird erstellt. Zum Beispiel wird die Parse-Zeit ermittelt. 27. Wurde eine JumpUrl definiert, wird auf diese nun weitergeleitet. 28. Da es möglich ist, Seiten auch statisch zu publizieren, wird dies hier durchgeführt, falls die Konfiguration dies verlangt. 29. Das Admin-Panel wird an den Quellcode angehängt und ausgegeben, sofern es aktiviert wurde und der angemeldete Backend-Benutzer die Rechte dazu hat. 30. Bei aktiviertem Deugging werden alle Debug-Messages ausgegeben. 31. Ausgabe der Daten, falls Gzip-Kompression aktiviert ist.
1.2
Aufbau einer Extension Eine Extension kann aus einem oder mehreren Abschnitten bestehen. Die FrontendAusgabe besteht (in der Regel) aus einem Plug-in. Davon können durchaus mehrere in einer Extension existieren. Sie liegen in eigenen Verzeichnissen mit der Bezeichnung p1#, wobei # für eine vorlaufende Nummer steht. Plug-ins können auf die TypoScriptKonfiguration zurückgreifen oder aber direkt konfiguriert werden, sofern ein Konfigurationsformular implementiert wird. Backend-Module dagegen integrieren sich in das Hauptmenü des Backends und geben keine Ausgabe an das Frontend weiter. Sie sind in Unterverzeichnissen mit der Bezeichnung mod# organisiert. Auch Services können in einer Extension existieren, um Funktionen bereitzustellen. Für AJAX-Requests und ähnliche Aufgaben können Skripte hinzugefügt werden, die über den eID-Parameter aufgerufen werden können und die meisten Funktionalitäten des TYPO3-Cores umgehen. Nur der Datenbankzugriff und das FEuser-Objekt sind hier verfügbar. Eine Dokumentation darf ebenfalls nicht fehlen.
6
1.3 Arten und Einteilung von Extensions
1.3
Arten und Einteilung von Extensions Es gibt drei Arten von Extensions:
Lokale Extensions Globale Extensions Systemextensions Die Reihenfolge spiegelt die Priorität wider. Ist eine Extension also beispielsweise lokal und global installiert, wird die lokale Version verwendet, da sie die höhere Priorität besitzt. Um Extensions etwas zu ordnen, sind sie in verschiedene Kategorien eingeteilt. Backend Extensions, die im Backend zum Tragen kommen, aber keinen eigenen Menüpunkt im Hauptmenü besitzen. Sie stellen in der Regel Erweiterungen bestehender Funktionalitäten oder Tools dar. Ein Beispiel ist rtehtmlarea. Backend-Modul Extensions mit einem eigenen Menüpunkt, also einem eigenen Modul. Als Beispiel wäre hier quixplorer zu nennen. Frontend Erweiterungen für das Frontend, die nicht unbedingt eine eigene Ausgabe erzeugen, diese aber durchaus beeinflussen und verändern können. Die bekannteste Extension dieser Art ist die css_styled_content. Frontend-Plug-in Eine Extension, die ein eigenes Plug-in mitbringt und eine Ausgabe im Frontend erzeugt. Eine der bekanntesten Extension dieser Kategorie ist tt_news. Services Services stellen Dienstleistungen und Funktionalitäten für andere Extensions bereit. Ein Service kann beispielsweise Daten über externe Schnittstellen weiterverarbeiten. Documentation Diese Extensions dienen zur Bereithaltung von Dokumentationen und Manuals. Diese werden in der Regel als OpenOffice-Dokumente bereitgestellt. Examples Tutorials und Beispiele für TYPO3 und Extensions.
7
1 Grundlagen Templates Fertige TYPO3-Templates. Diese stehen sowohl als HTML-/CSS-Templates wie auch für TemplaVoila und TemplateAutoparser bereit. Templates für timtab werden beispielsweise in dieser Kategorie im TER bereitgehalten. Miscellaneous Alles, was nicht in die eben genannten Kategorien fällt, wird hier eingeordnet. [] Diese Nichtkategorie sammelt Extensions, für die keine Kategorie angegeben wurde. Die Entscheidung, in welche Kategorie eine Extension fällt, ist nicht immer einfach. Hier sollten Sie den Hauptzweck der Extension hinterfragen und danach eine Bewertung vornehmen. Wenn eine Extension mit FE-Plug-ins, BE-Modulen und vielleicht noch Services daherkommt, ihre Hauptaufgabe aber darin besteht, ganz tolle Sachen auf der Webseite darzustellen, ist die treffendste Kategorie natürlich Frontend-Plug-ins. Miscellaneous sollte die Ausnahme darstellen. Die Zeit, sich etwas Gedanken über die eigene Extension zu machen, sollte man schon mitbringen
1.4
Der Extension-Key Bevor Sie auch nur eine Zeile Code schreiben, kommt die Wahl des richtigen ExtensionKeys. Und diese Wahl will gut überlegt sein. Denn „eineLustigeExtension_trallalalla“ sorgt für mehr Frust und ist die fünf Sekunden Lächeln nicht wert. Der Extension-Key muss einmalig, (möglichst) treffend und (idealerweise) kurz sein. Sonderzeichen sind nicht erlaubt. Der oft anzutreffende Underscore „_“ ist zwar nicht verboten, sollte aber nicht mehr verwendet werden, da dieser im Quellcode sowieso getilgt wird. Aus „elu_krass“ wird beispielsweise „class_elukrass_pi1“. Haben Sie sich für einen Extension-Key entschieden, sollten Sie den Key reservieren. Zum einen um auszuschließen, dass es bereits eine Extension mit dem Key gibt, und anderseits um Probleme zu vermeiden, wenn ein Zweiter den genialen Einfall hatte, den Sie gerade produziert haben. Sie können natürlich den Extension-Key später noch ändern – theoretisch. Glauben Sie uns, Sie möchten das nicht tun. Dazu wäre es nötig, den Key auch in allen Skripten der Extension zu ändern. Bei umfangreichen Extensions kann das eine ganze Weile dauern. Um einen Key zu registrieren, loggen Sie sich auf der Webseite http://typo3.org ein. Wenn Sie noch keinen Login besitzen, ist dies nun die perfekte Gelegenheit für eine Registrierung auf der Seite. Nach der Anmeldung navigieren Sie in den Menüpunkt Extensions. Hier ist die Unterseite Extension-Keys von Interesse. Auf dieser Seite können Sie im Reiter Register Keys einen neuen Key anlegen.
8
1.5 TYPO3 Coding Guidelines
Abbildung 1.1 Neuen Key registrieren
1.5
TYPO3 Coding Guidelines Man könnte prinzipiell loslegen und Extensions programmieren. Einmal quer durch die API pflügen, und am Ende steht eine Extension da, die vielleicht sogar funktioniert. Aus Gründen der Sicherheit, der Erweiterbarkeit und der Zukunftssicherheit sollte man sich aber doch an einige Regeln halten. Diese Regeln haben in den TYPO3 Coding Guidelines Gestalt angenommen1. Die CGLs beinhalten beispielsweise die Verzeichnisstruktur einer Extension. Hier ist auch nachzulesen, dass eine strikte Trennung zwischen dem TYPO3-Kern und allen übrigen Dateien einzuhalten ist. PHP-Dateien, die Klassen beinhalten, müssen mit class_ im Namen beginnen, Dateien mit PHP-Interfaces mit interface_. Jede Datei sollte nur eine Klasse oder nur ein Interface beinhalten. Die Benennung erfolgt nach diesem Beispiel: class__.php
Der Namespace ordnet Klassen und Funktionen logisch zu.
1
http://typo3.org/documentation/document-library/core-documentation/doc_core_cgl/4.3.0/view/
9
1 Grundlagen
1.5.1
Namespace
Eine Reihe von Namensräumen ist bereits vordefiniert. t3lib Dieser Namensraum definiert gemeinsame Dateien für das Frontend und das Backend. Diese stellen allgemeine Funktionalitäten bereit. Sie befinden sich im t3lib-Verzeichnis des Cores und sind in Unterverzeichnisse geordnet. Die Verzeichnishierarchie wird in die Benennung der Klassendateien mit aufgenommen. User-Dateien dürfen diesen Namensraum nicht nutzen. typo3 Dieser Namensraum wird von TYPO3-Backend-Dateien verwendet, die aus historischen Gründen auch andere Präfixe in ihrer Benennung nutzen können. Keine User-Dateien erlaubt. tslib Die TypoScript-Bibliotheken sind für das Frontend-Rendering verantwortlich und halten sich aus historischen Gründen nicht zwingend an die Namenskonvention. User-Dateien dürfen diesen Namensraum ebenfalls nicht nutzen. tx_ Extensions nutzen den Namensraum tx_, gefolgt vom Extension-Key, der um die Underscores bereinigt wurde. Beispiel tx_mykey_myclass, user_ Der Namensraum user_ gilt für PHP-Dateien ohne Klasse. Die Verwendung von user_ wird nicht empfohlen. Funktionen in klassenlosen PHP-Dateien werden von TYPO3 nicht ausgeführt, wenn sie den user_-Namespace nicht verwenden. Auch die Funktionen selbst müssen dieses Präfix im Namen enthalten. ux_ Dieser Namespace ist für XCLASS-Dateien in Extensions reserviert.
10
1.5 TYPO3 Coding Guidelines
1.5.2
PHP-Regeln
PHP-Tags Die PHP-Tags dürfen als Paar nur einmal in einer Datei auftreten. Das Tag muss geschlossen werden. Listing 1.1 Korrekte Verwendung
Nach dem schließenden Tag dürfen keine Leerzeichen oder Leerzeilen kommen. Dies würde die Kompression verhindern und AJAX-Requests stören. Nicht erlaubt ist dagegen die folgende Verwendung. Listing 1.2 Falsche Verwendung
###TITLE### ###SUBTITLE### ###CRDATE### ###TEASERIMG### ###TEASER### ###BODYTEXT### ###CATEGORY### ###AUTHOR###
Speichern Sie die Datei unter dem Namen tx_elublog_template.tpl im Verzeichnis pi1 ab. Nun muss das Plug-in diese Datei einlesen und die Werte substituieren. Folgende Eintragung in der Funktion main() definiert die Template-Vorlage:
109
4 Frontend-Plug-ins Listing 4.28 Template verwenden $this->templateFile = ($conf['templateFile']) ? $this->cObj-> fileResource($conf['templateFile']) : $this->cObj-> fileResource('EXT:elublog/pi1/tx_elublog_template.tpl');
Nun müssen den Markern die Inhalte zugewiesen werden. Dazu ändern wir die Funktion $this->pi_list_row(). Listing 4.29 pi_list_row() function pi_list_row($c) { $cObj = t3lib_div::makeInstance('tslib_cObj'); $markerArray['###BODYTEXT###'] = ($this->getFieldContent ('bodytextinlist') == 1) ? $cObj->stdWrap($this->getFieldContent ('bodytext'),$this->conf['listView.']['bodytext_stdWrap']) : ''; $markerArray['###TITLE###'] = $cObj->stdWrap($this-> getFieldContent('title'),$this->conf['listView.']['title_stdWrap.']); $markerArray['###CRDATE###'] = $cObj->stdWrap(htmlspecialchars($this-> getFieldContent('crdate')),$this->conf['listView.']['crdate_stdWrap.']); $markerArray['###SUBTITLE###'] = $cObj->stdWrap(htmlspecialchars ($this->getFieldContent('subtitle')),$this->conf['listView.'] ['subtitle_stdWrap.']); $markerArray['###TEASERIMG###'] = $cObj->stdWrap($this-> getFieldContent('teaserimg'),$this->conf['listView.'] ['teaserimg_stdWrap.']); $markerArray['###TEASERTEXT###'] = $cObj->stdWrap($this-> getFieldContent('teasertext'),$this->conf['listView.'] ['teasertext_stdWrap.']); $markerArray['###AUTHOR###'] = $cObj->stdWrap($this-> getFieldContent('author'),$this->conf['listView.']['author_stdWrap.']); $markerArray['###CATEGORY###'] = $cObj->stdWrap($this-> getFieldContent('category'),$this->conf['listView.'] ['category_stdWrap.']); $markerArray['###TAGS###'] = $cObj->stdWrap($this-> getFieldContent('tags'),$this->conf['listView.']['tags_stdWrap.']); $template['item'] = $this->cObj->getSubpart($this->templateFile, '###ITEM###'); return $this->cObj->substituteMarkerArrayCached$template['item'], $markerArray); }
Es wird ein Array namens $markerArray aufgebaut, dessen Keys den Markern in der Vorlage entsprechen. Diesem Array werden die Markerinhalte zugewiesen, nachdem mittels $this->cObj->stdWrap() die StdWrap-Eigenschaften zugewiesen wurden. Am Ende wird dem Subpart ###ITEM### das Array übergeben, und damit werden die Marker in diesem Subpart substituiert. Allerdings muss auch die Funktion $this->pi_make_list() der Klasse tslib_pibase überschrieben werden, da diese Funktion eine Tabelle aufbaut, die uns hier nichts nützt. Listing 4.30 Neue Funktion $this->pi_make_list() function pi_list_makelist($res,$tableParams='') { $this->internal['currentRow']=''; $template['total'] = $this->cObj->getSubpart($this->templateFile, '###LISTVIEW###'); $template['item'] = $this->cObj->getSubpart($this->templateFile, '###ITEM###'); $c=0; $fixedMarkerArray['###AT###'] = $this->pi_getLL('at'); $fixedMarkerArray['###FROM###'] = $this->pi_getLL('from'); $fixedMarkerArray['###IN###'] = $this->pi_getLL('in');
110
4.3 HTML-Templates für das Plug-in while($this->internal['currentRow'] = $GLOBALS['TYPO3_DB']-> sql_fetch_assoc($res)) { $markerArray = $this->pi_list_row($c); $markerArrayMerged = array_merge($markerArray,$fixedMarkerArray); $contentItem .= $this->cObj->substituteMarkerArrayCached ($template['item'],$markerArrayMerged); $c++; } $content = $this->cObj->substituteMarkerArrayCached($template['total'], array(), array('###ITEM###' => $contentItem)); return $content; }
Die Datenbankeinträge werden geholt. Bei jedem Durchlauf wird die Funktion $this>pi_list_row() aufgerufen und das Ergebnis der Variablen $contentItem hinzugefügt.
Diese wird letztendlich dem Subpart ###LISTVIEW### zugewiesen. Am Ende wird der Subpart substituiert. Im TypoScript fehlen noch die Eigenschaften des stdWrap der einzelnen Felder. Jedes Feld sollte mit einem -Container gewrapt werden. Listing 4.31 stdWrap im TypoScript plugin.tx_elublog_pi1.listView.title_stdWrap.wrap = | plugin.tx_elublog_pi1.listView.subtitle_stdWrap.wrap = | plugin.tx_elublog_pi1.listView.crdate_stdWrap.wrap = | plugin.tx_elublog_pi1.listView.teaserimg_stdWrap.wrap = | plugin.tx_elublog_pi1.listView.teasertext_stdWrap.wrap = | plugin.tx_elublog_pi1.listView.bodytext_stdWrap.wrap = | plugin.tx_elublog_pi1.listView.author_stdWrap.wrap = | plugin.tx_elublog_pi1.listView.category_stdWrap.wrap = | plugin.tx_elublog_pi1.listView.tags_stdWrap.wrap = |
Das Ergebnis sehen Sie in der folgenden Abbildung.
111
4 Frontend-Plug-ins
Abbildung 4.4 Die Ausgabe der Listenansicht per Template
Auch die Ausgabe im SingleView, also der Artikel allein, muss angepasst werden. Es werden auch die Marker für die Kommentare und das Kommentarformular gesetzt. Diese werden aus eigenen Funktionen kommen, werden aber im Moment nur als Dummy gebaut. Listing 4.32 Templating der Einzelansicht function singleView($content, $conf) { $this->conf = $conf; $this->pi_setPiVarDefaults(); $this->pi_loadLL(); if ($this->internal['currentRow']['title']) $GLOBALS['TSFE']-> indexedDocTitle=$this->internal['currentRow']['title']; $content=''; $cObj = t3lib_div::makeInstance('tslib_cObj'); $markerArray['###BODYTEXT###'] = $cObj->stdWrap($this->getFieldContent ('bodytext'),$this->conf['singleView.']['bodytext_stdWrap']); $markerArray['###TITLE###'] = $cObj->stdWrap($this->getFieldContent ('title'),$this->conf['singleView.']['title_stdWrap.']); $markerArray['###CRDATE###'] = $cObj->stdWrap(htmlspecialchars ($this->getFieldContent('crdate')),$this->conf['singleView.'] ['crdate_stdWrap.']); $markerArray['###SUBTITLE###'] = $cObj->stdWrap(htmlspecialchars ($this->getFieldContent('subtitle')),$this->conf['singleView.'] ['subtitle_stdWrap.']);
112
4.3 HTML-Templates für das Plug-in $markerArray['###TEASERIMG###'] = $cObj->stdWrap($this-> getFieldContent('teaserimg'),$this->conf['singleView.'] ['teaserimg_stdWrap.']); $markerArray['###TEASERTEXT###'] = $cObj->stdWrap($this-> getFieldContent('teasertext'),$this->conf['singleView.'] ['teasertext_stdWrap.']); $markerArray['###AUTHOR###'] = $cObj->stdWrap($this->getFieldContent ('author'),$this->conf['singleView.']['author_stdWrap.']); $markerArray['###CATEGORY###'] = $cObj->stdWrap($this-> getFieldContent('category'),$this->conf['singleView.'] ['category_stdWrap.']); $markerArray['###TAGS###'] = $cObj->stdWrap($this->getFieldContent ('tags'),$this->conf['singleView.']['tags_stdWrap.']); $markerArray['###COMMENTS###'] = $cObj->stdWrap($this->getComments(), $this->conf['singleView.']['comments_stdWrap.']); $markerArray['###COMMENTFORM###'] = ($this->getFieldContent ('lockcomments') == 1) ? $cObj->stdWrap($this->pi_getLL ('commentsNotAllowed'),$this->conf['singleView.']['commentForm_stdWrap.'] ) : $cObj->stdWrap($this->getCommentForm(),$this->conf['singleView.'] ['commentForm_stdWrap.']); $markerArray['###AT###'] = $this->pi_getLL('at'); $markerArray['###FROM###'] = $this->pi_getLL('from'); $markerArray['###IN###'] = $this->pi_getLL('in'); $markerArray['###BACKLINK###'] = $cObj->stdWrap($this-> pi_list_linkSingle($this->pi_getLL('back','Back'),0),$this->conf ['singleView.']['backLink_stdWrap.']); $template['item'] = $this->cObj->getSubpart($this->templateFile, '###SINGLEVIEW###'); $content .= $this->cObj->substituteMarkerArrayCached ($template['item'],$markerArray); $content .= ""; $this->pi_getEditPanel(); return $content; }
Die Funktion sieht $this->pi_list_row() sehr ähnlich. Allerdings fehlt die if-Abfrage beim bodytext, der stdWrap wird durch den TypoScript-Hive singleView konfiguriert, und das Einbinden der Kommentarfunktion ist vorbereitet. Allerdings müssen wir zwei Funktionen anlegen, da sonst ein Fehler gemeldet würde. Sie müssen erst einmal nur existieren, ausprogrammiert werden sie im nächsten Schritt. Listing 4.33 Funktions-Dummys anlegen function getComments() {} function getCommentForm() {}
Da wir die Ausgabe des Funktionsselektors nicht benötigen, entfernen Sie aus der Funktion $this->listView folgende Zeilen: Listing 4.34 Funktionsselektor $fullTable.=$this->pi_list_modeSelector($items);
Wir haben die Listenansicht und die Einzelansicht mit Templates belegt. Durch Änderungen an diesen mit CSS und TypoScript haben wir nun die Möglichkeit, die Ausgabe individuell anzupassen. Im Folgenden wurde das Template in eine (sehr einfache) Seite mit drei Spalten eingebaut und gestylt.
113
4 Frontend-Plug-ins
Abbildung 4.5 Der Blog mit angepasstem Styling
4.4
Die Kommentarfunktion mit AJAX und eID Bei jedem Blog ist die Kommentarfunktion wichtig. Es gehört zum guten Ton des Web 2.0, die Besucher zu integrieren und Interaktivitäten zu ermöglichen. Um das Ganze ein wenig aufzupeppen, sollen die Kommentare über AJAX versendet werden. Der Schüssel dazu liegt im eID-Mechanismus. Dadurch sind Datenbankmanipulationen möglich, ohne den kompletten Rendering-Prozess von TYPO3 zu durchlaufen.
114
4.4 Die Kommentarfunktion mit AJAX und eID
Abbildung 4.6 Der Ablauf beim Abschicken eines Kommentars
4.4.1
Ausgabe vorhandener Kommentare
Wir beginnen also mit der Ausgabe eventuell vorhandener Kommentare und des Kommentarformulars. Dazu kommt ein wenig JavaScript für den AJAX-Request und das Einfügen des neuen Kommentars in die Kommentarliste.
115
4 Frontend-Plug-ins Um die vorhandenen Kommentare auszugeben, verwenden wir die Funktion $this-> getComments(), die wir vorhin als Dummy angelegt haben. Listing 4.35 Funktion $this->getComments() function getComments() { $template['comment'] = $this->cObj->getSubpart($this->templateFile, '###COMMENT###'); $template['item'] = $this->cObj->getSubpart($this->templateFile, '###COMMENTITEM###'); $contentItem = ''; $c=1; $cObj = t3lib_div::makeInstance('tslib_cObj'); // Datenbankabfrage nach allen Kommentaren zu dem Blogeintrag $res = $this->pi_exec_query('tx_elublog_blogcomments', 0, "AND blogentry=".$this->internal['currentRow']['uid']); // Übersetzungsmarker, die sich nicht ändern, setzen. $fixedMarkerArray['###AT###'] = $this->pi_getLL('at'); // Datensätze durchlaufen und Marker zuweisen while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { $markerArray['###NUMBER###'] = $cObj->stdWrap($c,$this->conf ['singleView.']['comment.']['number_stdWrap.']); $markerArray['###AUTHOR###'] = ($row['website'] != '') ? $cObj-> stdWrap("conf['singleView.'] ['comment.']['author_stdWrap.']."") : $cObj->stdWrap($row['author'], $this->conf['singleView.']['comment.']['author_stdWrap.']); $markerArray['###COMMENTTEXT###'] = $cObj->stdWrap(strip_tags ($row['comment']),$this->conf['singleView.']['comment.'] ['comment_stdWrap.']); $markerArray['###DATE###'] = $cObj->stdWrap($row['crdate'],$this-> conf['singleView.']['comment.']['crdate_stdWrap.']); $markerArray['###GRAVATAR###'] = $cObj->stdWrap('',$this->conf['singleView.']['comment.'] ['gravatar_stdWrap.']); // $markerArray mit den fixen Markern in $fixedMarkerArray zusammenführen $markerArrayMerged = array_merge($markerArray,$fixedMarkerArray); // Marker substituieren $contentItem .= ''.$this-> cObj->substituteMarkerArrayCached($template['item'], $markerArrayMerged). ''; $c++; } // Anzahl der Kommentare ermitteln und zuweisen. $count = $c-1; $marker['###COMMENTCOUNT###'] = $cObj->stdWrap(''.$count.''.$this-> pi_getLL('comments'),$this->conf['singleView.']['comment.'] ['commentcount_stdWrap.']); $content = ($contentItem != '') ? $this->cObj-> substituteMarkerArrayCached($template['comment'], $marker, array('###COMMENTITEM###' => $contentItem)):$this->pi_getLL ("noComments"); return ''.$content.''; }
Es wird eine Abfrage gegen die Datenbank abgesetzt, die alle Kommentare aus der Tabelle tx_elublog_blogcomments sucht, die dem Beitrag zugeordnet sind. Die Ergebnisse werden durchlaufen und den Markern zugeordnet.
116
4.4 Die Kommentarfunktion mit AJAX und eID Listing 4.36 HTML-Template für die Kommentare
###COMMENTNUMBER### ###COMMENTAUTHOR### ###AT### ###COMMENTDATE### ###GRAVATAR### ###COMMENTTEXT###
Der Container mit ID tx_elublog_newcomment wird den neuen Kommentar anzeigen, den der Besucher hinterlässt. Eine Besonderheit ist der Marker ###GRAVATAR###. Ihm wird ein sogenannter Gravatar zugeordnet. Das ist ein Bild, auch als Avatar bekannt, das oft den Kommentarverfasser, aber auch beliebig andere Inhalte zeigt. Das Bild ist einer Mail-Adresse zugeordnet und wird unter http://www.gravatar.com verwaltet. Zur Zeit der Drucklegung ist dieser Dienst kostenlos (und wird es wohl auch bleiben). Die Gravatar-Bilder haben in der Regel eine Größe zwischen 40 und 120 Pixel. Über eine API-Schnittstelle wird der MD5-Hash der Mail-Adresse bei Gravatar.com abgefragt, ob dafür ein Bild existiert. Wenn ja, wird dieses in der angeforderten Größe zurückgesendet. Andernfalls wird ein Standardbild geliefert. Zwei Parameter müssen über TypoScript konfiguriert werden: Listing 4.37 Gravatar-Konfiguration // Größe des Gravatars in Pixel plugin.tx_elublog_pi1.singleView.comment.gravatar_size = 40 // URL des Standardbildes plugin.tx_elublog_pi1.singleView.comment.gravatar_default_url = http://example.com/fileadmin/elublog/gravatar.png
Diese Parameter werden an die API zusammen mit dem MD5-Hash der Mail-Adresse übermittelt. Das Ergebnis wird in ein -Tag eingebaut.
Abbildung 4.7 Die Ausgabe der Kommentare mit Gravataren
117
4 Frontend-Plug-ins
4.4.2
Das Kommentarformular hinzufügen
Auch für das Formular haben wir bereits eine Funktion vorbereitet. Diese heißt $this-> getCommentForm(). Das Formular selbst bauen wir als HTML-Vorlage auf. Darin werden
nur ein paar Labels zum Substituieren sein. Listing 4.38 $this->getCommentForm() function getCommentForm() { /* ###### Platzhalter für AJAX-Funktionalität ###### */ $markerArray['###LABEL_COMMENTFORM###'] = $this-> pi_getLL('label_commentform'); $markerArray['###LABEL_COMMENTFORM_AUTHOR###'] = $this-> pi_getLL('label_commentform_author'); $markerArray['###LABEL_COMMENTFORM_AUTHOREMAIL###'] = $this-> pi_getLL('label_commentform_authoremail'); $markerArray['###LABEL_COMMENTFORM_WEBSITE###'] = $this-> pi_getLL('label_commentform_website'); $markerArray['###LABEL_COMMENTFORM_COMMENT###'] = $this-> pi_getLL('label_commentform_comment'); $markerArray['###LABEL_COMMENTFORM_SUBMIT###'] = $this-> pi_getLL('label_commentform_submit'); $markerArray['###BID###'] = $this->internal['currentRow']['bid']; $markerArray['###BLOGENTRY###'] = $this->internal['currentRow']['uid']; $markerArray['###DATEFORMAT###'] = $this->conf['singleView.'] ['comment.']['dateFormat']; $template['commentform'] = $this->cObj->getSubpart($this-> templateFile,'###COMMENTFORMSET###'); $content = $this->cObj->substituteMarkerArrayCached ($template['commentform'],$markerArray); return $content; }
In den Platzhalter am Anfang der Funktion setzen wir gleich die AJAX-Funktionalität ein. Die Übersetzung der Labels kommt wieder aus locallang.xml. Listing 4.39 locallang.xml Senden
Das Formular selbst ist unspektakulär. Es enthält die erforderlichen Felder und Labels. Die einzige Besonderheit ist die Abwesenheit eines -Tags. Das Formular wird mit einem onclick-Event getriggert. Listing 4.40 HTML-Template-Vorlage
Nun fehlt allerdings noch die komplette AJAX-Funktionalität. Im Prinzip wollen wir die Eingaben des Formulars zum Server übertragen, wo sie in die Datenbank geschrieben werden. Quasi als Bestätigung, sollen die Daten zurück zum Skript geschickt und als neuer Kommentar dargestellt werden. Ab Version 4.3 wird TYPO3 mit dem ExtJS JavaScript-Framework ausgeliefert. ExtJS ist ein sehr mächtiges Framework, das wir für unsere Zwecke einsetzen möchten. Wir nutzen es für den AJAX-Request selbst, um dafür den zurückgelieferten Kommentar unter den bestehenden anzufügen. Der Vorteil, wie wir gleich sehen werden, ist der, dass wir dazu wieder das Template aus der Template-Vorlage verwenden können. Natürlich kann das Beispiel auch mit anderen Frameworks oder sogar nur mit eigenem JavaScript-Code umgesetzt werden. Fügen Sie Listing 4.41 und Listing 4.42 in den Platzhalter aus Listing 4.38 ein. Da wir die Template-Vorlage, die schon besteht, verwenden wollen, müssen wir diese laden und die Marker substituieren. Da die Inhalte aber erst auf dem Client nach dem AJAXRequest bereitstehen, substituieren wir sie wiederum mit eigenen Markern für ExtJS. Listing 4.41 Template-Vorlage für ExtJS erstellen $cObj = t3lib_div::makeInstance('tslib_cObj'); $gravatar_size = $this->conf['singleView.']['comment.'] ['gravatar_size']; $gravatar_default = $this->conf['singleView.']['comment.'] ['gravatar_default_url']; $template['comment'] = $this->cObj->getSubpart($this-> templateFile,'###COMMENT###'); $template['item'] = $this->cObj->getSubpart($this-> templateFile,'###COMMENTITEM###'); $fixedMarkerArray['###AT###'] = $this->pi_getLL('at'); $markerArray['###COMMENTNUMBER###'] = $cObj-> stdWrap('{commentnumber}',$this->conf['singleView.']['comment.']
119
4 Frontend-Plug-ins ['number_stdWrap.']); $markerArray['###COMMENTAUTHOR###'] = $cObj->stdWrap('{commentauthor}', $this->conf['singleView.']['comment.']['author_stdWrap.']); $markerArray['###COMMENTTEXT###'] = $cObj->stdWrap('{comment}',$this-> conf['singleView.']['comment.']['comment_stdWrap.']); $markerArray['###COMMENTDATE###'] = $cObj->stdWrap('{commentdate}', $this->conf['singleView.']['comment.']['crdate_stdWrap.']); $markerArray['###GRAVATAR###'] = $cObj->stdWrap('{commentemail}', $this->conf['singleView.']['comment.']['gravatar_stdWrap.']); $markerArrayMerged = array_merge($markerArray,$fixedMarkerArray); $html = str_replace("\n",'','' .$this->cObj->substituteMarkerArrayCached($template['item'], $markerArrayMerged).'');
Wir lesen die Einstellungen für die Gravatar-Darstellung ein. Dann geht es an das Substituieren. Am Beispiel ###COMMENT### sieht man, dass der Marker durch {comment} ersetzt wird, nachdem ein stdWrap darauf angewendet wurde. Auch ist ersichtlich, dass der Subpart ###COMMENT### nicht verwendet wird, sondern nur der tiefer liegende ###ITEM###. Listing 4.42 Das JavaScript $js = "";
Da JavaScript nur am Rande mit der Extension-Programmierung zu tun hat, gehen wir auf das Skript nur kurz ein. Die Funktion Ext.Ajax.request() löst einen AJAX-Request mit den übergebenen Parametern aus. Der Parameter params enthält ein Array mit den zu übergebenden Parameter an das Zielskript. Diese werden aus den Values der Input-Felder ausgelesen. Im Erfolgsfall wird das Template, das zuvor erzeugt und in die Variable $html geschrieben wurde, mit den Rückgabeparametern befüllt und in den Div-Container tx_elublog_ newcomment eingehängt. Im Fehlerfall wird die Statusmeldung mit einem Fehler ausgegeben. Der AJAX-Request wird an die URL index.php?eID=tx_elublog_eid gesendet. Der Parameter eID stellt eine Besonderheit dar. Ist er gesetzt, wird der Frontend-RenderingProzess abgebrochen und die Klasse tslib_eidtools eingebunden. eID-Skripte sind etwas schwieriger zu programmieren, da viele Klassen nicht zur Verfügung stehen, dazu gehören zum Beispiel auch die tslib_pibase und tslib_cObj. Da wir aber nur den Zugriff auf die Datenbank und den FE-User benötigen, stellt das kein Problem dar. Neu in TYPO3 4.3
Wie gesagt, stehen in eID-Skripten nicht alle Funktionen zur Verfügung. Mit „FOUR3“ kommen aber ein paar Änderungen: Mit tslib_eidtools::initLanguage() wird die Sprachunterstützung bereitgestellt. Mit tslib_eidtools::initTCA() wird das TCA geladen. Und mit tslib_eidtools::getTSFE() wird die Frontend-Klasse geladen. Somit können diese Funktionalitäten ebenfalls in eID-Skripten verwendet werden.
Listing 4.43 Die eID-Datei
Als Ergebnis liefert das Skript einen JSON-String zurück, der von JavaScript mittels eval() in ein Array zurückverwandelt und ausgegeben wird. Da eID-Skripte nicht den ganzen Rendering-Prozess durchlaufen, und nur ein ganz kleiner Teil des TYPO3-Frameworks geladen wird, sind sie bedeutend schneller und ressourcen-
122
4.5 Was sind Hooks? schonender, als wenn wir direkt ein Plug-in abgefragt hätten. Das prädestiniert sie für AJAX-Abfrageskripte, auch wenn nicht die ganze Funktionalität verfügbar ist. Es besteht natürlich immer noch die Möglichkeit, einzelne Klassen zu inkludieren.
Abbildung 4.8 Ein neuer Kommentar wurde eingegeben.
4.5
Was sind Hooks? Es kann nötig sein, eine bestehende Extension um Funktionalität zu erweitern oder bestehende Funktionen zu ändern. Damit andere Programmierer das möglichst einfach tun können, werden sogenannte Hooks eingebaut. Hooks sind im Grunde Einsprungmarken, über die eine Extension erweitert wird. Wenn eine Extension eine andere Extension – oder auch den Core – mit einer Hook-Funktion erweitert, wird diese in der Datei ext_localconf.php
123
4 Frontend-Plug-ins registriert. Das Plug-in, das erweitert wird, führt eine Schleife über die Registrierung aus und ruft über t3lib_div::callUserFunc() die entsprechende Funktion auf. Listing 4.44 Registrierung einer Hook-Funktion $TYPO3_CONF_VARS['EXTCONF']['hooked_extkey']['nameDesHooks'] [$_EXTKEY] = 'EXT:'.$_EXTKEY. '/class.tx_extkey_hooks.php:tx_extkey_hooks->hookFunc';
“hooked_extkey” ist hierbei durch den Extension-Key der zu hookenden Extension zu ersetzen. Damit Hooks überhaupt verwendet werden können, müssen sie erst einmal vorhanden sein. Hier beginnen die Überlegungen, wo Hooks überhaupt sinnvoll sind. Da wäre zum Beispiel:
Hooks, um Marker in der Einzel- und Listenansicht hinzuzufügen oder zu ändern. Ein Hook, bevor ein Kommentar in die Datenbank geschrieben wird. Eine Möglichkeit, die sofort ins Auge springt, ist die Überprüfung der Mail-Adresse. Wir wollen sichergehen, dass auch wirklich eine Mail-Adresse eingegeben wird. Mit einer Regex-Überprüfung ist das schnell erledigt. In diesem Fall müssen wir unsere eID-Funktion hooken. Der Hook kommt direkt nach dem Befüllen des Arrays $fields. Listing 4.45 Hook einbauen 'cruser_id' => $GLOBALS['TSFE']->fe_user->user['uid'], 'pid' => $this->extconf['storageId'] ); $checkError = 0; if (isset($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['elublog'] ['commentCheck'])){ foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['elublog'] ['commentCheck'] as $userFunc) { $params = array( 'fields' => $fields, 'pObj' => &$this ); $checkError = $checkError + t3lib_div::callUserFunction($userFunc,$params,$this); } } if ($checkError > 0) {die(json_encode(array('fail' => 1)));} if ($res = $GLOBALS['TYPO3_DB']->exec_INSERTquery ('tx_elublog_blogcomments',$fields)) {
Jede Hook-Funktion muss 0 zurückliefern, wenn alles in Ordnung ist. Jeder Fehler erhöht die Variable $checkError. Ist sie, nachdem alle Hook-Funktionen abgearbeitet sind, größer als 0, wird der Kommentar nicht in die Datenbank eingetragen. Um unseren Hook zu testen, legen wir eine neue Extension namens elublogmailcheck an. Dazu muss im Kickstarter nur der Punkt General info ausgefüllt werden. Speichern Sie die Extension ab, und legen Sie eine neue Datei namens ext_localconf.php im Verzeichnis der Extension an. Diese füllen Sie mit folgendem Inhalt:
124
4.6 Flexforms Listing 4.46 ext_localconf.php
Der Teil zwischen den PHP-Tags kommt in eine Zeile. Wie zu sehen ist, verweist die Hook-Registrierung auf die Datei class.tx_elublogmailcheck_hooks.php, der sich aus dem Dateinamen ergebenden Klasse und der Funktion hookFunc. Legen Sie also eine Datei namens class.tx_elublogmailcheck_hooks.php an. Listing 4.47 class.tx_elublogmailcheck_hooks.php
Die Funktion hookFunc() prüft die übermittelte Mail-Adresse mit einem RegexAusdruck. Wird damit eine Mail-Adresse erkannt, liefert die Funktion 0, ansonsten 1 zurück. Somit ist es möglich, verschiedenste Arten von Prüfungen zu realisieren.
4.6
Flexforms Es wäre toll, wenn sich einige Einstellungen leichter konfigurieren ließen als über TypoScript. Und vor allem für einzelne Plug-ins, wenn sich also Einstellungen im Plug-in selbst setzen ließen. Mit Flexforms ist das möglich. Folgende Einstellungen wollen wir hier konfigurierbar machen:
Die BlogID Seite für Einzelansicht (bei Listenansicht) Seite für Listenansicht (bei Einzelansicht) Anzahl der Beiträge pro Seite Länge der Voransicht Haupttext immer in Listenansicht anzeigen
Gerade der letzte Punkt ist wichtig, werden im Moment noch die Beiträge aller eingerichteten Blogs angezeigt. Eine Möglichkeit wäre, die Tabelle tt_content um die entsprechenden Felder zu erweitern. Allerdings darf man laut den TYPO3 Coding Guidelines ei-
125
4 Frontend-Plug-ins nige Tabellen nicht mehr auf Feldbasis erweitern. Wirft man einen Blick in die Feldstruktur von tt_content, sieht man auch den Grund: Die Tabelle ist so schon sehr groß, würde jede Extension weitere Felder hinzufügen, wächst die Tabelle extrem an. Die andere Möglichkeit bieten Flexforms. Dadurch werden alle Felder als XML-Struktur in dem Feld pi_flexform der tt_content-Tabelle gespeichert. Die Definition, wie die Felder angelegt werden – im Grunde handelt es sich um eine XML-Version der TCA –, wird als Flexform bezeichnet – für flexible Forms. Die XML-Struktur, die in der Datenbank abgespeichert wird und die Daten enthält, die durch die Flexform eingegeben wurden, nennt man DS bzw. Datenstruktur. Die DS kann von dem Plug-in wieder ausgelesen werden.
4.6.1
Erzeugen der Flexform
Um eine Flexform verwenden zu können, muss sie erst einmal aktiviert werden. Das geschieht in der Datei ext_tables.php. Fügen Sie folgende Zeilen am Ende der Datei, vor dem schließenden PHP-Tag, ein. Listing 4.48 Flexform aktivieren $TCA['tt_content']['types']['list']['subtypes']['subtypes_addlist'] [$_EXTKEY.'_pi1'] = 'pi_flexform'; t3lib_extMgm::addPiFlexFormValue($_EXTKEY.'_pi1', 'FILE:EXT:'.$_EXTKEY.'/flexform_ds_pi1.xml');
Um die Flexform zu erstellen, können Sie sich am TCA orientieren, da der Aufbau der Felder im Grunde gleich ist. Listing 4.49 Input-Feld im TCA 'author' => array ( 'exclude' => 0, 'label' => 'LLL:EXT:elublog/locallang_db.xml:tx_elublog_blogentrys.author', 'config' => array ( 'type' => 'input', 'size' => '30', ) ),
Listing 4.50 Input-Feld als Flexform
LLL:EXT:elublog/locallang.xml:label.author
input 30
Die Grundstruktur der Flexform sieht folgendermaßen aus:
126
4.6 Flexforms Listing 4.51 Grundstruktur
array
< … Elemete … >
Der Node ist ein Platzhalter für den Namen des Elements. Im Beispiel des Elements aus Listing 4.50 wäre das . Es ist möglich, die Elemente auf verschiedenen Tabs aufzuteilen: Listing 4.52 Struktur mit Tabs
Sheet 1
array
< … Elemente … >
Sheet 2
array
< … Elemente … >
Abbildung 4.9 Tabs im Flexform von tt_news
127
4 Frontend-Plug-ins Erstellen Sie für die Flexform die Datei flexform_ds_pi1.xml im Extension-Verzeichnis. Listing 4.53 flexform_ds_pi1.xml
array
LLL:EXT:elublog/locallang.xml:fflabel.blogid
select
LLL:EXT:elublog/locallang.xml:fflabel.allBlogs 0
tx_elublog_blogs
LLL:EXT:elublog/locallang.xml:fflabel.listPage
group db pages 1 0 1 1 1
LLL:EXT:elublog/locallang.xml:fflabel.singlePage
group db pages 1 0 1 1 1
LLL:EXT:elublog/locallang.xml:fflabel.entrysperpage
input 20 40 int 1
128
4.6 Flexforms
LLL:EXT:elublog/locallang.xml:fflabel.teaserCrop
input 20 40 trim 1
LLL:EXT:elublog/locallang.xml:fflabel.fullTextInList
check
Die Labels werden wieder aus einer Übersetzungsdatei gefüllt. Öffnen Sie die Datei locallang.xml, und fügen Sie folgende Zeilen in die entsprechenden Übersetzungen ein. Listing 4.54 Übersetzung default Crop Teasertext after ...
Listing 4.55 Übersetzung Deutsch Angezeigter Blog Alle Blogs Seite für 'zurück' in Einzelansicht (leer für aktuelle Seite) Seite für Einzelansicht (leer für aktuelle Seite) Beiträge pro Seite in Listenansicht (0 für alle Teasertext nach ... Zeichen abschneiden
In Abbildung 4.10 sehen Sie das Ergebnis.
129
4 Frontend-Plug-ins
Abbildung 4.10 Flexform-Plug-in-Konfiguration
Nun müssen die Werte umgesetzt werden. In der Listenansicht sind alle Einstellungen bis auf „Seite für ‚zurück’ in Einzelansicht“ von Bedeutung. Um auf den Wert eines FlexForm-Feldes zuzugreifen, wird die Funktion pi_getFFvalue() verwendet. Listing 4.56 Zugriff auf die Flexform $var = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'element','sDEF');
Das Wort element entspricht dabei dem Namen des Feldes. In der Funktion $this-> listView() wird bestimmt, welcher Blog abgefragt wird, wie viele Beiträge pro Seite an-
gezeigt werden und auf welche Seite für die Einzelansicht verlinkt wird. Listing 4.57 Parameter bestimmen $entrysperpage = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'entrysperpage','sDEF'); $entrysperpage ($entrysperpage > 0) ? $entrysperpage : $this-> conf['listView.']['entrysPerPage']; $entrysperpage ($entrysperpage > 0) ? $entrysperpage : 10; $bid = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'bid', 'sDEF'); $bidmm = ($bid > 0) ? 'AND tx_elublog_blogentrys.bid='.$bid : ''; $bid = ($bid > 0) ? 'AND bid='.$bid : ''; $singleViewPID = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'singlePage','sDEF'); $singleViewPID = ($singleViewPID) ? $singleViewPID : $this-> conf['singleViewPID']; $this->singleViewPID = ($singleViewPID) ? $singleViewPID : 0;
Wenn in der Plug-in-Konfiguration kein Wert für die Beiträge pro Seite eingegeben wurde, wird der Wert aus der TypoScript-Konfiguration übernommen. Ist auch dieser leer, wird der Wert 10 verwendet. Genauso verhält es sich bei der Seiten-ID der Einzelansicht.
130
4.6 Flexforms Die Blog-ID (bid) der Plug-in-Konfiguration liefert die ID des darzustellenden Blogs. Diese wird in eine Erweiterung der WHERE-Klausel eingebaut, die bei der SQL-Abfrage nach den Blogbeiträgen angehängt wird. Diese Klausel sorgt dafür, dass nur Beiträge des gewählten Blogs selektiert werden. Wird der Wert 0 (alle Blogs) geliefert, wird nichts angehängt und die SQL-Abfrage demnach auch nicht auf einen Blog eingeschränkt. Damit der Wert in $entrysperpage verwendet wird, müssen wir folgende Änderung in derselben Funktion durchführen: Listing 4.58 Entrys per Page setzen // Suchen Sie folgende Zeile: $this->internal['results_at_a_time']=t3lib_div::intInRange($lConf ['results_at_a_time'],0,1000,3);
Die „3“ am Ende der Zeile ersetzen Sie mit $entrysperpage. Um die Blog-ID an die SQL-Abfrage zu übergeben, modifizieren Sie folgende Zeilen: Listing 4.59 Blog-ID setzen $res = $GLOBALS['TYPO3_DB']->exec_SELECT_mm_query('count (tx_elublog_blogentrys.uid)','tx_elublog_blogentrys','tx_elublog_blogentr ys_category_mm','tx_elublog_blogcategorys',$bidmm.' AND tx_elublog_blogentrys_category_mm.uid_foreign='.$this->piVars ['showCat']); $res = $this->pi_exec_query('tx_elublog_blogentrys',1,$bid); $res = $GLOBALS['TYPO3_DB']->exec_SELECT_mm_query('tx_elublog_blogentrys .*','tx_elublog_blogentrys','tx_elublog_blogentrys_category_mm','tx_elubl og_blogcategorys',$bidmm.' AND tx_elublog_blogentrys_category_mm .uid_foreign='.$this->piVars['showCat']); $res = $this->pi_exec_query('tx_elublog_blogentrys',0,$bid);
Fügen Sie jeweils die fett geschriebenen Teile hinzu. In der Funktion $this->getFieldContent() ändern Sie die Titelverarbeitung: Listing 4.60 Titel mit SingleViewPID verlinken case "title": return $this->pi_list_linkSingle($this->internal['currentRow'] [$fN],$this->internal['currentRow']['uid'],1,'','',$this->singleViewPID); break;
Um den „Zurück“-Link in der Einzelansicht mit der Seite für die Listenansicht zu verknüpfen, fügen Sie in die Funktion $this->singleView() folgende Zeilen am Anfang ein: Listing 4.61 Konfiguration auslesen $listViewPID = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'listPage','sDEF'); $listViewPID = ($listViewPID) ? $listViewPID : $this->conf ['listViewPID']; $listViewPID = ($listViewPID) ? $listViewPID : 0;
131
4 Frontend-Plug-ins Ist weder im Plug-in noch im TypoScript eine Seite für die Listenansicht definiert, wird 0 zurückgegeben. Das entspricht der aktuellen Seite. Auch der Marker für den Link muss angepasst werden. Listing 4.62 „Zurück“-Marker anpassen $markerArray['###BACKLINK###'] = $cObj->stdWrap($this-> pi_linkToPage($this->pi_getLL('back','Back'),$listViewPID),$this-> conf['singleView.']['backLink_stdWrap.']);
Ob in der Listenansicht der Teasertext beschnitten wird, wird ebenso wie die Anzeige des kompletten Blogbeitrags in der Funktion $this->pi_list_row() abgefragt. Folgende Zeilen gehören an den Anfang der Funktion: Listing 4.63 Die Konfiguration einlesen $tcrop = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'teaserCrop','sDEF'); $fullTextInList = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'fullTextInList','sDEF');
Dadurch ist eine Änderung der Marker-Zuweisung nötig. Listing 4.64 Marker neu zuweisen $markerArray['###BODYTEXT###'] = (($this->getFieldContent ('bodytextinlist') == 1) || ($fullTextInList == 1)) ? $cObj->stdWrap ($this->getFieldContent('bodytext'),$this->conf['listView.'] ['bodytext_stdWrap']) : ''; … $markerArray['###TEASERTEXT###'] = $cObj->stdWrap($this->cObj>crop($this->getFieldContent('teasertext'),$tcrop),$this>conf['listView.']['teasertext_stdWrap.']);
Damit ist das Plug-in fertig für den Einsatz.
4.7
Das Plug-in pi2 Nun sollten Sie in der Lage sein, das Plug-in selbst zu erstellen. Ein paar Hinweise und Anregungen. Das Plug-in soll folgende Module bereitstellen können:
Eine Liste aller Kategorien Eine Liste aller Tags Die letzten Kommentare Die Blogroll
Verwenden Sie die Plug-in-Konfiguration, um festzulegen, welches Modul dargestellt werden soll und von welchem Blog. Werten Sie die Modulwahl mit switch/case aus, und erstellen Sie für jedes Modul eine eigene Funktion. Alle Module lassen sich mit den eben gelernten Standard-Datenbankabfragen erstellen.
132
5 5
Dokumentation und Abschluß
Jede Extension sollte ausreichend dokumentiert sein. Das betrifft nicht nur die ExtensionDokumentation, die genau erklären muss, wie die Extension verwendet wird, sondern auch den Code, der auch für andere Entwickler nachvollziehbar sein soll.
5.1
Code dokumentieren mit extdeveval Die Extension extdeveval bringt viele nützliche Funktionen für Extension-Entwickler mit. Dazu gehört auch eine Hilfe für die Code-Dokumentation nach dem phpDoc-Format. Nach der Installation finden Sie ein neues Modul bei den Admin-Werkzeugen:
Abbildung 5.1 extdeveval im Menü
Wählen Sie im Funktionsmenü des Moduls PHP script documentation help. Sie werden nun aufgefordert, eine Extension – in diesem Fall elublog – zu wählen. Dann erhalten Sie eine Liste aller Dateien. Nun können Sie alle relevanten Dateien, wie Plug-in-Klassendateien und Moduldateien, durchgehen. Die Änderungen, die ausgeführt werden, werden anhand verschiedener Farben dargestellt. Es wird ein Inhaltsverzeichnis aller Funktionen angelegt. Jede Funktion erhält einen Kommentarkopf mit einer Dummy-Beschreibung aller Parameter und des Rückgabewertes. Die korrekte Beschreibung muss nur noch hinzugefügt werden. Wenn Sie später Änderungen hinzufügen, führen Sie die Funktion einfach wieder aus, um den Funktionsindex zu aktualisieren. Durch die Zeilenangabe findet man gerade in großen Extensions leichter das Gesuchte. Die Beschreibung der Parameter und Rückgabewerte ist wichtig, um nicht erst die ganze Funktion zerpflücken zu müssen, um herauszufinden, was die Funktion erwartet und zurückgibt.
133
5 Dokumentation und Abschluß Listing 5.1 Funktionsübersicht der Datei mod2/index.php /** * [CLASS/FUNCTION INDEX of SCRIPT] * * * * 59: class tx_elublog_module2 extends t3lib_SCbase * 67: function init() * 84: function menuConfig() * 100: function main() * 125: function jumpToUrl(URL) * 168: function printContent() * 179: function moduleContent() * 196: function getNewPostButton() * 213: function getPostList() * 273: function getFunctions($table,$row) * * TOTAL FUNCTIONS: 9 * (This index is automatically created/updated by the extension "extdeveval") * */
Innerhalb der Funktion sollten Sie ebenfalls Kommentare hinterlassen, um bestimmte Abschnitte zu dokumentieren.
5.2
Extension-Dokumentation schreiben Auch wenn man gerade Männern nachsagt, nie Handbücher zu lesen, so ist eine ausführliche Dokumentation unerlässlich. Sie zeigt dem Leser nicht nur auf, wie eine Extension funktioniert, sondern auch, welche Möglichkeiten der Konfiguration zur Verfügung stehen. Nicht wenige Integratoren lehnen es ab, Extensions ohne Dokumentation zu installieren. Verwenden Sie also auf die Dokumentation dieselbe Sorgfalt wie auf die Programmierung.
Abbildung 5.2 Extensions ohne swx-Datei im /doc-Verzeichnis erzeugen einen Render-Fehler im TER.
134
5.2 Extension-Dokumentation schreiben
5.2.1
Die Vorlage
Die Dokumentation wird nicht nur in der Extension mitgeliefert, sondern auch online verfügbar gemacht. Dazu rendert das TER die Dokumentation. Nach dem Upload einer Extension steht sie nach kurzer Zeit automatisch unter http://typo3.org/documentation/document-library/extension-manuals und bei den einzelnen Extensions unter http://typo3.org/extensions/repository zur Verfügung. Aus diesem Grund muss die Dokumentation aus einer eigenen Vorlage heraus erstellt werden. Um diese Vorlage nutzen zu können, benötigen Sie OpenOffice1. Laden Sie die Vorlage von http://typo3.org/documentation/document-library/core-documentation/doc_template/current/ herunter, öffnen Sie sie in OpenOffice, und speichern Sie sie als Vorlage ab. Dokumentationen werden im /doc-Verzeichnis der Extension als OpenOffice 1.0-Dokument (.swx) abgelegt.
5.2.2
Der Aufbau der Dokumentation
Die Dokumentation hat einen vorgegebenen Aufbau, von dem nicht abgewichen werden sollte. Sie sollten nicht benötigte Abschnitte aber entfernen. Das Dokument gliedert sich in folgende Abschnitte:
Inhaltsangabe Introduction: Eine kurze Erklärung, was die Extension macht. Hier können auch Screenshots, beispielsweise von der Frontend-Ausgabe, hinterlegt werden.
Users Manual: Erklärt, wie die Extension vom Integrator und von den FrontendBenutzern verwendet wird.
Administration: Erklärt Installation, Systemvoraussetzungen und Wartung für den Administrator, einschließlich der Extension-Konfiguration über den Extension-Manager.
Configuration: In diesem Abschnitt wird die Konfiguration erklärt. Dazu gehört eine vollständige Auflistung aller TypoScript-Eigenschaften und der Plug-in-Konfiguration.
Tutorial: Eine kurze und einfache Einführung in die Extension. Am besten anhand eines Beispiels.
Known Problems: Probleme und Inkompatibilitäten, die dem Autor bekannt sind. To-Do list: Eine optionale Liste der Aufgaben und Features, die noch offen sind und in einer der späteren Versionen gelöst sein sollen.
Changelog: Dieser Abschnitt enthält die Änderungen an der Extension, sollte aber nicht mehr verwendet werden. Verwenden Sie für das Changelog stattdessen die Datei Change Log im Extension-Verzeichnis. Weisen Sie in der Dokumentation nur auf diese Datei hin. 1
http://www.openoffice.org
135
5 Dokumentation und Abschluß Nicht jede Extension benötigt alle diese Abschnitte. Wird ein Abschnitt nicht benötigt, löschen Sie ihn. Das sorgt wiederum für Übersicht in der Online-Dokumentation.
5.2.3
Vorlagenstile
Das TER rendert die Vorlage auf Basis der eingesetzten Stile. Dazu wurde ein Satz eigener Stile erstellt, der zu verwenden ist. Alle anderen Stile werden beim Rendern ignoriert. Tabelle 5.1 Stile in der Vorlagendatei Stil
Verwendung
Text body
Der Standardstil. Dieser kommt im normalen Text zum Tragen.
Table heading
Wird für Tabellenüberschriften verwendet
Table contents
Stil für den Tabelleninhalt
Preformatted text
Codebeispiele, TypoScript u.Ä. werden mit diesem Stil ausgezeichnet.
Heading 1
Überschriften für die Hauptabschnitte. Das TER rendert für jeden Hauptabschnitt eine neue HTML-Seite.
Heading 2
Für die Abschnitte innerhalb der Hauptabschnitte
Heading 3
Weitere Untergliederung
Heading 4
Letzte Ebene der Untergliederung
Source text
Eingefügte Codefragmente werden in diesem Stil dargestellt.
Die Verwendung von Bildern in der Dokumentation erfordert, dass die Bilder in das Dokument eingefügt werden und nicht nur darauf verwiesen wird. Dazu wählen Sie im Menü Bearbeiten > Inhalte einfügen. In dem folgenden Dialog wählen Sie Bitmap.
5.2.4
Die Dokumentation verfassen
Wenn Sie sich schließlich an das Schreiben der Dokumentation machen, behalten Sie immer im Hinterkopf, dass nicht alle Leser denselben Wissensstand wie Sie selbst haben. Gerade Anfänger sind schnell frustriert, wenn Wissen vorausgesetzt wird, das ein Anfänger noch nicht haben kann. Sie müssen keinen ausgewachsenen Roman schreiben, aber wenn Sie unsicher sind, ob Sie ein bestimmtes Detail beschreiben sollen oder nicht, sollten Sie es lieber tun. Auch Screenshots sollten nicht fehlen. Versuchen Sie, die Extension allgemeinverständlich zu beschreiben.
136
5.3 Upload ins TER
5.3
Upload ins TER Ist die Extension fertig und dokumentiert, wird es Zeit, sie in TER hochzuladen. Klicken Sie im Extension-Manager auf Ihre Extension, und wählen Sie im Extension-Menü Upload to TER. Im folgenden Dialog sollten Sie eine kurze Zusammenfassung der Änderungen formulieren. Hier wird auch die Versionsnummer gesetzt. Wenn Ihre Extension genau das tut, was Sie von ihr erwarten, scheuen Sie sich nicht, eine Hauptversion 1.0.0. zu setzen. Sollten Bugs auftauchen (was bei praktisch jeder größeren Software der Fall ist), können Sie die Versionsnummer immer noch als Bug-Fix-Version anheben.
Abbildung 5.3 Upload ins TER
Nach dem Upload wird die Extension im TER zur Verfügung gestellt und taucht im Extension-Manager auf, sofern die Extension-Liste upgedatet wurde. Bis die Dokumentation online erscheint, kann es aber ein wenig dauern. Gratulation, Ihre Extension ist fertig!
137
II Teil II – Funktionsreferenz zur klassischen Extensionprogrammierung
6 6
Datenbank
6.1 $GLOBALS['TYPO3_DB'] Insbesondere beim Zugriff auf Datenbanken ist darauf zu achten, dass ausschließlich die TYPO3-eigenen Datenbank-Handler verwendet werden. Die Klasse t3lib_DB bildet hierfür das sogenannte Datenbank-Abstraktions-Layer (DBAL). Sie ist sowohl im Backend als auch im Frontend in $GLOBALS['TYPO3_DB'] instanziiert.
6.1.1
exec_SELECTquery
$GLOBALS['TYPO3_DB']->exec_SELECTquery($select_fields, $from_table, $where_clause, $groupBy='', $orderBy='', $limit='');
Diese Methode führt eine Select-Abfrage aus und gibt ein Datenbankobjekt zurück. Das Objekt kann dann mittels sql_fetch_assoc oder sql_fetch_row in ein assoziatives Array umgewandelt werden (nicht mysql_fetch_assoc). Listing 6.1 Abfrage aller Frontend-User, die gerade angemeldet sind $selectRes = $GLOBALS['TYPO3_DB']->exec_SELECTquery('username', 'fe_users', 'disable = 0 AND is_online = 1');
6.1.2
exec_SELECT_queryArray
$GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($queryParts);
Dies ist eine Abwandlung von exec_SELECTquery, durch die gute Lesbarkeit vor allem für komplexere Abfragen sehr zu empfehlen.
141
6 Datenbank Listing 6.2 Abfrage aller Frontend-User, die gerade angemeldet sind $selectRes = $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray(array( 'SELECT' => 'username', 'FROM' => 'fe_users', 'WHERE' => 'disable = 0 AND is_online = 1', 'GROUPBY' => '', 'ORDERBY' => '', 'LIMIT' => '' ));
6.1.3
exec_SELECTgetRows
$GLOBALS['TYPO3_DB']->exec_SELECTgetRows($select_fields, $from_table, $where_clause, $groupBy='', $orderBy='', $limit='', $uidIndexField='');
Führt eine Select-Abfrage aus und gibt ein assoziatives Array mit allen Ergebnissen zurück. Sehr interessant ist vor allem der letzte Parameter $uidIndexField. Falls die Abfrage ein eindeutiges Feld enthält wie z.B. uid, so werden die Keys des ausgegebenen Arrays mit diesem Feld gefüllt. Listing 6.3 Abfrage aller Frontend-User, die gerade angemeldet sind $selectRows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid, username', 'fe_users', 'disable = 0 AND is_online = 1', '', '', '','uid');
6.1.4
exec_SELECT_mm_query
$GLOBALS['TYPO3_DB']->exec_SELECT_mm_query($select, $local_table, $mm_table, $foreign_table, $whereClause='', $groupBy='', $orderBy='', $limit='');
Dient zur Abfrage von n-n-Beziehungen zwischen $local_table und $foreign_table. Verknüpft sind die beiden Tabellen über $mm_table. Zu beachten ist vor allem bei gleichnamigen Feldern in $local_table und $foreign_table wie etwa uid oder pid, dass hierfür entsprechende Aliasse in $select vergeben werden. Listing 6.4 Beispiel $selectRes = $GLOBALS['TYPO3_DB']->exec_SELECT_mm_query( 'product, name', 'tx_extkey_products', 'tx_extkey_products_category_mm', 'tx_extkey_categories'); while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($selectRes)) { $content.= $row['product'].':'.$row['name'].'
'; } /* Ergebnis in $content: Kaffee:Arabica Kaffee:Robusta */
142
6.1 $GLOBALS['TYPO3_DB']
6.1.5
exec_INSERTquery
$GLOBALS['TYPO3_DB']->exec_INSERTquery($table, $fields_values, $no_quote_fields=FALSE);
Fügt einen Datensatz in die Tabelle $table mit den im Array $field_values definierten Werten ein. Listing 6.5 Beispiel $GLOBALS['TYPO3_DB']->exec_INSERTquery('fe_users', array( 'username' => 'mickey', 'password' => 'start123', 'usergroup' => '4', 'name' => 'Mickey Maus', 'tstamp' => time() ));
6.1.6
exec_UPDATEquery
$GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, $where, $fields_values, $no_quote_fields=FALSE);
Führt ein SQL Update auf $table aus. Die Bedingungen werden in $where definiert und die zu aktualisierenden Felder im Array $fields_values. Listing 6.6 Beispiel $GLOBALS['TYPO3_DB']->exec_UPDATEquery('fe_users', 'username = \'mickey\'', array('disable' => '1'));
6.1.7
exec_DELETEquery
$GLOBALS['TYPO3_DB']->exec_DELETEquery($table, $where);
Führt ein SQL Delete auf $table aus. Die Bedingungen werden in $where definiert. Listing 6.7 Beispiel $GLOBALS['TYPO3_DB']->exec_DELETEquery('fe_users', 'username = \'mickey\'');
6.1.8
sql_fetch_assoc
$GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
Pendant zu mysql_fetch_assoc; um den Datenbank-Handler geschlossen im TYPO3-Core zu belassen, sollte auch unbedingt diese Methode genutzt werden.
143
6 Datenbank Listing 6.8 Beispiel: alphabetisch sortierte Liste aller User, die derzeit online sind $selectRes = $GLOBALS['TYPO3_DB']->exec_SELECTquery('username', 'fe_users', 'disable = 0 AND is_online = 1', '', 'username'); $usersOnline = array(); while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($selectRes)) { $usersOnline[] = $row['username']; }
6.1.9
sql_fetch_row
$GLOBALS['TYPO3_DB']->sql_fetch_row($res);
Siehe mysql_fetch_assoc, Pendant zu mysql_fetch_row.
6.1.10
searchQuery
$GLOBALS['TYPO3_DB']->searchQuery($searchWords,$fields,$table);
Erzeugt eine SQL-Abfragebedingung, um in mehreren Datenbankfeldern $fields nach den Suchbegriffen $searchWords zu suchen. Listing 6.9 Suche in den Feldern „username“ und „name“ nach „peter“ und „muster“ $whereClause = $GLOBALS['TYPO3_DB']->searchQuery(array('peter', 'muster'),array('name', 'username'), 'fe_users'); /* Ergebnis in $whereClause: (fe_users.name LIKE '%peter%' OR fe_users.username LIKE '%peter%') AND (fe_users.name LIKE '%muster%' OR fe_users.username LIKE '%muster%') */
6.1.11
listQuery
$GLOBALS['TYPO3_DB']->listQuery($field, $value, $table);
Erzeugt eine SQL-Abfragebedingung, um in kommaseparierten Listen nach einem bestimmten Wert $value zu suchen. Die kommaseaprierte Liste steht hierbei im Feld $field in der Tabelle $table. Listing 6.10 Suche im Listenfeld „Hersteller“ nach der Herstellernummer „25“ $whereClause = $GLOBALS['TYPO3_DB']->listQuery('hersteller', '25', 'tx_t3ref_produkte'); /* Ergebnis in $whereClause:
144
6.1 $GLOBALS['TYPO3_DB'] (hersteller LIKE '%,25,%' OR hersteller LIKE '25,%' OR hersteller LIKE '%,25' OR hersteller='25') */
6.1.12
splitGroupOrderLimit
$GLOBALS['TYPO3_DB']->splitGroupOrderLimit($str);
Zerlegt eine SQL-Abfrage in ein Array, optimal für exec_SELECT_queryArray. Listing 6.11 Beispiel $selectArr = $GLOBALS['TYPO3_DB']->splitGroupOrderLimit( "hersteller = '25' and lagerbestand > 0 group by menge limit 0,100"); /* Ergebnis in $selectArr: Array ( [WHERE] => hersteller = '25' and lagerbestand > 0 [GROUPBY] => menge [ORDERBY] => [LIMIT] => 0,100 ) */
6.1.13
quoteStr
$GLOBALS['TYPO3_DB']-> quoteStr($str, $table);
Ersatz der PHP-Funktion addslashes(). Listing 6.12 Beispiel mit Suchtext: Peter „PM“ Muster $quoteString = $GLOBALS['TYPO3_DB']-> quoteStr('Peter "PM" Muster', 'fe_users'); /* Ergebnis in $quoteString: Peter \"PM\" Muster */
6.1.14
fullQuoteStr
$GLOBALS['TYPO3_DB']-> fullQuoteStr($str, $table);
Wie quoteStr, jedoch mit slashes vor und hinter dem String.
145
6 Datenbank Listing 6.13 Beispiel mit Suchtext: Peter „PM“ Muster $quoteString = $GLOBALS['TYPO3_DB']-> fullQuoteStr('Peter "PM" Muster', 'fe_users'); /* Ergebnis in $quoteString: 'Peter \"PM\" Muster' */
6.1.15
fullQuoteArray
$GLOBALS['TYPO3_DB']->fullQuoteArray($arr, $table, $noQuote=FALSE);
Erweitert fullQuoteStr um die Funktionalität, ein Array abzuarbeiten. Wird Parameter $noQuote gefüllt (String oder Array), so können bestimmte Keys im Array ausgeschlossen werden, z.B. für Datenbankfelder. Listing 6.14 Beispiel mit zwei Suchtexten $quoteArray = $GLOBALS['TYPO3_DB']-> fullQuoteArray(array('Peter "PM" Muster', 'Eva "EM" Muster'), 'fe_users'); /* Ergebnis in $quoteArray: Array ( [0] => 'Peter \"PM\" Muster' [1] => 'Eva \"EM\" Muster' ) */
Listing 6.15 Beispiel mit einem Suchtext und $noQuote $quoteArray = $GLOBALS['TYPO3_DB']-> fullQuoteArray(array('select' => 'name, username', 'where' => 'Peter "PM" Muster'), 'fe_users', 'select'); /* Ergebnis in $quoteArray: Array ( [select] => name, username [where] => 'Peter \"PM\" Muster' ) */
6.1.16
escapeStrForLike
$GLOBALS['TYPO3_DB']->escapeStrForLike($str, $table);
Die Zeichen _ und % werden maskiert. Listing 6.16 Beispiel mit 100% $escapeString = $GLOBALS['TYPO3_DB']->escapeStrForLike('100%', 'tx_t3ref_bewertungen');
146
6.1 $GLOBALS['TYPO3_DB'] /* Ergebnis in $escapeString: 100\% */
6.1.17
cleanIntArray
$GLOBALS['TYPO3_DB']->cleanIntArray($arr);
Alle Werte in einem eindimensionalen Array werden in Integer-Werte umgewandelt. Listing 6.17 Beispiel $intArr = $GLOBALS['TYPO3_DB']->cleanIntArray(array(100,'69.99','5,5')); /* Ergebnis in $intArr: Array ( [0] => 100 [1] => 69 [2] => 5 ) */
6.1.18
cleanIntList
$GLOBALS['TYPO3_DB']->cleanIntList($list);
Alle Werte in einer kommaseparierten Liste werden in Integer-Werte umgewandelt. Listing 6.18 Beispiel $intList = $GLOBALS['TYPO3_DB']->cleanIntList('100,69.99,5a2'); /* Ergebnis in $intList: 100,69,5 */
6.1.19
debug_lastBuiltQuery
$GLOBALS['TYPO3_DB']->debug_lastBuiltQuery;
Enthält die letzte erzeugte SQL-Abfrage. Hierfür muss eine der beiden folgenden Optionen gesetzt sein: $GLOBALS['TYPO3_DB']->store_lastBuiltQuery = true; oder $GLOBALS['TYPO3_DB']->debugOutput = true;
147
6 Datenbank Listing 6.19 Beispiel $debugQuery = $GLOBALS['TYPO3_DB']->debug_lastBuiltQuery; /* Ergebnis in $debugQuery: SELECT uid,username FROM fe_users WHERE disable = 0 AND is_online = 1 */
6.2 tslib_pibase Standardmäßig erweitert jedes Frontend-Plug-in die Klasse tslib_pibase. Hier finden sich einige praktische Funktionen, mit denen es möglich ist, bestimmte Abfragen in wenigen Zeilen Quellcode auszuführen.
6.2.1
pi_exec_query
$this->pi_exec_query($table, $count=0, $addWhere='', $mm_cat='', $groupBy='', $orderBy='', $query='');
Führt eine SQL-Abfrage aus, primär gedacht, um Datensätze innerhalb einer Seite abzufragen. Ist $query nicht gesetzt, so wird immer nur die aktuelle pid abgefragt mit allen aktiven Elementen, je nachdem, welche Felder in der Tabelle vorhanden sind, werden auch deleted, hidden, starttime, endtime etc. mit berücksichtigt. Listing 6.20 Beispiel: Tabelle pages: $result = $this->pi_exec_query('pages', 0); while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) $items[] = array('uid' => $row['uid'], 'title' => $row['title']); /* Ergebnis in $items: Array ( [0] => Array ( [uid] => 41 [title] => subpage 1 ) [1] => Array ( [uid] => 42 [title] => subpage 2 ) ) Ausgeführte SQL-Abfrage: SELECT pages.* FROM pages WHERE pid IN (25) AND pages.deleted=0 AND pages.t3ver_statepi_exec_query('pages', 1); $item = $GLOBALS['TYPO3_DB']->sql_fetch_row($result); /* Ergebnis in $item: Array ( [0] => 2 ) Ausgeführte SQL-Abfrage: SELECT count(*) FROM pages WHERE pid IN (25) AND pages.deleted=0 AND pages.t3ver_statepi_exec_query('fe_users', 0, '', '', '' ,'', 'FROM fe_users'); while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) $items[] = array('username' => $row['username'], 'name' => $row['name']); /* Ergebnis in $item: Array [0] [1] [2] )
( => Array ( [username] => test [name] => ) => Array ( [username] => max [name] => ) => Array ( [username] => eva [name] => )
Ausgeführte SQL-Abfrage: SELECT fe_users.* FROM fe_users LIMIT 0,20 */
6.2.2
pi_getPidList
$this->pi_getPidList($pid_list, $recursive = 0)
Erzeugt eine kommaseparierte Liste von Seiten-IDs innerhalb der ebenfalls kommaseparierten Liste $pid_list. Mit einem Wert größer 0 für $recursive kann auch um diesen Wert rekursiv gesucht werden. Listing 6.23 Beispiel: Suche alle Seiten innerhalb der Page-IDs 12 und 24 $pages = $this->pi_getPidList('24,12',2); /* Ergebnis in $pages:
149
6 Datenbank 44,25,41,42,26,24,36,12 */
6.2.3
pi_getRecord
$this->pi_getRecord($table,$uid,$checkPage=0)
Es wird ein einzelner Datensatz aus Tabelle $table abgefragt, es gibt nur die Bedingung auf eine gezielte $uid. Mit $checkPage kann zusätzlich abgefragt werden, ob dieser Datensatz auf der jeweiligen Seite verfügbar ist. Listing 6.24 Beispiel $product = $this->pi_getRecord('tx_extkey_products', 1); /* Ergebnis in $products: Array ( [uid] => 1 [pid] => 6 [tstamp] => 1255874092 [crdate] => 1255874092 [cruser_id] => 1 [product] => Kaffee [category] => 2 )
6.2.4
pi_prependFieldsWithTable
$this->pi_prependFieldsWithTable($table,$fieldList)
Fügt allen Feldern in der kommaseparierten Liste $fieldList den Tabellennamen $table vorne an. Listing 6.25 Beispiel $fields = $this->pi_prependFieldsWithTable('tx_extkey_products', 'name, category, price'); /* Ergebnis in $fields: tx_extkey_products.name,tx_extkey_products.category, tx_extkey_products.price */
150
6.3 cObj
6.3 cObj
6.3.1
DBgetDelete
$this->cObj->DBgetDelete($table, $uid, $doExec=FALSE)
„Löscht“ einen Datensatz aus Tabelle $table mit $uid als Bedingung. Sofern die Tabelle das Feld „deleted“ enthält, wird der Datensatz nicht physikalisch gelöscht, sondern es wird lediglich das Feld „deleted“ auf „1“ gesetzt. Bleibt $doExec false, so gibt die Funktion die SQL-Abfrage zurück, die ausgeführt werden würde – dies dient allerdings nur zur Information. Die SQL-Abfrage sollte immer mit $doExec = true ausgeführt werden. Im Erfolgsfall wird „1“ zurückgegeben. Listing 6.26 Beispiel $delete = $this->cObj->DBgetDelete('fe_users', '1', false); /* Ergebnis in $delete: UPDATE fe_users SET deleted='1' WHERE uid=1 */ $deleted = $this->cObj->DBgetDelete('fe_users', '1', true); /* Ergebnis in $deleted: 1 */
6.3.2
DBgetInsert
$this->cObj->DBgetInsert($table, $pid, $dataArr, $fieldList, $doExec=FALSE)
Generiert einen SQL-Insert-Befehl, der alle Systemfelder wie „tstamp“, „crdate“, „cruser_id“, „fe_cruser_id“ und „fe_crgroup_id“ automatisch berücksichtigt, sofern sie in der Tabelle vorhanden sind. Es werden ausschließlich die Werte aus dem Array $dataArr in die Tabelle $table eingefügt, die in der kommaseparierten Liste $fieldList stehen. Listing 6.27 Beispiel $dataArr = array( 'username' => 'mickey', 'password' => 'start123', 'name' => 'Mickey Maus', 'usergroup' => '2',
151
6 Datenbank 'address' => 'Entenstr. 9' ); $insert = $this->cObj->DBgetInsert('fe_users', '6', $dataArr, 'username,password,name,usergroup', false); /* Ergebnis in $insert: INSERT INTO fe_users ( username, password, name, usergroup, tstamp, crdate, cruser_id, fe_cruser_id, pid ) VALUES ( 'mickey', 'start123', 'Mickey Maus', '2', '1255884274', '1255884274', '0', '0', '6' ) */ $inserted = $this->cObj->DBgetInsert('fe_users', '6', $dataArr, 'username,password,name,usergroup', true); /* Ergebnis in $inserted: 1 */
6.3.3
DBgetUpdate
$this->cObj->DBgetUpdate($table, $uid, $dataArr, $fieldList, $doExec=FALSE)
Generiert einen SQL-Update-Befehl, der das Feld „tstamp“ automatisch berücksichtigt, sofern es vorhanden ist. Zum Ausführen muss $doExec = true gesetzt werden. Listing 6.28 Beispiel $dataArr = array( 'address' => 'Entenstr. 9' ); $update = $this->cObj->DBgetUpdate('fe_users', '11', $dataArr, 'address', false) /* Ergebnis in $update: UPDATE fe_users SET address='Entenstr. 9', tstamp='1255884909' WHERE uid=11 */ $updated = $this->cObj->DBgetUpdate('fe_users', '11', $dataArr, 'address', true) /* Ergebnis in $updated: 1 */
152
6.3 cObj
6.3.4
enableFields
$this->cObj->enableFields($table,$show_hidden=0)
Erzeugt die für SQL-Abfragen benötigten Bedingungen, um nur die aktuell „aktiven“ Datensätze zu bekommen. Es werden nur Bedingungen erzeugt für Systemfelder, die in der abgefragten Tabelle vorhanden sind. Listing 6.29 Beispiele $whereCategories = $this->cObj->enableFields('tx_extkey_categories'); /* Ergebnis in $whereCategories: AND tx_extkey_categories.deleted=0 */ $whereTTContent = $this->cObj->enableFields('tt_content', 1); /* Ergebnis in $whereTTContent; AND tt_content.deleted=0 AND tt_content.t3ver_state [1] => [2] => [3] => [4] => [5] => )
flags scripts struktur styles templates user_upload
*/
7.1.5
getAllFilesAndFoldersInPath
t3lib_div::getAllFilesAndFoldersInPath(array $fileArr,$path,$extList='', $regDirs=0,$recursivityLevels=99,$excludePattern='')
Ermittelt innerhalb von $path alle Dateien und Verzeichnisse. Über das Array $fileArr können bereits zuvor ausgelesene Verzeichnisse dem Ergebnis vorangestellt, über die kommaseparierte Liste $extList bestimmte Dateierweiterungen gefiltert werden. $regDirs steuert, ob im Ergebnis-Array auch die Verzeichnisnamen separat aufgeführt werden sollen. Wie viele Ebenen rekursiv ausgelesen werden sollen, steuert $recursivityLevels. Mit Hilfe eines regulären Ausdrucks in $excludePattern können bestimmte Dateien oder Verzeichnisse ausgeschlossen werden. Listing 7.5 Beispiel $files = t3lib_div::getAllFilesAndFoldersInPath( array(), 'fileadmin/', '', 1 ); /* Auszug aus $files: Array ( [0] => fileadmin/ [65a5bd5b6c270c9628c3e90ca979996b] [1] => fileadmin/flags/ [472a2f8cda5b585bb8cb64b349e1f61c] [5cd2cbdc135d3c3a90f65b756877db77] [814da70ac0d558d15295303e3f7e249b] [6f7e898514e7baa8558a535608fbe699] [b6d02f3ee6b3ceb12644cb022bf7b444] [...] => ... )
=> fileadmin/logfile.log => => => => =>
fileadmin/flags/ar.gif fileadmin/flags/ar.png fileadmin/flags/ar_d.gif fileadmin/flags/bg.gif fileadmin/flags/bg.png
Der Array-Key ist der jeweilige md5-hash der Datei. */
157
7 Dateisystem
7.1.6
getFileAbsFileName
t3lib_div::getFileAbsFileName($filename, $onlyRelative=TRUE,$relToTYPO3_mainDir=FALSE)
Gibt den absoluten Dateipfad zur Datei in $filename an, wobei $filename auch ein Verzeichnis sein kann. $onlyRelative steuert, ob nur Dateien innerhalb des aktuellen Seitenpfades berücksichtigt werden. Standardmäßig bezieht sich der relative Dateipfad in $filename auf den aktuellen Seitenpfad, alternativ kann sich der Pfad mit $relToTYPO3_mainDir = true auf das TYPO3Core-Verzeichnis beziehen. Listing 7.6 Beispiel $file = t3lib_div::getFileAbsFileName('fileadmin/logfile.log'); /* Ergebnis in $file: /srv/www/domain.com/htdocs/fileadmin/logfile.log */
7.1.7
getFilesInDir
t3lib_div::getFilesInDir($path,$extensionList='',$prependPath=0, $order='',$excludePattern='')
Liest alle Dateien innerhalb des Verzeichnisses $path ein. $extensionList ist eine optionale kommaseparierte Liste, um nur bestimmte Dateierweiterungen einzulesen. Wird $prependPath = 1 gesetzt, so wird allen Dateinamen der Pfad vorangestellt. Mit $order = 1 wird die Dateiliste alphabetisch sortiert, $order = 'mtime' nach dem Aktualisierungsdatum. Listing 7.7 Beispiel $files = t3lib_div::getFilesInDir('fileadmin/flags/', 'png', 0, 1); /* Ergebnis in $files: Array ( [5cd2cbdc135d3c3a90f65b756877db77] [b6d02f3ee6b3ceb12644cb022bf7b444] [df58e1c2dd9a87f2b86b33b0e2cfe688] [f0aa7d05b27a5a85716c911f7e34556c] [...] => ... ) */
158
=> => => =>
ar.png bg.png bs.png ca.png
7.1 t3lib_div
7.1.8
getURL
t3lib_div::getURL($url, $includeHeader = 0, $requestHeaders = false, &$report = NULL)
Liest eine Datei oder URL aus und gibt den Dateiinhalt zurück. Optional wird der httpHeader mit ausgelesen ($includeHeader = 1). Auch der http-Header der Anfrage kann mittels $requestHeaders angepasst werden. Die Funktion nutzt cURL, setzt also ein installiertes cURL-Paket voraus. Listing 7.8 Beispiel $rss = t3lib_div::getURL('http://snippets.typo3.org/snippets.xml'); /* Ergebnis in $rss:
fileadmin/file1.csv [1] => fileadmin/ext/file2.csv ) */
7.1.14 resolveBackPath t3lib_div::resolveBackPath($pathStr)
Löst überflüssige relative Rücksprünge im Pfad $pathStr auf. Listing 7.14 Beispiel $path = t3lib_div::resolveBackPath( 'fileadmin/first/path/../../second/path/'); /* Ergebnis in $path: fileadmin/second/path/ */
7.1.15 rmdir t3lib_div::rmdir($path,$removeNonEmpty=false)
Erweitert die PHP-Funktion rmdir um die Möglichkeit, rekursiv Verzeichnisse löschen zu können inklusive aller enthaltenen Dateien. Im Erfolgsfall gibt die Funktion true zurück. $path muss absolut sein. Listing 7.15 Beispiel $deleted = t3lib_div::rmdir('/srv/www/domain.com/htdocs/fileadmin/ext/', true);
161
7 Dateisystem
7.1.16 split_fileref t3lib_div::split_fileref($fileref)
Bricht den Pfad zu einer Datei in Pfad, Datei, Dateiname und Erweiterung auf. Listing 7.16 Beispiel $filerefParts = t3lib_div::split_fileref('fileadmin/logfile.log'); /* Ergebnis in $filerefParts: Array ( [path] => fileadmin/ [file] => logfile.log [filebody] => logfile [fileext] => log ) */
7.1.17 tempnam t3lib_div::tempnam($filePrefix)
Ersetzt die PHP-Funktion tempnam(). Alle Dateinamen werden innerhalb des Verzeichnisses typo3temp erzeugt. Listing 7.17 Beispiel $tmpfile = t3lib_div::tempnam('ext'); /* Ergebnis in $tmpfile: /path/to/typo3/htdocs/typo3temp/ext076.tmp */
7.1.18 unlink_tempfile t3lib_div::unlink_tempfile($uploadedTempFileName)
Löscht die temporäre Datei $uploadedTempFileName im Verzeichnis „typo3temp/“ und wird üblicherweise nach der Funktion t3lib_div::upload_to_tempfile() aufgerufen. Es können nur Dateien innerhalb des Verzeichnis „typo3temp/“ gelöscht werden.
7.1.19 upload_copy_move t3lib_div::upload_copy_move($source,$destination)
162
7.1 t3lib_div Verschiebt eine hochgeladene Datei in den absoluten Pfad $destination. Wird als $source keine hochgeladene Datei angegeben, wird eine Kopie der Datei erstellt. Listing 7.18 Beispiel $source = $_FILES['uploadedfile']['tmp_name']; $destination = t3lib_div::getFileAbsFileName('uploads'). '/'.$this->extKey.'/'. str_replace(" ","_",$_FILES['uploadedfile']['name']); $uploaded = t3lib_div::upload_copy_move($source,$destination); /* Ergebnis in $uploaded: true */
7.1.20 upload_to_tempfile t3lib_div::upload_to_tempfile($uploadedFileName)
Verschiebt eine hochgeladene Datei ins Verzeichnis typo3temp mit temporärem Dateinamen. Der Rückgabewert enthält im Erfolgsfall den Dateinamen. Listing 7.19 Beispiel $source = $_FILES['uploadedfile']['tmp_name']; $filename = t3lib_div::upload_to_tempfile($source); /* Ergebnis in $filename: /srv/www/domain.tld/htdocs/typo3temp/upl1D5.tmp */
7.1.21 verifyFilenameAgainstDenyPattern t3lib_div::verifyFilenameAgainstDenyPattern($filename)
Überprüft den übergebenen Dateinamen gegen die Konfiguration in $GLOBALS['TYPO3_CONF_VARS']['BE']['fileDenyPattern']
und gibt false zurück, sobald der Dateiname übereinstimmt.
163
7 Dateisystem
7.1.22 writeFile t3lib_div::writeFile($file,$content)
Schreibt den String $content in die Datei $file. Existiert $file bereits, so wird die Datei überschrieben. Listing 7.20 Beispiel $written = t3lib_div::writeFile('fileadmin/data.txt','hello world'); /* Ergebnis in $written: true */
7.1.23 writeFileToTypo3tempDir t3lib_div::writeFileToTypo3tempDir($filepath,$content)
Schreibt $content in eine Datei innerhalb des Verzeichnisses typo3temp. $filepath muss den absoluten Pfad enthalten, es werden auch Verzeichnisse unterhalb von typo3temp unterstützt. Im Erfolgsfall gibt die Funktion false zurück. Listing 7.21 Beispiel $written = t3lib_div::writeFileToTypo3tempDir( PATH_site.'typo3temp/data.txt','hello world' ); /* Ergebnis in $written: false */
164
8 8
8.1
Strings, Arrays und Umgebungsvariablen
Allgemeine Funktionen
8.1.1
_GET
t3lib_div::_GET($var=NULL)
Gibt alle Werte des globalen GET-Arrays zurück. Da die Werte normalisiert und alle Escape-Zeichen entfernt werden, sollte jeder Zugriff auf GET-Variablen über diese Methode erfolgen. Wird $var gesetzt, erfolgt als Rückgabe nur der Wert von $var. Listing 8.1 Aufruf einer URL mit „&showArticle=54“ $articleID = t3lib_div::_GET('showArticel'); $getVars = t3lib_div::_GET(); /* Ergebnis in $articleID: 54 Ergebnis in $getVars: Array ( [id] => 40 [showArticle] => 54 ) */
8.1.2
_GETset
t3lib_div::_GETset($inputGet,$key='')
Schreibt Eingabe Werte in $_GET
165
8 Strings, Arrays und Umgebungsvariablen Wird $key nicht gesetzt, so wird das gesamte Array $_GET überschrieben! Mit definiertem $key wird nur dieser Bereich neu geschrieben. Listing 8.2 Beispiel t3lib_div::_GETset(array("name" => "mickey maus"));
8.1.3
_GP
t3lib_div::_GP($var,$strip=0)
Gibt den Wert von $var zurück, wobei $var sowohl eine GET- als auch eine POSTVariable sein kann. Sollten beide Variablen vorhanden sein, so wird die POST-Variable zurückgegeben. Mit $strip=1 werden nur Arrays normalisiert. Listing 8.3 Beispiel $name = t3lib_div::_GP('name'); /* Ergebnis in $name: mickey maus */
8.1.4
_POST
t3lib_div::_POST($var=NULL)
Gleiche Funktionalität wie _GET für _POST-Variablen Listing 8.4 Beispiel $articleID = t3lib_div::_POST('showArticel'); $getVars = t3lib_div::_POST(); /* Ergebnis in $articleID: 54 Ergebnis in $getVars: Array ( [id] => 40 [showArticle] => 54 ) */
8.1.5
callUserFunction
t3lib_div::callUserFunction( $funcName,&$params,&$ref,$checkPrefix='user_',$errorMode=0 )
166
8.1 Allgemeine Funktionen Führt eine benutzerdefinierte Funktion aus. Standardmäßig sollten diese Funktionen mit dem Präfix „user_“ beginnen. Die Parameter werden als Referenz übergeben. Listing 8.5 Beispiel $userVar = array (); t3lib_div::callUserFunction('user_Func',$userVar,$this); function user_Func($refVar) { $refVar = array(1 => 'hello world'); } /* Ergebnis in $userVar: Array ( [1] => hello world ) */
8.1.6
clientInfo
t3lib_div::clientInfo($useragent='')
Basisinformationen über den Browser und das Betriebssystem des Clients. Listing 8.6 Beispiel $client = t3lib_div::clientInfo(); /* Ergebnis in $client: Array ( [BROWSER] => net [VERSION] => 5 [SYSTEM] => win [FORMSTYLE] => 1 ) */
8.1.7
compat_version
t3lib_div::compat_version($verNumberStr)
Überprüft die Kompatibilität zur übergebenen TYPO3-Version Listing 8.7 Beispiel $check = t3lib_div::compat_version("4.2.0"); /* Ergebnis in $check: 1 */
167
8 Strings, Arrays und Umgebungsvariablen
8.1.8
compileSelectedGetVarsFromArray
t3lib_div::compileSelectedGetVarsFromArray( $varList,array $getArray,$GPvarAlt=1 )
Bildet einen Auszug aus einem eindimensionalen Array, gesteuert über eine kommaseparierte Liste von keys. Wird kein Array definiert, so werden die GET- und POST-Variablen verwendet (Reihenfolge siehe _GP). Listing 8.8 Beispiel $vars = t3lib_div::compileSelectedGetVarsFromArray('name,email',array()); /* Ergebnis ind $vars: Array ( [name] => mickey maus [email] => [email protected] ) */
8.1.9
getHostname
t3lib_div::getHostname()
Gibt den Fully Qualified Domain Name zurück. Listing 8.9 Beispiel t3lib_div::getHostname()
8.1.10 getIndpEnv t3lib_div::getIndpEnv($getEnvName)
Pendant zu $_SERVER, allerdings systemunabhängig. Listing 8.10 Gültige Werte für $getEnvName: SCRIPT_NAME, SCRIPT_FILENAME, REQUEST_URI, PATH_INFO, REMOTE_ADDR, REMOTE_HOST, HTTP_REFERER, HTTP_HOST, HTTP_USER_AGENT, HTTP_ACCEPT_LANGUAGE, QUERY_STRING, TYPO3_DOCUMENT_ROOT, TYPO3_HOST_ONLY, TYPO3_HOST_ONLY, TYPO3_REQUEST_HOST, TYPO3_REQUEST_URL, TYPO3_REQUEST_SCRIPT, TYPO3_REQUEST_DIR, TYPO3_SITE_URL, _ARRAY
8.1.11 getThisUrl t3lib_div::getThisUrl()
Gibt den Host und Pfad zur aktuellen Seite zurück.
168
8.1 Allgemeine Funktionen Listing 8.11 Beispiel $url = t3lib_div::getThisUrl(); /* Ergebnis in $url: domain.com/path/to/script/ */
8.1.12 linkThisScript t3lib_div::linkThisScript(array $getParams = array())
Erzeugt die vollständige URL zum aktuellen Skript, über das Array $getParams können die mit zu übergebenden GET-Parameter gesteuert werden. Ein leeres Array entfernt alle GET-Parameter. Listing 8.12 Beispiel $url = t3lib_div::linkThisScript(array()); /* Ergebnis in $url: /index.php?id=40 */
8.1.13 linkThisUrl t3lib_div::linkThisUrl($url,array $getParams=array())
Die in $url übergebene vollständige URL wird geparst und mit den in $getParams übergebenen Parametern ergänzt, bestehende werden überschrieben. Listing 8.13 Beispiel $url = t3lib_div::linkThisUrl('http://www.domain.com/produkte.html?productid=lee r',array('productid' => '354', 'category' => 'coffee')) /* Ergebnis in $url: http://www.domain.com/produkte.html?productid=354&category=coffee */
8.1.14 locationHeaderUrl t3lib_div::locationHeaderUrl($path)
Erzeugt aus relativen und absoluten Pfaden vollständige URLs.
169
8 Strings, Arrays und Umgebungsvariablen Listing 8.14 Beispiel $url = t3lib_div::locationHeaderUrl('/absolute/path/to/script.html'); /* Ergebnis in $url: http://www.domain.com/absolute/path/to/script.html */ $url = t3lib_div::locationHeaderUrl('relativepath/script.html'); /* Ergebnis in $url: http://www.domain.com/current/path/relativepath/script.html */
8.1.15 makeInstance t3lib_div::makeInstance($className)
Erzeugt eine neue Instanz der Klasse $className – sollte unbedingt statt der PHPMethode „new“ verwendet werden. Listing 8.15 Beispiel $obj =
t3lib_div::makeInstance('tx_extkey_functions');
8.1.16 makeInstanceService t3lib_div::makeInstanceService($serviceType, $serviceSubType='', $excludeServiceKeys=array())
Erzeugt eine neue Instanz eines Service und gibt die Service-Class als Objekt zurück Listing 8.16 Beispiel if (is_object($service = t3lib_div::makeInstanceService('myService'))) { $content = $serviceObj->main($value); }
8.1.17 rmFromList t3lib_div::rmFromList($element,$list)
Löscht den Inhalt von $element aus der kommaseparierten Liste $list.
170
8.2 String-Funktionen Listing 8.17 Beispiel $newList = t3lib_div::rmFromList('24', '12,26,24,1,4'); /* Ergebnis in $newList: 12,26,1,4 */
8.1.18 sysLog t3lib_div::sysLog($msg, $extKey, $severity=0) Schreibt den Inhalt von $msg in den syslog des Servers. Listing 8.18 Gültige Werte für $severity: 0 1 2 3 4
8.2
= = = = =
info, notice, warning, error, fatal error
String-Funktionen
8.2.1
calcParenthesis
t3lib_div::calcParenthesis($string)
Berechnet den übergebenen String unter der Berücksichtigung von Klammern. Listing 8.19 Beispiel $value = t3lib_div::calcParenthesis('(4+20)/4'); /* Ergebnis on $value: 6 */
8.2.2
cmpFQDN
t3lib_div::cmpFQDN($baseIP, $list)
171
8 Strings, Arrays und Umgebungsvariablen Vergleicht den Fully Qualified Domain Name der $baseIP mit einer in $list übergebenen kommaseparierten Liste. Diese Liste darf Wildcards enthalten. Bei Übereinstimmung gibt die Funktion true zurück, ansonsten false. Listing 8.20 Beispiele für $list: subdomain.*.com *.domain.com Falsch wäre: sub*.domain.com
8.2.3
cmpIP
t3lib_div::cmpIP($baseIP, $list)
Vergleicht die IP mit einer in $list übergebenen kommaseparierten Liste. Diese Liste darf Wildcards enthalten. Bei Übereinstimmung gibt die Funktion true zurück, ansonsten false. Es werden sowohl IPv4 als auch IPv6 unterstützt. Listing 8.21 Beispiel für $list 192.168.10.*,192.168.11.*
8.2.4
convUmlauts
t3lib_div::convUmlauts($str)
Wandelt die deutschen Umlaute um. Listing 8.22 Beispiel $string = t3lib_div::convUmlauts('Ä Ö Ü ä ö ü ß'); /* Ergebnis in $string: Ae Oe Ue ae oe ue ss */
8.2.5
csvValues
t3lib_div::csvValues(array $row,$delim=',',$quote='"')
Erzeugt aus einem eindimensionalen Array eine Zeile csv.
172
8.2 String-Funktionen Listing 8.23 Beispiel $csv = t3lib_div::csvValues(array('13','coffee','beans')); /* Ergebnis in $csv: "13","coffee","beans" */
8.2.6
deHSCentities
t3lib_div::deHSCentities($str)
Macht die Bearbeitung von HTML-Entities mit htmlspecialchars rückgängig. Listing 8.24 Beispiel $str = t3lib_div::deHSCentities("""); /* Ergebnis in $str: " */
8.2.7
expandList
t3lib_div::expandList($list)
Eine kommaseparierte Liste von Integer-Werten mit Bereichen „von-bis“ wird als erweiterte kommaseaprierte Liste zurückgegeben mit allen Einzelwerten innerhalb dieser Bereiche. Listing 8.25 Beispiel $list = t3lib_div::expandList("1,5,6-20,98"); /* Ergebnis in $list: 1,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,98 */
8.2.8
fixed_lgd
t3lib_div::fixed_lgd_cs($string,$origChars)
Kürzt den String $string am Ende mit $preStr ab, sofern dieser mehr Zeichen enthält als $origChars.
173
8 Strings, Arrays und Umgebungsvariablen Listing 8.26 Beispiel $str = t3lib_div::fixed_lgd_cs("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt", 30); /* Ergebnis in $str: Lorem ipsum dolor sit amet,... */
8.2.9
fixed_lgd_pre
t3lib_div::fixed_lgd_pre($string,$chars)
Kürzt den String $string am Ende mit „...“ ab, sofern dieser mehr Zeichen enthält als $origChars. Listing 8.27 Beispiel $str = t3lib_div::fixed_lgd_pre("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt.", 36); /* Ergebnis in $str: ...sed do eiusmod tempor incididunt. */
8.2.10 formatForTextarea t3lib_div::formatForTextarea($content)
Optimierte Variante von htmlspecialchars(), sollte für jede Textarea verwendet werden. Listing 8.28 Beispiel $content = t3lib_div::formatForTextarea($content);
8.2.11 generateRandomBytes t3lib_div::generateRandomBytes($count)
Erzeugt einen Zufalls-String mit der Anzahl von $count-Zeichen. Als Bereich werden die gesamten 8 Bit genutzt.
174
8.2 String-Funktionen Listing 8.29 Beispiel $random = t3lib_div::generateRandomBytes(20); /* Ergebnis in $random: uðU†+é /anmeldung.html [method] => get [target] => main )
8.2.13 htmlspecialchars_decode t3lib_div::htmlspecialchars_decode($value)
Umkehrfunktion zur PHP-Funktion htmlspecialchars(). Listing 8.31 Beispiel $value = t3lib_div::htmlspecialchars_decode('&'); /* Ergebnis in $value: & */
8.2.14 implodeArrayForUrl t3lib_div::implodeArrayForUrl($name,array $theArray, $str='',$skipBlank=0,$rawurlencodeParamName=0)
Erzeugt aus dem multidimensionalen Array $theArray einen String, der die Wertepaare des Arrays als GET-Parameter enthält.
175
8 Strings, Arrays und Umgebungsvariablen $name ist hierbei ein Präfix für alle Keys des Arrays. Wird $skipBlank gesetzt, so werden nur GET-Parameter geschrieben, die auch einen Wert übergeben. $rawurlencodeParamName steuert die PHP-Funktion rawurlencode() für die Keys. Listing 8.32 Beispiel $url = t3lib_div::implodeArrayForUrl('product', array( 'id' => '52345', 'category' => '', 'group' => 'coffee,beans' ), '', 1); /* Ergebnis in $url: &product[id]=52345&product[group]=coffee%2Cbeans */
8.2.15 implodeAttributes t3lib_div::implodeAttributes(array $arr, $xhtmlSafe=FALSE,$dontOmitBlankAttribs=FALSE)
Erzeugt aus einem Array Attribute für bspw. ein html-Tag. $xhtmlSafe = true wird hier empfohlen, da diese Option gleichzeitig eventuell doppelt vorkommende Attribute ignoriert (hier wird jeweils das erste verwendet) und die Werte durch htmlspecialchars() bereinigt. Standardmäßig werden leere Attribute nicht berücksichtigt; falls allerdings $dontOmitBlankAttributes gesetzt ist, werden auch leere Attribute zurückgegeben. Listing 8.33 Beispiel $attr = t3lib_div::implodeAttributes(array( 'action' => '/anmeldung.html', 'Method' => 'get', 'target' => 'anmeldeformular' ), true); /* Ergebnis in $attr: action="/anmeldung.html" method="get" target="anmeldeformular" */
8.2.16 inList t3lib_div::inList($list, $item)
Sucht nach dem Element $item in der kommaseparierten Liste $list. Ist das Element vorhanden, gibt die Funktion true zurück, ansonsten false.
176
8.2 String-Funktionen Listing 8.34 Beispiel $status = (t3lib_div::inList('1,5,8,13,29,rehw,r7345j', 'reh')) ? 'gefunden' : 'nicht gefunden'; /* Ergebnis in $status: nicht gefunden */
8.2.17 int_from_ver t3lib_div::int_from_ver($verNumberStr)
Erzeugt einen Integer-Wert aus einer Versionsnummer im Format „x.x.x“, wobei jeder Teil der Versionsnummer bis 999 zählt. Listing 8.35 Beispiel $ver = t3lib_div::int_from_ver('5.0.13'); /* Ergebnis in $ver: 5000013 */
8.2.18 intInRange t3lib_div::intInRange($theInt,$min,$max=2000000000,$zeroValue=0)
Überprüft, ob $theInt innerhalb der Werte $min und $max liegt. Ist der Wert kleiner oder größer, so wird entweder $min oder $max ausgegeben. Falls der Wert kein Integer-Wert ist, wird er durch $zeroValue ersetzt. Listing 8.36 Beispiele $res[0] = t3lib_div::intInRange(5, 10); $res[1] = t3lib_div::intInRange(5, 1, 10); $res[2] = t3lib_div::intInRange('v', 1, 10); $res[3] = t3lib_div::intInRange(100, 1, 10); /* Ergebnis in $res: Array ( [0] => [1] => [2] => [3] => )
10 5 1 10
177
8 Strings, Arrays und Umgebungsvariablen
8.2.19 intval_positive t3lib_div::intval_positive($theInt)
Falls $theInt negativ ist, wird 0 zurückgegeben, positive Werte bleiben unverändert. Listing 8.37 Beispiele $res[0] = t3lib_div::intval_positive(-5); $res[1] = t3lib_div::intval_positive(10); $res[2] = t3lib_div::intval_positive('v'); /* Ergebnis in $res: Array ( [0] => 0 [1] => 10 [2] => 0 )
8.2.20 isFirstPartOfStr t3lib_div::isFirstPartOfStr($str, $partStr)
Überprüft, ob $partStr mit dem Anfang von $str übereinstimmt, und gibt true oder false zurück. Listing 8.38 Beispiel $str = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt"; $partStr =
"Lorem ipsum dolor sit amet";
$isFirstPart = t3lib_div::isFirstPartOfStr($str, $partStr); /* Ergebnis in $isFirstPart: true */
8.2.21 md5int t3lib_div::md5int($str)
Wandelt die ersten sieben Stellen des md5-Hash von $str in den Integer-Wert um, quasi der Integer-Hash von $str.
178
8.2 String-Funktionen Listing 8.39 Beispiel $intHash = t3lib_div::md5int('coffee'); /* Ergebnis in $intHash: 38711389 */
8.2.22 milliseconds t3lib_div::milliseconds()
microtime() in Millisekunden Listing 8.40 Beispiel $ms = t3lib_div::milliseconds(); /* Ergebnis in $ms: 1256537906427 */
8.2.23 modifyHTMLColor t3lib_div::modifyHTMLColor($color,$R,$G,$B)
Berechnet eine neue Farbe, indem den jeweiligen Farben die Offsets $R, $G und $B dazugerechnet werden. Der gültige Wertebereich liegt zwischen 0 und 255. Listing 8.41 Beispiel $newColor = t3lib_div::modifyHTMLColor('#000000', '155', '0', '255'); /* Ergebnis in $newColor: #9b00ff */
8.2.24 modifyHTMLColorAll t3lib_div::modifyHTMLColorAll($color,$all)
Der Farbe $color wird ein gleichmäßiges Offset dazugerechnet (Aufhellung). Die Werte des Offsets $all können zwischen 0 und 255 liegen.
179
8 Strings, Arrays und Umgebungsvariablen Listing 8.42 Beispiel $newColor = t3lib_div::modifyHTMLColorAll('#000000', '155'); /* Ergebnis in $newColor: #9b9b9b */
8.2.25 normalizeIPv6 t3lib_div::normalizeIPv6($address)
Normalisiert eine komprimierte Darstellung einer IPv6-Adresse $address. Listing 8.43 Beispiel $ipv6 = t3lib_div::normalizeIPv6('3ffe:400:280::1'); /* Ergebnis in $ipv6: 3ffe:0400:0280:0000:0000:0000:0000:0001 *&
8.2.26 removeXSS t3lib_div::removeXSS($string)
Entfernt eventuellen Cross-Site-Scripting-Code im Input-Wert $string. Listing 8.44 Beispiel $input = t3lib_div::removeXSS("
Mit dieser TCA-Definition wird nun Folgendes erreicht:
Blogs werden in der Tabelle tx_simpleblog_domain_model_blog gespeichert. Posts werden einerseits in der Tabelle tx_simpleblog_domain_model_post gespeichert und andererseits im Feld posts der Tabelle tx_simpleblog_domain_model_ blog referenziert. Hierbei werden dort die UIDs der Post-Beiträge als kommaseparierte Liste gespeichert. Dies wird über die foreign_*-Optionen des TCA erreicht.
Tags werden einerseits in der Tabelle
tx_simpleblog_domain_model_tag gespei-
chert und andererseits im Feld tags der Tabelle tx_simpleblog_domain_model_ posts referenziert. Hier wird allerdings – im Gegensatz zu den Posts im Blog – ledig-
lich die Anzahl der Tags in der Tabelle tx_simpleblog_domain_model_posts im
332
16.5 Anlegen eines Repositorys Feld tags abgespeichert. Die dazugehörigen Referenzen werden in die MM-Tabelle tx_simpleblog_post_tag_mm eingetragen. Das Handling für 1:N oder M:M-Relationen ist also prinzipiell komplett identisch – lediglich das TCA gibt vor, wie Extbase damit umgehen soll.
16.5 Anlegen eines Repositorys Vorhin haben wir ein Blog derart erzeugt, indem wir schlicht die Klasse instanziiert haben. Dies ist natürlich nicht praktikabel, da wir das so erzeugte Objekt schlecht speichern können und auch Extbase von dessen Existenz schlicht nichts weiß. Um nun ein Objekt vorschriftsmäßig zu erzeugen, werden wir gemäß der Paradigmen des Domain Driven Designs ein sogenanntes Repository verwenden. Dieses stellt die Schnittstelle von Domain und Infrastruktur dar und wird im Verzeichnis typo3conf/ext/simpleblog/Classes/Domain/Repository mit dem Namen EntityRepository.php erwartet. Hat man also ein Repository für die Entität Blog, so lautet die zugehörige Datei BlogRepository.php, und genau diese legen wir nun an. Listing 16.14 Die Datei BlogRepository.php
Nanu, werden Sie sich jetzt fragen – die Klasse ist ja komplett leer. Das hat tatsächlich seine Richtigkeit. Dadurch, dass die Klasse Tx_Extbase_Persistence_Repository abgeleitet wird, enthält das Repository bereits alle für den Anfang notwendigen Funktionalitäten. So kann beispielsweise ein Objekt (in unserem Fall ein Blog) zum Repository mittels add() hinzugefügt oder mittels remove() entfernt werden. Darüber hinaus stehen bereits per Default Methoden zum Finden alle Objekte (findAll()) oder über die magische Funktion findByEigenschaft() eine Funktion zur Verfügung, die nur diejenigen Objekte findet, deren Eigenschaft einen bestimmten Wert aufweist. So lässt sich beispielsweise nach dem Titel eines Objekts suchen, indem man findByTitle() verwendet.
Anpassen des Blog-Controllers Damit unser Repository auch benutzt wird, müssen wir es im Blog-Controller direkt ansprechen:
333
16 Entwicklung eines eigenen Plug-ins Listing 16.15 Änderung an der Datei BlogController.php
Wir haben den Controller nun um eine zusätzliche „magische“ Methode erweitert, und zwar initializeAction(). Diese Methode wird immer dann aufgerufen, wenn eine Action angefordert wird. Dabei wird kurz zuvor diese Methode angesprungen, und die dort enthaltenen Anweisungen werden noch kurz vor der eigentlichen Action ausgeführt. In diesem Fall wird das Blog-Repository initialisiert. Auf dieses kann später mittels $this>repository zugegriffen werden. Anschließend wird nun auch die Index-Action entsprechend angepasst, indem beispielhaft eine Schleife drei Blogs erzeugt. Der Titel der Blogs wird entsprechend gesetzt und mittels add() im Repository gespeichert. Schließlich werden über die dem Repository eigene Funktion findAll() alle Blogs gesucht und dem View zugeordnet. Zusätzlich müssen wir hier also auch den View entsprechend anpassen: Listing 16.16 Änderungen an der View-Datei index.html
Blog hinzufügen
Bitte geben Sie hier Ihre Änderungen ein: