TYPO3 Extension development using new Extbase framework

7,554 views

Published on

My presentation for the TYPO3 community day in Tokyo, Japan.

The code is available at https://github.com/ctrabold/t3ski-workshop.

Due to copyright issues I had to remove all pictures of Miffy.

Published in: Technology
3 Comments
5 Likes
Statistics
Notes
No Downloads
Views
Total views
7,554
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
58
Comments
3
Likes
5
Embeds 0
No embeds

No notes for slide

TYPO3 Extension development using new Extbase framework

  1. 1. TYPO3 Extensiondevelopment usingnew Extbaseframework2011/02/18, T3Ski11 TokyoChristian Trabold
  2. 2. Christian TraboldSenior Developerdkd Internet Service GmbHTYPO3 since 2004Focus on quality assuranceAuthor of TYPO3 Cookbook, OReillyAbout me
  3. 3. Carrier 12:34 PM Web Page Title http://host.domain.tld 320 x 480 Vertical Resolution
  4. 4. - TYPO3 basics- Find extensions with TER- Get your ideas into TYPO3- Question and answersAgenda - Part 1
  5. 5. - Create example application- See kickstarter in action- Customize les to your needs- Question and answersAgenda - Part 2
  6. 6. Goal of this workshop
  7. 7. Get the big picture
  8. 8. Understand concepts
  9. 9. Find nice Sushi bars
  10. 10. Carrier 12:34 PM Web Page Title http://host.domain.tld 320 x 480 Vertical Resolution
  11. 11. Part 1TYPO3 Basics
  12. 12. Frontend Backend Extensionshttp://www.flickr.com/photos/grendelkhan/121671781/sizes/l/in/photostream/ TYPO3 is like Sushi
  13. 13. Extensions extendeverything
  14. 14. Extensions containyour PHP code
  15. 15. Extensions containyour ideas
  16. 16. Inspiring people toshare
  17. 17. How to nd extensions
  18. 18. typo3.org/extensions/
  19. 19. List extensions
  20. 20. Extension details
  21. 21. View les
  22. 22. Extension manager
  23. 23. Extension details
  24. 24. Read documentation
  25. 25. Look into les
  26. 26. It is very importantthat you check everydetail of an extensionbefore you install.Security and con dence
  27. 27. What if nothing ts?
  28. 28. http://www.flickr.com/photos/rreid/420388478/ Add your own creation
  29. 29. How do you startyour own creation?
  30. 30. Understandextension structure
  31. 31. Installextbase kickstarter
  32. 32. Andstart coding!
  33. 33. Why do I need akickstarter?
  34. 34. Faster and less errors
  35. 35. The kickstarter doesall the boring work
  36. 36. You can focus on yourideas and design= more fun!
  37. 37. TYPO3 has old andnew extension styles Old pi_base New extbase
  38. 38. We will focus on thenew extbase kickstarter ✘ Old pi_base New extbase
  39. 39. Old = less structurehard to maintain !"" ChangeLog !"" doc #   !"" wizard_form.dat #   %"" wizard_form.html !"" ext_emconf.php !"" ext_icon.gif !"" ext_localconf.php !"" ext_tables.php !"" ext_tables.sql !"" flexform_tx_sushifinder_bars_flex.xml !"" icon_tx_sushifinder_bars.gif !"" locallang_db.xml !"" pi1 #   %"" class.tx_sushifinder_pi1.php !"" README.txt %"" tca.php
  40. 40. You tend to buildhuge classes !"" ChangeLog? !"" #   #   doc !"" wizard_form.dat %"" wizard_form.html !"" ext_emconf.php !"" ext_icon.gif !"" ext_localconf.php !"" ext_tables.php !"" ext_tables.sql !"" flexform_tx_sushifinder_bars_flex.xml !"" icon_tx_sushifinder_bars.gif !"" locallang_db.xml !"" pi1 #   %"" class.tx_sushifinder_pi1.php !"" README.txt %"" tca.php
  41. 41. <?php/*************************************************************** * Copyright notice * * (c) 1999-2004 Kasper SkÌ´rhÌüj (kasperYYYY@typo3.com) * (c) 2004-2009 Rupert Germann (rupi@gmx.li) * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is * free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * The GNU General Public License can be found at * http://www.gnu.org/copyleft/gpl.html. * A copy is found in the textfile GPL.txt and important notices to the license * from the author is found in LICENSE.txt distributed with these scripts. * * * This script is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************//** * class.tx_ttnews.php * * versatile news system for TYPO3. * $Id: class.tx_ttnews.php 27058 2009-11-27 12:24:02Z rupi $ * * TypoScript setup: * @See ext/tt_news/pi/static/ts_new/setup.txt * @See tt_news Manual: http://typo3.org/documentation/document-library/extension-manuals/tt_news/current/ * @See TSref: http://typo3.org/documentation/document-library/references/doc_core_tsref/current/ * * @author Rupert Germann <rupi@gmx.li> * @co-author Ingo Renner <typo3@ingo-renner.com> */require_once (PATH_tslib . class.tslib_pibase.php);require_once (PATH_t3lib . class.t3lib_htmlmail.php);require_once (t3lib_extMgm::extPath(tt_news) . lib/class.tx_ttnews_catmenu.php);require_once (t3lib_extMgm::extPath(tt_news) . lib/class.tx_ttnews_helpers.php);require_once (t3lib_extMgm::extPath(tt_news) . lib/class.tx_ttnews_cache.php);
  42. 42. * * @author Rupert Germann <rupi@gmx.li> * @package TYPO3 * @subpackage tt_news */class tx_ttnews extends tslib_pibase { // Default plugin variables: var $prefixId = tx_ttnews; // Same as class name var $scriptRelPath = pi/class.tx_ttnews.php; // Path to this script relative to the extension dir. var $extKey = tt_news; // The extension key. var $hObj; // class with helper functions var $tt_news_uid = 0; // the uid of the current news record in SINGLE view var $pid_list = 0; var $config = array(); // the processed TypoScript configuration array var $confArr; // extension config from extmanager var $genericMarkerConf; var $sViewSplitLConf = array(); var $langArr = array(); // the languages found in the tt_news sysfolder var $sys_language_mode = ; var $alternatingLayouts = 0; var $allowCaching = 1; var $catExclusive = ; var $actuallySelectedCategories = ; var $arcExclusive = 0; var $fieldNames = array(); var $searchFieldList = short,bodytext,author,keywords,links,imagecaption,title; var $theCode = ; // the current code var $codes; // list of all codes var $rdfToc = ; var $templateCode = ; var $versioningEnabled = false; // is the extension version loaded var $vPrev = false; // do we display a versioning preview var $categories = array(); var $pageArray = array(); // internal cache with an array of the pages in the pid-list var $pointerName = pointer; var $SIM_ACCESS_TIME = 0; // var $renderFields = array(); var $errors = array(); var $enableFields = ; var $enableCatFields = ; var $SPaddWhere = ; var $catlistWhere = ; var $token = ; var $debugTimes = FALSE; // debug parsetimes var $useDevlog = TRUE; // write parsetimes to devlog instead printing debug messages
  43. 43. var $parsetimeThreshold = 0.1; // log only functions which need more than x.xx seconds var $writeCachingInfoToDevlog = FALSE; // 1 = write only cache misses to devlog, 2 = write cache hit info, too var $start_time = NULL; var $global_start_time = 0; var $start_code_line = 0; var $cache; var $cache_amenuPeriods = FALSE; var $cache_categoryCount = FALSE; var $cache_categories = FALSE; /** * Main news function: calls the init_news() function and decides by the given CODEs which of the * functions to display news should by called. * * @param string $content : function output is added to this * @param array $conf : configuration array * @return string $content: complete content generated by the tt_news plugin */ function main_news($content, $conf) { $this->confArr = unserialize($GLOBALS[TYPO3_CONF_VARS][EXT][extConf][tt_news]); if ($this->confArr[writeParseTimesToDevlog]) { $this->debugTimes = TRUE; } if ($this->confArr[parsetimeThreshold]) { $this->parsetimeThreshold = floatval(trim($this->confArr[parsetimeThreshold])); } $this->hObj = new tx_ttnews_helpers($this); if ($this->debugTimes) { $this->hObj->getParsetime(__METHOD__); } $this->conf = $conf; //store configuration // leave early if USER_INT $this->convertToUserIntObject = $this->conf[convertToUserIntObject] ? 1 : 0; if (t3lib_div::int_from_ver(TYPO3_version) >= 4003000 && $this->convertToUserIntObject && $this->cObj->getUserObjectType() == tslib_cObj::OBJECTTYPE_USER) { $this->cObj->convertToUserIntObject(); return; } $this->preInit(); if ($this->conf[enableConfigValidation]) {
  44. 44. if (count($this->errors)) { return $this->hObj->displayErrors(); } } $this->init(); foreach ($this->codes as $theCode) { $theCode = (string) strtoupper(trim($theCode)); $this->theCode = $theCode; // initialize category vars $this->initCategoryVars(); $this->initGenericMarkers(); switch ($theCode) { case SINGLE : case SINGLE2 : $content .= $this->displaySingle(); break; case VERSION_PREVIEW : $content .= $this->displayVersionPreview(); break; case LATEST : case LIST : case LIST2 : case LIST3 : case HEADER_LIST : case SEARCH : case XML : $content .= $this->displayList(); break; case AMENU : $content .= $this->displayArchiveMenu(); break; case CATMENU : $content .= $this->displayCatMenu(); break; default : if ($this->debugTimes) { $this->hObj->getParsetime(__METHOD__ . extraCodesHook start); } // hook for processing of extra codes if (is_array($GLOBALS[TYPO3_CONF_VARS][EXTCONF][tt_news][extraCodesHook])) { foreach ($GLOBALS[TYPO3_CONF_VARS][EXTCONF][tt_news][extraCodesHook] as $_classRef) { $_procObj = & t3lib_div::getUserObj($_classRef); $content .= $_procObj->extraCodesProcessor($this); } } else { // code not known and no hook found to handle it -> displayerror $this->errors[] = CODE " . $theCode . " not known;
  45. 45. if ($this->debugTimes) { $this->hObj->getParsetime(__METHOD__ . extraCodesHook end); } break; } } // check errors array again if ($this->conf[enableConfigValidation]) { if (count($this->errors)) { return $this->hObj->displayErrors(); } } if ($this->debugTimes) { $this->hObj->getParsetime(__FUNCTION__, true); } return $this->cObj->stdWrap($content, $this->conf[stdWrap.]); } /** * [Describe function...] * * @return [type] ... */ function preInit() { $this->pi_initPIflexForm(); // Init FlexForm configuration for plugin $flexformTyposcript = $this->pi_getFFvalue($this->cObj->data[pi_flexform], myTS,s_misc); if ($flexformTyposcript) { require_once(PATH_t3lib.class.t3lib_tsparser.php); $tsparser = t3lib_div::makeInstance(t3lib_tsparser); // Copy conf into existing setup $tsparser->setup = $this->conf; // Parse the new Typoscript $tsparser->parse($flexformTyposcript); // Copy the resulting setup back into conf $this->conf = $tsparser->setup; } // "CODE" decides what is rendered: codes can be set by TS or FF with priority on FF $code = $this->pi_getFFvalue($this->cObj->data[pi_flexform], what_to_display, sDEF); $this->config[code] = ($code ? $code : $this->cObj->stdWrap($this->conf[code], $this->conf[code.])); if ($this->conf[displayCurrentRecord]) { $this->config[code] = $this->conf[defaultCode] ? trim($this->conf[defaultCode]) : SINGLE; $this->tt_news_uid = $this->cObj->data[uid];
  46. 46. } // get codes and decide which function is used to process the content $codes = t3lib_div::trimExplode(,, $this->config[code] ? $this->config[code] : $this->conf[defaultCode], 1); if (! count($codes)) { // no code at all $codes = array(); $this->errors[] = No code given; } $this->codes = $codes; } /** * Init Function: here all the needed configuration values are stored in class variables.. * * @param array $conf : configuration array from TS * @return void */ function init() { $this->pi_loadLL(); // Loading language-labels $this->pi_setPiVarDefaults(); // Set default piVars from TS $this->SIM_ACCESS_TIME = $GLOBALS[SIM_ACCESS_TIME]; // fallback for TYPO3 < 4.2 if (! $this->SIM_ACCESS_TIME) { $simTime = $GLOBALS[SIM_EXEC_TIME]; $this->SIM_ACCESS_TIME = $simTime - ($simTime % 60); } $this->initCaching(); $this->local_cObj = t3lib_div::makeInstance(tslib_cObj); // Local cObj. $this->enableFields = $this->getEnableFields(tt_news); if ($this->tt_news_uid === 0) { // no tt_news_uid set by displayCurrentRecord $this->tt_news_uid = intval($this->piVars[tt_news]); // Get the submitted uid of a news (if any) } if (! isset($this->conf[compatVersion]) || ! preg_match(/^d+.d+.d+$/, $this->conf[compatVersion])) { $this->conf[compatVersion] = $this->hObj->getCurrentVersion(); } $this->token = md5(microtime()); if (t3lib_extMgm::isLoaded(version)) { $this->versioningEnabled = true; } // load available syslanguages $this->initLanguages(); // sys_language_mode defines what to do if the requested translation is not found
  47. 47. $this->sys_language_mode = ($this->conf[sys_language_mode] ? $this->conf[sys_language_mode] : $GLOBALS[TSFE]->sys_language_mode); if ($this->conf[searchFieldList]) { // get fieldnames from the tt_news db-table $this->fieldNames = array_keys($GLOBALS[TYPO3_DB]->admin_get_fields(tt_news)); $searchFieldList = $this->hObj->validateFields($this->conf[searchFieldList], $this->fieldNames); if ($searchFieldList) { $this->searchFieldList = $searchFieldList; } } // Archive: $archiveMode = trim($this->conf[archiveMode]); // month, quarter or year listing in AMENU $this->config[archiveMode] = $archiveMode ? $archiveMode : month; // arcExclusive : -1=only non-archived; 0=dont care; 1=only archived $arcExclusive = $this->pi_getFFvalue($this->cObj->data[pi_flexform], archive, sDEF); $this->arcExclusive = $arcExclusive ? $arcExclusive : intval($this->conf[archive]); $this->config[datetimeDaysToArchive] = intval($this->conf[datetimeDaysToArchive]); $this->config[datetimeHoursToArchive] = intval($this->conf[datetimeHoursToArchive]); $this->config[datetimeMinutesToArchive] = intval($this->conf[datetimeMinutesToArchive]); if ($this->conf[useHRDates]) { $this->hObj->convertDates(); } // list of pages where news records will be taken from if (! $this->conf[dontUsePidList]) { $this->initPidList(); } // itemLinkTarget is only used for categoryLinkMode 3 (catselector) in framesets $this->conf[itemLinkTarget] = trim($this->conf[itemLinkTarget]); // id of the page where the search results should be displayed $this->config[searchPid] = intval($this->conf[searchPid]); // pages in Single view will be divided by this token $this->config[pageBreakToken] = trim($this->conf[pageBreakToken]) ? trim($this->conf[pageBreakToken]) : <---newpage--->; $this->config[singleViewPointerName] = trim($this->conf[singleViewPointerName]) ? trim($this->conf[singleViewPointerName]) : sViewPointer $maxWordsInSingleView = intval($this->pi_getFFvalue($this->cObj->data[pi_flexform], maxWordsInSingleView, s_misc)); $maxWordsInSingleView = $maxWordsInSingleView ? $maxWordsInSingleView : intval($this->conf[maxWordsInSingleView]); $this->config[maxWordsInSingleView] = $maxWordsInSingleView ? $maxWordsInSingleView : 0; $this->config[useMultiPageSingleView] = $this->conf[useMultiPageSingleView]; // pid of the page with the single view. the old var PIDitemDisplay is still processed if no other value is found $singlePid = $this->pi_getFFvalue($this->cObj->data[pi_flexform], PIDitemDisplay, s_misc);
  48. 48. Does this tell youanything about theapplication?
  49. 49. Maybe #wtf!
  50. 50. New = more structureeasy to maintain !"" Classes #   !"" Controller #   %"" Domain !"" Configuration #   !"" TCA #   %"" TypoScript !"" ext_emconf.php !"" ext_icon.gif !"" ext_localconf.php !"" ext_tables.php !"" ext_tables.sql !"" kickstarter.json %"" Resources !"" Private %"" Public
  51. 51. Because it forces you tothink in components ! !"" #   #   Classes !"" Controller %"" Domain !"" Configuration #   !"" TCA #   %"" TypoScript !"" ext_emconf.php !"" ext_icon.gif !"" ext_localconf.php !"" ext_tables.php !"" ext_tables.sql !"" kickstarter.json %"" Resources !"" Private %"" Public
  52. 52. How do I getstarted?
  53. 53. Download extbasekickstartercd ./typo3conf/ext/git clone git://git.typo3.org/TYPO3v4/Extensions/extbase_kickstarter.git(one line)
  54. 54. Download extbasekickstartercd ./typo3conf/ext/git clonegit://git.typo3.org/TYPO3v4/Extensions/extbase_kickstarter.git(all in one line)
  55. 55. Why git?Fast, comfortable version control systemSmooth development even with large filesGraphical interfaces availablehttp://git-scm.com/toolsDownload ithttp://git-scm.com/download
  56. 56. Use extbasekickstarter Demo
  57. 57. We created le withour new Domain Class . !"" Classes #   !"" Controller #   %"" Domain #   %"" Model #      %"" Bar.php !"" Configuration #   !"" TCA #   %"" TypoScript !"" ext_emconf.php !"" ext_icon.gif !"" ext_localconf.php !"" ext_tables.php !"" ext_tables.sql !"" kickstarter.json %"" Resources
  58. 58. + Backend forms
  59. 59. You can instantly createnew content for ourwebsite!
  60. 60. "BREAK"
  61. 61. Part 2Example
  62. 62. - Create a web application to manage sushi bars- Click on a bar to get details- Find bar on Google MapsGoal: Find Sushi Bars
  63. 63. Sushi Bar- Name- Location- Business hours- ImagesOur Bar model
  64. 64. Sushi Bar ReviewAdd Relations
  65. 65. - Allow Feedback- Rating- StatementReview model
  66. 66. - Link Website- Add QRCode to open a map- Easy to ndImprove view
  67. 67. Final result
  68. 68. Many happy customers!
  69. 69. http://forge.typo3.org/projects/typo3v4-mvchttp://wiki.typo3.org/Category:Topic/extbaseFurther reading
  70. 70. Thank you!
  71. 71. Have fun with TYPO3!

×