extbase and beyond

97
Extbase and Beyond Jochen Rau <[email protected]> Irving, Texas May 22, 2010

Upload: jochen-rau

Post on 08-May-2015

12.023 views

Category:

Technology


0 download

DESCRIPTION

With Extbase - a new framework for extension development introduced in TYPO3 4.3 - you are able to develop with the paradigms of FLOW3 today. During this talk, you get in touch with the features of the framework to understand how it supports your development process to develop clean code cost efficient in less time. Extbase is one cornerstone for a smooth transition to TYPO3 v5, another is reusable business domain knowledge in form of Generic Domain Models available in 4.x and 5.x. The Generic Domain Models will enable you to add a Semantic Web topping.

TRANSCRIPT

Page 1: Extbase and Beyond

Extbase and Beyond

Jochen Rau <[email protected]>Irving, TexasMay 22, 2010

Page 2: Extbase and Beyond

Who is this?

Page 3: Extbase and Beyond

Dipl.-Ing. Mechanical Engineering

Page 4: Extbase and Beyond

infected with TYPO3 in 2OO1

Page 5: Extbase and Beyond

Tübingen

Page 6: Extbase and Beyond
Page 7: Extbase and Beyond

6O% selfemployed6O% father

Page 8: Extbase and Beyond

6O% selfemployed6O% father

----8O%

Page 9: Extbase and Beyond

5 years: Fraunhofer-Gesellschaft

German Aerospace Center

Page 10: Extbase and Beyond

5 years:high school

teacher

Page 11: Extbase and Beyond

What is Extbase all about?

Page 12: Extbase and Beyond

v4

2OO6

Page 13: Extbase and Beyond

v4

v5

Page 14: Extbase and Beyond

v4

v5

Page 15: Extbase and Beyond

v4

v5

Page 16: Extbase and Beyond

v4

v5Extbase

Page 17: Extbase and Beyond

v4

v5

Page 18: Extbase and Beyond

ExtbaseFLO 4W

Page 19: Extbase and Beyond

ExtbaseFLO 4W6O%

Page 20: Extbase and Beyond

ExtbaseFLO 4

25%WW

Page 21: Extbase and Beyond

ExtbaseFLO 4

25%W

Page 22: Extbase and Beyond

ExtbaseFLO 4

2O%W

Page 23: Extbase and Beyond

ExtbaseFLO 4W

Page 24: Extbase and Beyond

ExtbaseFLOW 3

Page 25: Extbase and Beyond

What is Extbase all about?

Page 26: Extbase and Beyond

Extbase

Page 27: Extbase and Beyond

ExtbaseMVC

DDD

VfB

OOP Aggregate

Entity

Repository

View

Helper

Page 28: Extbase and Beyond

Extbase

Entity

View Helper

Value

Page 29: Extbase and Beyond

clean architecturedomain driven

modularpatterns

Page 30: Extbase and Beyond

rapid developmentuse conventions

stay focusedbe relieved

Page 31: Extbase and Beyond

smooth transition

youcodedata

Page 32: Extbase and Beyond

What is Extbase all about?

Page 34: Extbase and Beyond

http://commons.wikimedia.org/wiki/File:Z%C3%BCrich_-_Seefeld_-_Heureka_IMG_1757.JPG

tx_ttnews 3397tx_pbsurvey_pi1 253Otx_ttproducts_pi1 1O9Otx_mmforum_pi1 6126tx_veguestbook_pi1 1156

Page 35: Extbase and Beyond

<?php/**************************************************************** Copyright notice** (c) 1999-2004 Kasper SkÃ¥rhøj ([email protected])* (c) 2004-2007 Rupert Germann ([email protected])* 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 8605 2008-03-15 20:03:19Z rupertgermann $** TypoScript setup:* @See 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 <[email protected]>* @co-author Ingo Renner <[email protected]>*//** * [CLASS/FUNCTION INDEX of SCRIPT] * * * * 112: class tx_ttnews extends tslib_pibase * 143: function main_news($content, $conf) * 219: function init($conf) * 373: function newsArchiveMenu() * 523: function displaySingle() * 606: function displayVersionPreview () * 659: function displayList($excludeUids = 0) * 1003: function getListContent($itemparts, $selectConf, $prefix_display) * 1172: function getSelectConf($where, $noPeriod = 0) * 1419: function generatePageArray() * 1440: function getItemMarkerArray ($row, $textRenderObj = 'displaySingle') * 1723: function insertPagebreaks($text,$firstPageWordCrop) * 1773: function makeMultiPageSView($bodytext,$lConf) * 1803: function makePageBrowser($showResultCount=1,$tableParams='',$pointerName='pointer') * 1885: function getCategories($uid, $getAll=false) * 1958: function getCategoryPath($categoryArray) * 2015: function getSubCategories($catlist, $cc = 0) * 2044: function displayCatMenu() * 2157: function getCatMenuContent($array_in,$lConf, $l=0) * 2209: function getSubCategoriesForMenu ($catlist, $fields, $addWhere, $cc = 0) * 2240: function getCatMarkerArray($markerArray, $row, $lConf) * 2380: function getImageMarkers($markerArray, $row, $lConf, $textRenderObj) * 2448: function getRelated($uid) * 2608: function userProcess($mConfKey, $passVar) * 2623: function spMarker($subpartMarker) * 2641: function searchWhere($sw) * 2652: function formatStr($str) * 2667: function getLayouts($templateCode, $alternatingLayouts, $marker) * 2685: function initLanguages () * 2705: function initCategoryVars() * 2775: function checkRecords($recordlist) * 2807: function initTemplate() * 2832: function initPidList () * 2857: function getXmlHeader() * 2958: function getW3cDate($datetime) * 2983: function main_xmlnewsfeed($content, $conf) * 2998: function getStoriesResult() * 3020: function cleanXML($str) * 3034: function convertDates() * 3073: function getHrDateSingle($tstamp) * 3086: function displayFEHelp() * 3107: function validateFields($fieldlist) * 3128: function getNewsSubpart($myTemplate, $myKey, $row = Array()) * * SECTION: DB Functions * 3149: function exec_getQuery($table, $conf) * 3167: function getQuery($table, $conf, $returnQueryArray=FALSE) * 3249: function getWhere($table,$conf, $returnQueryArray=FALSE) * * TOTAL FUNCTIONS: 45 * (This index is automatically created/updated by the extension "extdeveval") * */

require_once(PATH_t3lib . 'class.t3lib_xml.php');require_once(PATH_t3lib . 'class.t3lib_htmlmail.php');require_once(PATH_tslib . 'class.tslib_pibase.php');require_once(t3lib_extMgm::extPath('tt_news') . 'class.tx_ttnews_catmenu.php');

/** * Plugin 'news' for the 'tt_news' extension. * * @author Rupert Germann <[email protected]> * @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 $tt_news_uid; // the uid of the current news record in SINGLE view var $config; // the processed TypoScript configuration array var $langArr; // the languages found in the tt_news sysfolder var $sys_language_mode; var $alternatingLayouts; var $allowCaching; var $catExclusive; var $arcExclusive; var $searchFieldList = 'short,bodytext,author,keywords,links,imagecaption,title'; var $theCode = ''; var $rdfToc = ''; var $versioningEnabled = false; // is the extension 'version' loaded var $vPrev = false; // do we display a versioning preview var $categories = array(); // Is initialized with the categories of the news system var $pageArray = array(); // Is initialized with an array of the pages in the pid-list

/** * 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 * @returnstring $content: complete content generated by the tt_news plugin */ function main_news($content, $conf) { $this->local_cObj = t3lib_div::makeInstance('tslib_cObj'); // Local cObj. $this->init($conf);

if ($this->conf['displayCurrentRecord']) { $this->config['code'] = $this->conf['defaultCode']?trim($this->conf['defaultCode']):'SINGLE'; $this->tt_news_uid = $this->cObj->data['uid']; }

// 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(); $noCode = true; }

while (list(, $theCode) = each($codes)) { $theCode = (string)strtoupper(trim($theCode)); $this->theCode = $theCode; switch ($theCode) { case 'SINGLE': $content .= $this->displaySingle(); break; case 'VERSION_PREVIEW': $content .= $this->displayVersionPreview(); break; case 'LATEST': case 'LIST': case 'SEARCH': case 'XML': $content .= $this->displayList(); break; case 'AMENU': $content .= $this->newsArchiveMenu(); break; case 'CATMENU': $content .= $this->displayCatMenu(); break; default: // Adds 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 { $langKey = strtoupper($GLOBALS['TSFE']->config['config']['language']); $helpTemplate = $this->cObj->fileResource('EXT:tt_news/pi/news_help.tmpl'); // Get language version of the help-template $helpTemplate_lang = ''; if ($langKey) { $helpTemplate_lang = $this->getNewsSubpart($helpTemplate, "###TEMPLATE_" . $langKey . '###'); } $helpTemplate = $helpTemplate_lang ? $helpTemplate_lang : $this->getNewsSubpart($helpTemplate, '###TEMPLATE_DEFAULT###'); // Markers and substitution: $markerArray['###CODE###'] = $this->theCode; $markerArray['###EXTPATH###'] = $GLOBALS['TYPO3_LOADED_EXT']['tt_news']['siteRelPath']; $content .= $this->displayFEHelp(); } break; } } if($noCode) { $content .= $this->displayFEHelp(); } return $content; }

/** * Init Function: here all the needed configuration values are stored in class variables.. * * @param array $conf : configuration array from TS * @returnvoid */ function init($conf) { $this->conf = $conf; //store configuration $this->pi_loadLL(); // Loading language-labels $this->pi_setPiVarDefaults(); // Set default piVars from TS $this->pi_initPIflexForm(); // Init FlexForm configuration for plugin $this->enableFields = $this->cObj->enableFields('tt_news'); $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->getCurrentVersion(); }

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 $this->sys_language_mode = $this->conf['sys_language_mode']?$this->conf['sys_language_mode'] : $GLOBALS['TSFE']->sys_language_mode;

// "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.']);

// initialize category vars $this->initCategoryVars();

// get fieldnames from the tt_news db-table $this->fieldNames = array_keys($GLOBALS['TYPO3_DB']->admin_get_fields('tt_news'));

if ($this->conf['searchFieldList']) { $searchFieldList = $this->validateFields($this->conf['searchFieldList']); if ($searchFieldList) { $this->searchFieldList = $searchFieldList; } } // Archive: $this->config['archiveMode'] = trim($this->conf['archiveMode']) ; // month, quarter or year listing in AMENU $this->config['archiveMode'] = $this->config['archiveMode']?$this->config['archiveMode']:'month';

// arcExclusive : -1=only non-archived; 0=don't care; 1=only archived $arcExclusive = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'archive', 'sDEF'); $this->arcExclusive = $arcExclusive?$arcExclusive:$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->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->config['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'] = $maxWordsInSingleView>1?1:$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'); $singlePid = $singlePid?$singlePid:intval($this->cObj->stdWrap($this->conf['singlePid'],$this->conf['singlePid.'])); $this->config['singlePid'] = $singlePid ? $singlePid:intval($this->conf['PIDitemDisplay']);

// pid to return to when leaving single view $backPid = intval($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'backPid', 's_misc')); $backPid = $backPid?$backPid:intval($this->conf['backPid']); $backPid = $backPid?$backPid:intval($this->piVars['backPid']); $backPid = $backPid?$backPid:$GLOBALS['TSFE']->id ; $this->config['backPid'] = $backPid;

// max items per page $FFlimit = t3lib_div::intInRange($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'listLimit', 's_misc'), 0, 1000);

$limit = t3lib_div::intInRange($this->cObj->stdWrap($this->conf['limit'],$this->conf['limit.']), 0, 1000); $limit = $limit?$limit: 50; $this->config['limit'] = $FFlimit?$FFlimit:$limit;

$latestLimit = t3lib_div::intInRange($this->cObj->stdWrap($this->conf['latestLimit'],$this->conf['latestLimit.']), 0, 1000); $latestLimit = $latestLimit?$latestLimit:10; $this->config['latestLimit'] = $FFlimit?$FFlimit:$latestLimit;

// orderBy and groupBy statements for the list Query $orderBy = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'listOrderBy', 'sDEF'); $orderByTS = trim($this->conf['listOrderBy']); $orderBy = $orderBy?$orderBy:$orderByTS; $this->config['orderBy'] = $orderBy;

if ($orderBy) { $ascDesc = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'ascDesc', 'sDEF'); $this->config['ascDesc'] = $ascDesc; if ($this->config['ascDesc']) { // remove ASC/DESC from 'orderBy' if it is already set from TS $this->config['orderBy'] = preg_replace('/( DESC| ASC)\b/i','',$this->config['orderBy']); } } $this->config['groupBy'] = trim($this->conf['listGroupBy']);

// if this is set, the first image is handled as preview image, which is only shown in list view $fImgPreview = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'firstImageIsPreview', 's_misc'); $this->config['firstImageIsPreview'] = $fImgPreview?$fImgPreview : $this->conf['firstImageIsPreview']; $forcefImgPreview = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'forceFirstImageIsPreview', 's_misc'); $this->config['forceFirstImageIsPreview'] = $forcefImgPreview?$fImgPreview : $this->conf['forceFirstImageIsPreview'];

// List start id $listStartId = intval($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'listStartId', 's_misc')); $this->config['listStartId'] = $listStartId?$listStartId:intval($this->conf['listStartId']); // supress pagebrowser $noPageBrowser = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'noPageBrowser', 's_misc'); $this->config['noPageBrowser'] = $noPageBrowser?$noPageBrowser: $this->conf['noPageBrowser'];

// image sizes given from FlexForms $this->config['FFimgH'] = intval($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'imageMaxHeight', 's_template')); $this->config['FFimgW'] = intval($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'imageMaxWidth', 's_template'));

// Get number of alternative Layouts (loop layout in LATEST and LIST view) default is 2: $altLayouts = intval($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'alternatingLayouts', 's_template')); $altLayouts = $altLayouts?$altLayouts:intval($this->conf['alternatingLayouts']); $this->alternatingLayouts = $altLayouts?$altLayouts:2;

// Get cropping lenght $this->config['croppingLenght'] = trim($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'croppingLenght', 's_template'));

$this->initTemplate();

// Configure caching $this->allowCaching = $this->conf['allowCaching']?1:0; if (!$this->allowCaching) { $GLOBALS['TSFE']->set_no_cache(); }

// get siteUrl for links in rss feeds. the 'dontInsert' option seems to be needed in some configurations depending on the baseUrl setting if (!$this->conf['displayXML.']['dontInsertSiteUrl']) { $this->config['siteUrl'] = t3lib_div::getIndpEnv('TYPO3_SITE_URL'); } }

/** * generates the News archive menu * * @returnstring html code of the archive menu */ function newsArchiveMenu() {

$this->arcExclusive = 1; $selectConf = $this->getSelectConf('', 1); // Finding maximum and minimum values: $selectConf['selectFields'] = 'max(tt_news.datetime) as maxval, min(tt_news.datetime) as minval';

$res = $this->exec_getQuery('tt_news', $selectConf);

$row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res); if ($row['minval'] || $row['maxval']) { // if ($row['minval']) { $dateArr = array(); $arcMode = $this->config['archiveMode']; $c = 0; do { switch ($arcMode) { case 'month': $theDate = mktime (0, 0, 0, date('m', $row['minval']) + $c, 1, date('Y', $row['minval'])); break; case 'quarter': $theDate = mktime (0, 0, 0, floor(date('m', $row['minval']) / 3) + 1 + (3 * $c), 1, date('Y', $row['minval'])); break; case 'year': $theDate = mktime (0, 0, 0, 1, 1, date('Y', $row['minval']) + $c); break; } $dateArr[] = $theDate; $c++; if ($c > 1000) break; } while ($theDate < $GLOBALS['SIM_EXEC_TIME']);

reset($dateArr); $periodAccum = array();

$selectConf2['where'] = $selectConf['where']; while (list($k, $v) = each($dateArr)) { if (!isset($dateArr[$k + 1])) { break; }

$periodInfo = array(); $periodInfo['start'] = $dateArr[$k]; $periodInfo['stop'] = $dateArr[$k + 1]-1; $periodInfo['HRstart'] = date('d-m-Y', $periodInfo['start']); $periodInfo['HRstop'] = date('d-m-Y', $periodInfo['stop']); $periodInfo['quarter'] = floor(date('m', $dateArr[$k]) / 3) + 1; // execute a query to count the archive periods $selectConf['selectFields'] = 'count(distinct(tt_news.uid))'; $selectConf['where'] = $selectConf2['where'] . ' AND tt_news.datetime>=' . $periodInfo['start'] . ' AND tt_news.datetime<' . $periodInfo['stop'];

$res = $this->exec_getQuery('tt_news', $selectConf);

$row = $GLOBALS['TYPO3_DB']->sql_fetch_row($res); $periodInfo['count'] = $row[0];

if (!$this->conf['archiveMenuNoEmpty'] || $periodInfo['count']) { $periodAccum[] = $periodInfo; } }

// get template subpart $t['total'] = $this->getNewsSubpart($this->templateCode, $this->spMarker('###TEMPLATE_ARCHIVE###')); $t['item'] = $this->getLayouts($t['total'], $this->alternatingLayouts, 'MENUITEM'); $cc = 0;

$veryLocal_cObj = t3lib_div::makeInstance('tslib_cObj'); // reverse amenu order if 'reverseAMenu' is given if ($this->conf['reverseAMenu']) { arsort($periodAccum); }

$archiveLink = $this->conf['archiveTypoLink.']['parameter']; $this->conf['parent.']['addParams'] = $this->conf['archiveTypoLink.']['addParams']; reset($periodAccum); $itemsOutArr = array(); while (list(, $pArr) = each($periodAccum)) { // Print Item Title $wrappedSubpartArray = array();

if (!$this->conf['disableCategoriesInAmenuLinks']) { if ($this->config['catSelection'] && $this->config['amenuWithCatSelector']) { // use the catSelection from GPvars only if 'amenuWithCatSelector' is given. $amenuLinkCat = $this->config['catSelection']; } else { $amenuLinkCat = $this->catExclusive; } }

if ($this->conf['useHRDates']) { $year = date('Y',$pArr['start']); $month = date('m',$pArr['start']); if ($arcMode == 'year') { $archLinkArr = $this->pi_linkTP_keepPIvars('|', array('cat' => ($amenuLinkCat?$amenuLinkCat:null), 'year' => $year), $this->allowCaching, 1, ($archiveLink?$archiveLink:$GLOBALS['TSFE']->id)); } else { $archLinkArr = $this->pi_linkTP_keepPIvars('|', array('cat' => ($amenuLinkCat?$amenuLinkCat:null), 'year' => $year, 'month' => $month), $this->allowCaching, 1, ($archiveLink?$archiveLink:$GLOBALS['TSFE']->id)); } $wrappedSubpartArray['###LINK_ITEM###'] = explode('|', $archLinkArr); } else { $wrappedSubpartArray['###LINK_ITEM###'] = explode('|', $this->pi_linkTP_keepPIvars('|', array('cat' => ($amenuLinkCat?$amenuLinkCat:null), 'pS' => $pArr['start'], 'pL' => ($pArr['stop'] - $pArr['start']), 'arc' => 1), $this->allowCaching, 1, ($archiveLink?$archiveLink:$GLOBALS['TSFE']->id))); }

$markerArray = array(); $veryLocal_cObj->start($pArr, ''); $markerArray['###ARCHIVE_TITLE###'] = $veryLocal_cObj->cObjGetSingle($this->conf['archiveTitleCObject'], $this->conf['archiveTitleCObject.'], 'archiveTitle'); $markerArray['###ARCHIVE_COUNT###'] = $pArr['count']; $markerArray['###ARCHIVE_ITEMS###'] = $this->pi_getLL('archiveItems');

// fill the generated data to an array to pass it to a userfuction as a single variable $itemsOutArr[] = array('html' => $this->cObj->substituteMarkerArrayCached($t['item'][($cc % count($t['item']))], $markerArray, array(), $wrappedSubpartArray), 'data' => $pArr); $cc++; } // Pass to user defined function if ($this->conf['newsAmenuUserFunc']) { $itemsOutArr = $this->userProcess('newsAmenuUserFunc', $itemsOutArr); }

foreach ($itemsOutArr as $itemHtml) { $tmpItemsArr[] = $itemHtml['html']; }

if (is_array($tmpItemsArr)) { $itemsOut = implode('', $tmpItemsArr); }

// Reset: $subpartArray = array(); $wrappedSubpartArray = array(); $markerArray = array(); $markerArray['###ARCHIVE_HEADER###'] = $this->local_cObj->stdWrap($this->pi_getLL('archiveHeader'), $this->conf['archiveHeader_stdWrap.']); // Set content $subpartArray['###CONTENT###'] = $itemsOut; $content = $this->cObj->substituteMarkerArrayCached($t['total'], $markerArray, $subpartArray, $wrappedSubpartArray); } else { // if nothing is found in the archive display the TEMPLATE_ARCHIVE_NOITEMS message $markerArray['###ARCHIVE_HEADER###'] = $this->local_cObj->stdWrap($this->pi_getLL('archiveHeader'), $this->conf['archiveHeader_stdWrap.']); $markerArray['###ARCHIVE_EMPTY_MSG###'] = $this->local_cObj->stdWrap($this->pi_getLL('archiveEmptyMsg'), $this->conf['archiveEmptyMsg_stdWrap.']); $noItemsMsg = $this->getNewsSubpart($this->templateCode, $this->spMarker('###TEMPLATE_ARCHIVE_NOITEMS###')); $content = $this->cObj->substituteMarkerArrayCached($noItemsMsg, $markerArray); }

return $content; }

/** * Displays the "single view" of a news article. Is also used when displaying single news records with the "insert records" content element. * * @returnstring html-code for the "single view" */ function displaySingle() { $singleWhere = 'tt_news.uid=' . intval($this->tt_news_uid); $singleWhere .= ' AND type NOT IN(1,2)' . $this->enableFields; // only real news -> type=0

$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery( '*', 'tt_news', $singleWhere);

$row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res); // get the translated record if the content language is not the default language if ($GLOBALS['TSFE']->sys_language_content) { $OLmode = ($this->sys_language_mode == 'strict'?'hideNonTranslated':''); $row = $GLOBALS['TSFE']->sys_page->getRecordOverlay('tt_news', $row, $GLOBALS['TSFE']->sys_language_content, $OLmode); } if ($this->versioningEnabled) { // get workspaces Overlay $GLOBALS['TSFE']->sys_page->versionOL('tt_news',$row); // fix pid for record from workspace $GLOBALS['TSFE']->sys_page->fixVersioningPid('tt_news',$row); } $GLOBALS['TSFE']->displayedNews[]=$row['uid'];

if (is_array($row) && ($row['pid'] > 0 || $this->vPrev)) { // never display versions of a news record (having pid=-1) for normal website users // Get the subpart code if ($this->conf['displayCurrentRecord']) { $item = trim($this->getNewsSubpart($this->templateCode, $this->spMarker('###TEMPLATE_SINGLE_RECORDINSERT###'), $row)); } if (!$item) { $item = $this->getNewsSubpart($this->templateCode, $this->spMarker('###TEMPLATE_SINGLE###'), $row); } // reset marker array $wrappedSubpartArray = array(); // build the backToList link if ($this->conf['useHRDates']) { $pointerName = 'pointer'; $wrappedSubpartArray['###LINK_ITEM###'] = explode('|', $this->pi_linkTP_keepPIvars('|', array( 'tt_news' => null, 'backPid' => null, $this->config['singleViewPointerName'] => null, 'pS' => null, 'pL' => null), $this->allowCaching, ($this->conf['dontUseBackPid']?1:0), $this->config['backPid'])); } else { $wrappedSubpartArray['###LINK_ITEM###'] = explode('|', $this->pi_linkTP_keepPIvars('|', array( 'tt_news' => null, 'backPid' => null, $this->config['singleViewPointerName'] => null), $this->allowCaching, ($this->conf['dontUseBackPid']?1:0), $this->config['backPid'])); } // set the title of the single view page to the title of the news record if ($this->conf['substitutePagetitle']) { $GLOBALS['TSFE']->page['title'] = $row['title']; // set pagetitle for indexed search to news title $GLOBALS['TSFE']->indexedDocTitle = $row['title']; } if ($this->conf['displaySingle.']['catOrderBy']) { $this->config['catOrderBy'] = $this->conf['displaySingle.']['catOrderBy']; } $markerArray = $this->getItemMarkerArray($row, 'displaySingle'); // Substitute $content = $this->cObj->substituteMarkerArrayCached($item, $markerArray, array(), $wrappedSubpartArray); } elseif ($this->sys_language_mode == 'strict' && $this->tt_news_uid && $GLOBALS['TSFE']->sys_language_content) { // not existing translation $noTranslMsg = $this->local_cObj->stdWrap($this->pi_getLL('noTranslMsg'), $this->conf['noNewsIdMsg_stdWrap.']); $content = $noTranslMsg; } elseif ($row['pid'] < 0) { // a non-public version of a record was requested $nonPlublicVersion = $this->local_cObj->stdWrap($this->pi_getLL('nonPlublicVersionMsg'), $this->conf['nonPlublicVersionMsg_stdWrap.']); $content = $nonPlublicVersion; } else { // if singleview is shown with no tt_news uid given from GETvars (&tx_ttnews[tt_news]=) an error message is displayed. $noNewsIdMsg = $this->local_cObj->stdWrap($this->pi_getLL('noNewsIdMsg'), $this->conf['noNewsIdMsg_stdWrap.']); $content = $noNewsIdMsg; } return $content; }

/** * Displays the "versioning preview". * The functions checks: * - if the extension "version" is loaded * - if a BE_user is logged in * - the plausibility of the requested "version preview". * If this is all OK, "displaySingle()" is executed to display the "versioning preview". * * @returnstring html code for the "versioning preview" */ function displayVersionPreview () { if ($this->versioningEnabled) { $vPrev = t3lib_div::_GP('ADMCMD_vPrev'); if ($this->piVars['ADMCMD_vPrev']) { $piADMCMD = unserialize(rawurldecode($this->piVars['ADMCMD_vPrev'])); } if ((is_array($vPrev) || is_array($piADMCMD)) && is_object($GLOBALS['BE_USER'])) { // check if ADMCMD_vPrev is set and if a BE_user is logged in. $this->piVars['ADMCMD_vPrev'] is needed for previewing a "single view with pagebrowser" if (!is_array($vPrev)) { $vPrev = $piADMCMD; } list($table,$t3ver_oid) = explode(':',key($vPrev)); if ($table == 'tt_news') { if ($testrec = $this->pi_getRecord('tt_news', intval($vPrev[key($vPrev)]))) { // check if record exists before doing anything if ($testrec['t3ver_oid'] == intval($t3ver_oid) && $testrec['pid']==-1) { // check if requested t3ver_oid is the t3ver_oid of the requested tt_news record, and if the pid of the record is -1 (=non-plublic version) $GLOBALS['TSFE']->set_no_cache(); // version preview will never be cached // make version preview message with a link to the public version of hte record which is previewed $vPrevHeader = $this->local_cObj->stdWrap( $this->pi_getLL('versionPreviewMessage'). $this->local_cObj->typolink( $this->local_cObj->stdWrap( $this->pi_getLL('versionPreviewMessageLinkToOriginal'),$this->conf['versionPreviewMessageLinkToOriginal_stdWrap.'] ), array( 'parameter' => $this->config['singlePid'].' _blank', 'additionalParams' => '&tx_ttnews[tt_news]='.$t3ver_oid, 'no_cache' => 1 ) ), $this->conf['versionPreviewMessage_stdWrap.'] ); $this->tt_news_uid = intval($vPrev[key($vPrev)]); $this->piVars['tt_news'] = $this->tt_news_uid; $this->piVars['ADMCMD_vPrev'] = rawurlencode(serialize(array($table.':'.$t3ver_oid => $this->tt_news_uid))); $this->theCode = 'SINGLE'; $this->vPrev = true; $content = $vPrevHeader.$this->displaySingle(); } else { // error: t3ver_oid mismatch $GLOBALS['TT']->setTSlogMessage('tt_news: ERROR! The "t3ver_oid" of requested tt_news record and the "t3ver_oid" from GPvars doesn\'t match.'); } } } } } return $content; }

Page 36: Extbase and Beyond

<?php/**************************************************************** Copyright notice** (c) 1999-2004 Kasper SkÃ¥rhøj ([email protected])* (c) 2004-2007 Rupert Germann ([email protected])* 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 8605 2008-03-15 20:03:19Z rupertgermann $** TypoScript setup:* @See 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 <[email protected]>* @co-author Ingo Renner <[email protected]>*//** * [CLASS/FUNCTION INDEX of SCRIPT] * * * * 112: class tx_ttnews extends tslib_pibase * 143: function main_news($content, $conf) * 219: function init($conf) * 373: function newsArchiveMenu() * 523: function displaySingle() * 606: function displayVersionPreview () * 659: function displayList($excludeUids = 0) * 1003: function getListContent($itemparts, $selectConf, $prefix_display) * 1172: function getSelectConf($where, $noPeriod = 0) * 1419: function generatePageArray() * 1440: function getItemMarkerArray ($row, $textRenderObj = 'displaySingle') * 1723: function insertPagebreaks($text,$firstPageWordCrop) * 1773: function makeMultiPageSView($bodytext,$lConf) * 1803: function makePageBrowser($showResultCount=1,$tableParams='',$pointerName='pointer') * 1885: function getCategories($uid, $getAll=false) * 1958: function getCategoryPath($categoryArray) * 2015: function getSubCategories($catlist, $cc = 0) * 2044: function displayCatMenu() * 2157: function getCatMenuContent($array_in,$lConf, $l=0) * 2209: function getSubCategoriesForMenu ($catlist, $fields, $addWhere, $cc = 0) * 2240: function getCatMarkerArray($markerArray, $row, $lConf) * 2380: function getImageMarkers($markerArray, $row, $lConf, $textRenderObj) * 2448: function getRelated($uid) * 2608: function userProcess($mConfKey, $passVar) * 2623: function spMarker($subpartMarker) * 2641: function searchWhere($sw) * 2652: function formatStr($str) * 2667: function getLayouts($templateCode, $alternatingLayouts, $marker) * 2685: function initLanguages () * 2705: function initCategoryVars() * 2775: function checkRecords($recordlist) * 2807: function initTemplate() * 2832: function initPidList () * 2857: function getXmlHeader() * 2958: function getW3cDate($datetime) * 2983: function main_xmlnewsfeed($content, $conf) * 2998: function getStoriesResult() * 3020: function cleanXML($str) * 3034: function convertDates() * 3073: function getHrDateSingle($tstamp) * 3086: function displayFEHelp() * 3107: function validateFields($fieldlist) * 3128: function getNewsSubpart($myTemplate, $myKey, $row = Array()) * * SECTION: DB Functions * 3149: function exec_getQuery($table, $conf) * 3167: function getQuery($table, $conf, $returnQueryArray=FALSE) * 3249: function getWhere($table,$conf, $returnQueryArray=FALSE) * * TOTAL FUNCTIONS: 45 * (This index is automatically created/updated by the extension "extdeveval") * */

require_once(PATH_t3lib . 'class.t3lib_xml.php');require_once(PATH_t3lib . 'class.t3lib_htmlmail.php');require_once(PATH_tslib . 'class.tslib_pibase.php');require_once(t3lib_extMgm::extPath('tt_news') . 'class.tx_ttnews_catmenu.php');

/** * Plugin 'news' for the 'tt_news' extension. * * @author Rupert Germann <[email protected]> * @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 $tt_news_uid; // the uid of the current news record in SINGLE view var $config; // the processed TypoScript configuration array var $langArr; // the languages found in the tt_news sysfolder var $sys_language_mode; var $alternatingLayouts; var $allowCaching; var $catExclusive; var $arcExclusive; var $searchFieldList = 'short,bodytext,author,keywords,links,imagecaption,title'; var $theCode = ''; var $rdfToc = ''; var $versioningEnabled = false; // is the extension 'version' loaded var $vPrev = false; // do we display a versioning preview var $categories = array(); // Is initialized with the categories of the news system var $pageArray = array(); // Is initialized with an array of the pages in the pid-list

/** * 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 * @returnstring $content: complete content generated by the tt_news plugin */ function main_news($content, $conf) { $this->local_cObj = t3lib_div::makeInstance('tslib_cObj'); // Local cObj. $this->init($conf);

if ($this->conf['displayCurrentRecord']) { $this->config['code'] = $this->conf['defaultCode']?trim($this->conf['defaultCode']):'SINGLE'; $this->tt_news_uid = $this->cObj->data['uid']; }

// 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(); $noCode = true; }

while (list(, $theCode) = each($codes)) { $theCode = (string)strtoupper(trim($theCode)); $this->theCode = $theCode; switch ($theCode) { case 'SINGLE': $content .= $this->displaySingle(); break; case 'VERSION_PREVIEW': $content .= $this->displayVersionPreview(); break; case 'LATEST': case 'LIST': case 'SEARCH': case 'XML': $content .= $this->displayList(); break; case 'AMENU': $content .= $this->newsArchiveMenu(); break; case 'CATMENU': $content .= $this->displayCatMenu(); break; default: // Adds 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 { $langKey = strtoupper($GLOBALS['TSFE']->config['config']['language']); $helpTemplate = $this->cObj->fileResource('EXT:tt_news/pi/news_help.tmpl'); // Get language version of the help-template $helpTemplate_lang = ''; if ($langKey) { $helpTemplate_lang = $this->getNewsSubpart($helpTemplate, "###TEMPLATE_" . $langKey . '###'); } $helpTemplate = $helpTemplate_lang ? $helpTemplate_lang : $this->getNewsSubpart($helpTemplate, '###TEMPLATE_DEFAULT###'); // Markers and substitution: $markerArray['###CODE###'] = $this->theCode; $markerArray['###EXTPATH###'] = $GLOBALS['TYPO3_LOADED_EXT']['tt_news']['siteRelPath']; $content .= $this->displayFEHelp(); } break; } } if($noCode) { $content .= $this->displayFEHelp(); } return $content; }

/** * Init Function: here all the needed configuration values are stored in class variables.. * * @param array $conf : configuration array from TS * @returnvoid */ function init($conf) { $this->conf = $conf; //store configuration $this->pi_loadLL(); // Loading language-labels $this->pi_setPiVarDefaults(); // Set default piVars from TS $this->pi_initPIflexForm(); // Init FlexForm configuration for plugin $this->enableFields = $this->cObj->enableFields('tt_news'); $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->getCurrentVersion(); }

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 $this->sys_language_mode = $this->conf['sys_language_mode']?$this->conf['sys_language_mode'] : $GLOBALS['TSFE']->sys_language_mode;

// "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.']);

// initialize category vars $this->initCategoryVars();

// get fieldnames from the tt_news db-table $this->fieldNames = array_keys($GLOBALS['TYPO3_DB']->admin_get_fields('tt_news'));

if ($this->conf['searchFieldList']) { $searchFieldList = $this->validateFields($this->conf['searchFieldList']); if ($searchFieldList) { $this->searchFieldList = $searchFieldList; } } // Archive: $this->config['archiveMode'] = trim($this->conf['archiveMode']) ; // month, quarter or year listing in AMENU $this->config['archiveMode'] = $this->config['archiveMode']?$this->config['archiveMode']:'month';

// arcExclusive : -1=only non-archived; 0=don't care; 1=only archived $arcExclusive = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'archive', 'sDEF'); $this->arcExclusive = $arcExclusive?$arcExclusive:$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->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->config['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'] = $maxWordsInSingleView>1?1:$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'); $singlePid = $singlePid?$singlePid:intval($this->cObj->stdWrap($this->conf['singlePid'],$this->conf['singlePid.'])); $this->config['singlePid'] = $singlePid ? $singlePid:intval($this->conf['PIDitemDisplay']);

// pid to return to when leaving single view $backPid = intval($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'backPid', 's_misc')); $backPid = $backPid?$backPid:intval($this->conf['backPid']); $backPid = $backPid?$backPid:intval($this->piVars['backPid']); $backPid = $backPid?$backPid:$GLOBALS['TSFE']->id ; $this->config['backPid'] = $backPid;

// max items per page $FFlimit = t3lib_div::intInRange($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'listLimit', 's_misc'), 0, 1000);

$limit = t3lib_div::intInRange($this->cObj->stdWrap($this->conf['limit'],$this->conf['limit.']), 0, 1000); $limit = $limit?$limit: 50; $this->config['limit'] = $FFlimit?$FFlimit:$limit;

$latestLimit = t3lib_div::intInRange($this->cObj->stdWrap($this->conf['latestLimit'],$this->conf['latestLimit.']), 0, 1000); $latestLimit = $latestLimit?$latestLimit:10; $this->config['latestLimit'] = $FFlimit?$FFlimit:$latestLimit;

// orderBy and groupBy statements for the list Query $orderBy = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'listOrderBy', 'sDEF'); $orderByTS = trim($this->conf['listOrderBy']); $orderBy = $orderBy?$orderBy:$orderByTS; $this->config['orderBy'] = $orderBy;

if ($orderBy) { $ascDesc = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'ascDesc', 'sDEF'); $this->config['ascDesc'] = $ascDesc; if ($this->config['ascDesc']) { // remove ASC/DESC from 'orderBy' if it is already set from TS $this->config['orderBy'] = preg_replace('/( DESC| ASC)\b/i','',$this->config['orderBy']); } } $this->config['groupBy'] = trim($this->conf['listGroupBy']);

// if this is set, the first image is handled as preview image, which is only shown in list view $fImgPreview = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'firstImageIsPreview', 's_misc'); $this->config['firstImageIsPreview'] = $fImgPreview?$fImgPreview : $this->conf['firstImageIsPreview']; $forcefImgPreview = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'forceFirstImageIsPreview', 's_misc'); $this->config['forceFirstImageIsPreview'] = $forcefImgPreview?$fImgPreview : $this->conf['forceFirstImageIsPreview'];

// List start id $listStartId = intval($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'listStartId', 's_misc')); $this->config['listStartId'] = $listStartId?$listStartId:intval($this->conf['listStartId']); // supress pagebrowser $noPageBrowser = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'noPageBrowser', 's_misc'); $this->config['noPageBrowser'] = $noPageBrowser?$noPageBrowser: $this->conf['noPageBrowser'];

// image sizes given from FlexForms $this->config['FFimgH'] = intval($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'imageMaxHeight', 's_template')); $this->config['FFimgW'] = intval($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'imageMaxWidth', 's_template'));

// Get number of alternative Layouts (loop layout in LATEST and LIST view) default is 2: $altLayouts = intval($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'alternatingLayouts', 's_template')); $altLayouts = $altLayouts?$altLayouts:intval($this->conf['alternatingLayouts']); $this->alternatingLayouts = $altLayouts?$altLayouts:2;

// Get cropping lenght $this->config['croppingLenght'] = trim($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'croppingLenght', 's_template'));

$this->initTemplate();

// Configure caching $this->allowCaching = $this->conf['allowCaching']?1:0; if (!$this->allowCaching) { $GLOBALS['TSFE']->set_no_cache(); }

// get siteUrl for links in rss feeds. the 'dontInsert' option seems to be needed in some configurations depending on the baseUrl setting if (!$this->conf['displayXML.']['dontInsertSiteUrl']) { $this->config['siteUrl'] = t3lib_div::getIndpEnv('TYPO3_SITE_URL'); } }

/** * generates the News archive menu * * @returnstring html code of the archive menu */ function newsArchiveMenu() {

$this->arcExclusive = 1; $selectConf = $this->getSelectConf('', 1); // Finding maximum and minimum values: $selectConf['selectFields'] = 'max(tt_news.datetime) as maxval, min(tt_news.datetime) as minval';

$res = $this->exec_getQuery('tt_news', $selectConf);

$row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res); if ($row['minval'] || $row['maxval']) { // if ($row['minval']) { $dateArr = array(); $arcMode = $this->config['archiveMode']; $c = 0; do { switch ($arcMode) { case 'month': $theDate = mktime (0, 0, 0, date('m', $row['minval']) + $c, 1, date('Y', $row['minval'])); break; case 'quarter': $theDate = mktime (0, 0, 0, floor(date('m', $row['minval']) / 3) + 1 + (3 * $c), 1, date('Y', $row['minval'])); break; case 'year': $theDate = mktime (0, 0, 0, 1, 1, date('Y', $row['minval']) + $c); break; } $dateArr[] = $theDate; $c++; if ($c > 1000) break; } while ($theDate < $GLOBALS['SIM_EXEC_TIME']);

reset($dateArr); $periodAccum = array();

$selectConf2['where'] = $selectConf['where']; while (list($k, $v) = each($dateArr)) { if (!isset($dateArr[$k + 1])) { break; }

$periodInfo = array(); $periodInfo['start'] = $dateArr[$k]; $periodInfo['stop'] = $dateArr[$k + 1]-1; $periodInfo['HRstart'] = date('d-m-Y', $periodInfo['start']); $periodInfo['HRstop'] = date('d-m-Y', $periodInfo['stop']); $periodInfo['quarter'] = floor(date('m', $dateArr[$k]) / 3) + 1; // execute a query to count the archive periods $selectConf['selectFields'] = 'count(distinct(tt_news.uid))'; $selectConf['where'] = $selectConf2['where'] . ' AND tt_news.datetime>=' . $periodInfo['start'] . ' AND tt_news.datetime<' . $periodInfo['stop'];

$res = $this->exec_getQuery('tt_news', $selectConf);

$row = $GLOBALS['TYPO3_DB']->sql_fetch_row($res); $periodInfo['count'] = $row[0];

if (!$this->conf['archiveMenuNoEmpty'] || $periodInfo['count']) { $periodAccum[] = $periodInfo; } }

// get template subpart $t['total'] = $this->getNewsSubpart($this->templateCode, $this->spMarker('###TEMPLATE_ARCHIVE###')); $t['item'] = $this->getLayouts($t['total'], $this->alternatingLayouts, 'MENUITEM'); $cc = 0;

$veryLocal_cObj = t3lib_div::makeInstance('tslib_cObj'); // reverse amenu order if 'reverseAMenu' is given if ($this->conf['reverseAMenu']) { arsort($periodAccum); }

$archiveLink = $this->conf['archiveTypoLink.']['parameter']; $this->conf['parent.']['addParams'] = $this->conf['archiveTypoLink.']['addParams']; reset($periodAccum); $itemsOutArr = array(); while (list(, $pArr) = each($periodAccum)) { // Print Item Title $wrappedSubpartArray = array();

if (!$this->conf['disableCategoriesInAmenuLinks']) { if ($this->config['catSelection'] && $this->config['amenuWithCatSelector']) { // use the catSelection from GPvars only if 'amenuWithCatSelector' is given. $amenuLinkCat = $this->config['catSelection']; } else { $amenuLinkCat = $this->catExclusive; } }

if ($this->conf['useHRDates']) { $year = date('Y',$pArr['start']); $month = date('m',$pArr['start']); if ($arcMode == 'year') { $archLinkArr = $this->pi_linkTP_keepPIvars('|', array('cat' => ($amenuLinkCat?$amenuLinkCat:null), 'year' => $year), $this->allowCaching, 1, ($archiveLink?$archiveLink:$GLOBALS['TSFE']->id)); } else { $archLinkArr = $this->pi_linkTP_keepPIvars('|', array('cat' => ($amenuLinkCat?$amenuLinkCat:null), 'year' => $year, 'month' => $month), $this->allowCaching, 1, ($archiveLink?$archiveLink:$GLOBALS['TSFE']->id)); } $wrappedSubpartArray['###LINK_ITEM###'] = explode('|', $archLinkArr); } else { $wrappedSubpartArray['###LINK_ITEM###'] = explode('|', $this->pi_linkTP_keepPIvars('|', array('cat' => ($amenuLinkCat?$amenuLinkCat:null), 'pS' => $pArr['start'], 'pL' => ($pArr['stop'] - $pArr['start']), 'arc' => 1), $this->allowCaching, 1, ($archiveLink?$archiveLink:$GLOBALS['TSFE']->id))); }

$markerArray = array(); $veryLocal_cObj->start($pArr, ''); $markerArray['###ARCHIVE_TITLE###'] = $veryLocal_cObj->cObjGetSingle($this->conf['archiveTitleCObject'], $this->conf['archiveTitleCObject.'], 'archiveTitle'); $markerArray['###ARCHIVE_COUNT###'] = $pArr['count']; $markerArray['###ARCHIVE_ITEMS###'] = $this->pi_getLL('archiveItems');

// fill the generated data to an array to pass it to a userfuction as a single variable $itemsOutArr[] = array('html' => $this->cObj->substituteMarkerArrayCached($t['item'][($cc % count($t['item']))], $markerArray, array(), $wrappedSubpartArray), 'data' => $pArr); $cc++; } // Pass to user defined function if ($this->conf['newsAmenuUserFunc']) { $itemsOutArr = $this->userProcess('newsAmenuUserFunc', $itemsOutArr); }

foreach ($itemsOutArr as $itemHtml) { $tmpItemsArr[] = $itemHtml['html']; }

if (is_array($tmpItemsArr)) { $itemsOut = implode('', $tmpItemsArr); }

// Reset: $subpartArray = array(); $wrappedSubpartArray = array(); $markerArray = array(); $markerArray['###ARCHIVE_HEADER###'] = $this->local_cObj->stdWrap($this->pi_getLL('archiveHeader'), $this->conf['archiveHeader_stdWrap.']); // Set content $subpartArray['###CONTENT###'] = $itemsOut; $content = $this->cObj->substituteMarkerArrayCached($t['total'], $markerArray, $subpartArray, $wrappedSubpartArray); } else { // if nothing is found in the archive display the TEMPLATE_ARCHIVE_NOITEMS message $markerArray['###ARCHIVE_HEADER###'] = $this->local_cObj->stdWrap($this->pi_getLL('archiveHeader'), $this->conf['archiveHeader_stdWrap.']); $markerArray['###ARCHIVE_EMPTY_MSG###'] = $this->local_cObj->stdWrap($this->pi_getLL('archiveEmptyMsg'), $this->conf['archiveEmptyMsg_stdWrap.']); $noItemsMsg = $this->getNewsSubpart($this->templateCode, $this->spMarker('###TEMPLATE_ARCHIVE_NOITEMS###')); $content = $this->cObj->substituteMarkerArrayCached($noItemsMsg, $markerArray); }

return $content; }

/** * Displays the "single view" of a news article. Is also used when displaying single news records with the "insert records" content element. * * @returnstring html-code for the "single view" */ function displaySingle() { $singleWhere = 'tt_news.uid=' . intval($this->tt_news_uid); $singleWhere .= ' AND type NOT IN(1,2)' . $this->enableFields; // only real news -> type=0

$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery( '*', 'tt_news', $singleWhere);

$row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res); // get the translated record if the content language is not the default language if ($GLOBALS['TSFE']->sys_language_content) { $OLmode = ($this->sys_language_mode == 'strict'?'hideNonTranslated':''); $row = $GLOBALS['TSFE']->sys_page->getRecordOverlay('tt_news', $row, $GLOBALS['TSFE']->sys_language_content, $OLmode); } if ($this->versioningEnabled) { // get workspaces Overlay $GLOBALS['TSFE']->sys_page->versionOL('tt_news',$row); // fix pid for record from workspace $GLOBALS['TSFE']->sys_page->fixVersioningPid('tt_news',$row); } $GLOBALS['TSFE']->displayedNews[]=$row['uid'];

if (is_array($row) && ($row['pid'] > 0 || $this->vPrev)) { // never display versions of a news record (having pid=-1) for normal website users // Get the subpart code if ($this->conf['displayCurrentRecord']) { $item = trim($this->getNewsSubpart($this->templateCode, $this->spMarker('###TEMPLATE_SINGLE_RECORDINSERT###'), $row)); } if (!$item) { $item = $this->getNewsSubpart($this->templateCode, $this->spMarker('###TEMPLATE_SINGLE###'), $row); } // reset marker array $wrappedSubpartArray = array(); // build the backToList link if ($this->conf['useHRDates']) { $pointerName = 'pointer'; $wrappedSubpartArray['###LINK_ITEM###'] = explode('|', $this->pi_linkTP_keepPIvars('|', array( 'tt_news' => null, 'backPid' => null, $this->config['singleViewPointerName'] => null, 'pS' => null, 'pL' => null), $this->allowCaching, ($this->conf['dontUseBackPid']?1:0), $this->config['backPid'])); } else { $wrappedSubpartArray['###LINK_ITEM###'] = explode('|', $this->pi_linkTP_keepPIvars('|', array( 'tt_news' => null, 'backPid' => null, $this->config['singleViewPointerName'] => null), $this->allowCaching, ($this->conf['dontUseBackPid']?1:0), $this->config['backPid'])); } // set the title of the single view page to the title of the news record if ($this->conf['substitutePagetitle']) { $GLOBALS['TSFE']->page['title'] = $row['title']; // set pagetitle for indexed search to news title $GLOBALS['TSFE']->indexedDocTitle = $row['title']; } if ($this->conf['displaySingle.']['catOrderBy']) { $this->config['catOrderBy'] = $this->conf['displaySingle.']['catOrderBy']; } $markerArray = $this->getItemMarkerArray($row, 'displaySingle'); // Substitute $content = $this->cObj->substituteMarkerArrayCached($item, $markerArray, array(), $wrappedSubpartArray); } elseif ($this->sys_language_mode == 'strict' && $this->tt_news_uid && $GLOBALS['TSFE']->sys_language_content) { // not existing translation $noTranslMsg = $this->local_cObj->stdWrap($this->pi_getLL('noTranslMsg'), $this->conf['noNewsIdMsg_stdWrap.']); $content = $noTranslMsg; } elseif ($row['pid'] < 0) { // a non-public version of a record was requested $nonPlublicVersion = $this->local_cObj->stdWrap($this->pi_getLL('nonPlublicVersionMsg'), $this->conf['nonPlublicVersionMsg_stdWrap.']); $content = $nonPlublicVersion; } else { // if singleview is shown with no tt_news uid given from GETvars (&tx_ttnews[tt_news]=) an error message is displayed. $noNewsIdMsg = $this->local_cObj->stdWrap($this->pi_getLL('noNewsIdMsg'), $this->conf['noNewsIdMsg_stdWrap.']); $content = $noNewsIdMsg; } return $content; }

/** * Displays the "versioning preview". * The functions checks: * - if the extension "version" is loaded * - if a BE_user is logged in * - the plausibility of the requested "version preview". * If this is all OK, "displaySingle()" is executed to display the "versioning preview". * * @returnstring html code for the "versioning preview" */ function displayVersionPreview () { if ($this->versioningEnabled) { $vPrev = t3lib_div::_GP('ADMCMD_vPrev'); if ($this->piVars['ADMCMD_vPrev']) { $piADMCMD = unserialize(rawurldecode($this->piVars['ADMCMD_vPrev'])); } if ((is_array($vPrev) || is_array($piADMCMD)) && is_object($GLOBALS['BE_USER'])) { // check if ADMCMD_vPrev is set and if a BE_user is logged in. $this->piVars['ADMCMD_vPrev'] is needed for previewing a "single view with pagebrowser" if (!is_array($vPrev)) { $vPrev = $piADMCMD; } list($table,$t3ver_oid) = explode(':',key($vPrev)); if ($table == 'tt_news') { if ($testrec = $this->pi_getRecord('tt_news', intval($vPrev[key($vPrev)]))) { // check if record exists before doing anything if ($testrec['t3ver_oid'] == intval($t3ver_oid) && $testrec['pid']==-1) { // check if requested t3ver_oid is the t3ver_oid of the requested tt_news record, and if the pid of the record is -1 (=non-plublic version) $GLOBALS['TSFE']->set_no_cache(); // version preview will never be cached // make version preview message with a link to the public version of hte record which is previewed $vPrevHeader = $this->local_cObj->stdWrap( $this->pi_getLL('versionPreviewMessage'). $this->local_cObj->typolink( $this->local_cObj->stdWrap( $this->pi_getLL('versionPreviewMessageLinkToOriginal'),$this->conf['versionPreviewMessageLinkToOriginal_stdWrap.'] ), array( 'parameter' => $this->config['singlePid'].' _blank', 'additionalParams' => '&tx_ttnews[tt_news]='.$t3ver_oid, 'no_cache' => 1 ) ), $this->conf['versionPreviewMessage_stdWrap.'] ); $this->tt_news_uid = intval($vPrev[key($vPrev)]); $this->piVars['tt_news'] = $this->tt_news_uid; $this->piVars['ADMCMD_vPrev'] = rawurlencode(serialize(array($table.':'.$t3ver_oid => $this->tt_news_uid))); $this->theCode = 'SINGLE'; $this->vPrev = true; $content = $vPrevHeader.$this->displaySingle(); } else { // error: t3ver_oid mismatch $GLOBALS['TT']->setTSlogMessage('tt_news: ERROR! The "t3ver_oid" of requested tt_news record and the "t3ver_oid" from GPvars doesn\'t match.'); } } } } } return $content; }

Page 37: Extbase and Beyond

<?php/**************************************************************** Copyright notice** (c) 1999-2004 Kasper SkÃ¥rhøj ([email protected])* (c) 2004-2007 Rupert Germann ([email protected])* 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 8605 2008-03-15 20:03:19Z rupertgermann $** TypoScript setup:* @See 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 <[email protected]>* @co-author Ingo Renner <[email protected]>*//** * [CLASS/FUNCTION INDEX of SCRIPT] * * * * 112: class tx_ttnews extends tslib_pibase * 143: function main_news($content, $conf) * 219: function init($conf) * 373: function newsArchiveMenu() * 523: function displaySingle() * 606: function displayVersionPreview () * 659: function displayList($excludeUids = 0) * 1003: function getListContent($itemparts, $selectConf, $prefix_display) * 1172: function getSelectConf($where, $noPeriod = 0) * 1419: function generatePageArray() * 1440: function getItemMarkerArray ($row, $textRenderObj = 'displaySingle') * 1723: function insertPagebreaks($text,$firstPageWordCrop) * 1773: function makeMultiPageSView($bodytext,$lConf) * 1803: function makePageBrowser($showResultCount=1,$tableParams='',$pointerName='pointer') * 1885: function getCategories($uid, $getAll=false) * 1958: function getCategoryPath($categoryArray) * 2015: function getSubCategories($catlist, $cc = 0) * 2044: function displayCatMenu() * 2157: function getCatMenuContent($array_in,$lConf, $l=0) * 2209: function getSubCategoriesForMenu ($catlist, $fields, $addWhere, $cc = 0) * 2240: function getCatMarkerArray($markerArray, $row, $lConf) * 2380: function getImageMarkers($markerArray, $row, $lConf, $textRenderObj) * 2448: function getRelated($uid) * 2608: function userProcess($mConfKey, $passVar) * 2623: function spMarker($subpartMarker) * 2641: function searchWhere($sw) * 2652: function formatStr($str) * 2667: function getLayouts($templateCode, $alternatingLayouts, $marker) * 2685: function initLanguages () * 2705: function initCategoryVars() * 2775: function checkRecords($recordlist) * 2807: function initTemplate() * 2832: function initPidList () * 2857: function getXmlHeader() * 2958: function getW3cDate($datetime) * 2983: function main_xmlnewsfeed($content, $conf) * 2998: function getStoriesResult() * 3020: function cleanXML($str) * 3034: function convertDates() * 3073: function getHrDateSingle($tstamp) * 3086: function displayFEHelp() * 3107: function validateFields($fieldlist) * 3128: function getNewsSubpart($myTemplate, $myKey, $row = Array()) * * SECTION: DB Functions * 3149: function exec_getQuery($table, $conf) * 3167: function getQuery($table, $conf, $returnQueryArray=FALSE) * 3249: function getWhere($table,$conf, $returnQueryArray=FALSE) * * TOTAL FUNCTIONS: 45 * (This index is automatically created/updated by the extension "extdeveval") * */

require_once(PATH_t3lib . 'class.t3lib_xml.php');require_once(PATH_t3lib . 'class.t3lib_htmlmail.php');require_once(PATH_tslib . 'class.tslib_pibase.php');require_once(t3lib_extMgm::extPath('tt_news') . 'class.tx_ttnews_catmenu.php');

/** * Plugin 'news' for the 'tt_news' extension. * * @author Rupert Germann <[email protected]> * @package TYPO3 * @subpackage tt_news */class tx_ttnews extends tslib_pibase {// Default plugin variables:var $prefixId = 'tx_ttnews'; // Same as class namevar $scriptRelPath = 'pi/class.tx_ttnews.php'; // Path to this script relative to the extension dir.var $extKey = 'tt_news'; // The extension key.var $tt_news_uid; // the uid of the current news record in SINGLE viewvar $config; // the processed TypoScript configuration arrayvar $langArr; // the languages found in the tt_news sysfoldervar $sys_language_mode;var $alternatingLayouts;var $allowCaching;var $catExclusive;var $arcExclusive;var $searchFieldList = 'short,bodytext,author,keywords,links,imagecaption,title';var $theCode = '';var $rdfToc = '';var $versioningEnabled = false; // is the extension 'version' loadedvar $vPrev = false; // do we display a versioning previewvar $categories = array(); // Is initialized with the categories of the news systemvar $pageArray = array(); // Is initialized with an array of the pages in the pid-list

/** * Main news function: calls the init_news() function and decides by the given CODEs which of the * functions to display news should by called. * * @paramstring $content : function output is added to this * @paramarray $conf : configuration array * @returnstring $content: complete content generated by the tt_news plugin */function main_news($content, $conf) { $this->local_cObj = t3lib_div::makeInstance('tslib_cObj'); // Local cObj. $this->init($conf);

if ($this->conf['displayCurrentRecord']) { $this->config['code'] = $this->conf['defaultCode']?trim($this->conf['defaultCode']):'SINGLE'; $this->tt_news_uid = $this->cObj->data['uid']; }

// 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(); $noCode = true; }

while (list(, $theCode) = each($codes)) { $theCode = (string)strtoupper(trim($theCode)); $this->theCode = $theCode; switch ($theCode) { case 'SINGLE': $content .= $this->displaySingle(); break; case 'VERSION_PREVIEW': $content .= $this->displayVersionPreview(); break; case 'LATEST': case 'LIST': case 'SEARCH': case 'XML': $content .= $this->displayList(); break; case 'AMENU': $content .= $this->newsArchiveMenu(); break; case 'CATMENU': $content .= $this->displayCatMenu(); break; default: // Adds 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 { $langKey = strtoupper($GLOBALS['TSFE']->config['config']['language']); $helpTemplate = $this->cObj->fileResource('EXT:tt_news/pi/news_help.tmpl'); // Get language version of the help-template $helpTemplate_lang = ''; if ($langKey) { $helpTemplate_lang = $this->getNewsSubpart($helpTemplate, "###TEMPLATE_" . $langKey . '###'); } $helpTemplate = $helpTemplate_lang ? $helpTemplate_lang : $this->getNewsSubpart($helpTemplate, '###TEMPLATE_DEFAULT###'); // Markers and substitution: $markerArray['###CODE###'] = $this->theCode; $markerArray['###EXTPATH###'] = $GLOBALS['TYPO3_LOADED_EXT']['tt_news']['siteRelPath']; $content .= $this->displayFEHelp(); } break; } } if($noCode) { $content .= $this->displayFEHelp(); } return $content;}

/** * Init Function: here all the needed configuration values are stored in class variables.. * * @paramarray $conf : configuration array from TS * @returnvoid */function init($conf) { $this->conf = $conf; //store configuration $this->pi_loadLL(); // Loading language-labels $this->pi_setPiVarDefaults(); // Set default piVars from TS $this->pi_initPIflexForm(); // Init FlexForm configuration for plugin $this->enableFields = $this->cObj->enableFields('tt_news'); $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->getCurrentVersion(); }

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 $this->sys_language_mode = $this->conf['sys_language_mode']?$this->conf['sys_language_mode'] : $GLOBALS['TSFE']->sys_language_mode;

// "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.']);

// initialize category vars $this->initCategoryVars();

// get fieldnames from the tt_news db-table $this->fieldNames = array_keys($GLOBALS['TYPO3_DB']->admin_get_fields('tt_news'));

if ($this->conf['searchFieldList']) { $searchFieldList = $this->validateFields($this->conf['searchFieldList']); if ($searchFieldList) { $this->searchFieldList = $searchFieldList; } } // Archive: $this->config['archiveMode'] = trim($this->conf['archiveMode']) ; // month, quarter or year listing in AMENU $this->config['archiveMode'] = $this->config['archiveMode']?$this->config['archiveMode']:'month';

// arcExclusive : -1=only non-archived; 0=don't care; 1=only archived $arcExclusive = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'archive', 'sDEF'); $this->arcExclusive = $arcExclusive?$arcExclusive:$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->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->config['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'] = $maxWordsInSingleView>1?1:$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'); $singlePid = $singlePid?$singlePid:intval($this->cObj->stdWrap($this->conf['singlePid'],$this->conf['singlePid.'])); $this->config['singlePid'] = $singlePid ? $singlePid:intval($this->conf['PIDitemDisplay']);

// pid to return to when leaving single view $backPid = intval($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'backPid', 's_misc')); $backPid = $backPid?$backPid:intval($this->conf['backPid']); $backPid = $backPid?$backPid:intval($this->piVars['backPid']); $backPid = $backPid?$backPid:$GLOBALS['TSFE']->id ; $this->config['backPid'] = $backPid;

// max items per page $FFlimit = t3lib_div::intInRange($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'listLimit', 's_misc'), 0, 1000);

$limit = t3lib_div::intInRange($this->cObj->stdWrap($this->conf['limit'],$this->conf['limit.']), 0, 1000); $limit = $limit?$limit:50; $this->config['limit'] = $FFlimit?$FFlimit:$limit;

$latestLimit = t3lib_div::intInRange($this->cObj->stdWrap($this->conf['latestLimit'],$this->conf['latestLimit.']), 0, 1000); $latestLimit = $latestLimit?$latestLimit:10; $this->config['latestLimit'] = $FFlimit?$FFlimit:$latestLimit;

// orderBy and groupBy statements for the list Query $orderBy = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'listOrderBy', 'sDEF'); $orderByTS = trim($this->conf['listOrderBy']); $orderBy = $orderBy?$orderBy:$orderByTS; $this->config['orderBy'] = $orderBy;

if ($orderBy) { $ascDesc = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'ascDesc', 'sDEF'); $this->config['ascDesc'] = $ascDesc; if ($this->config['ascDesc']) { // remove ASC/DESC from 'orderBy' if it is already set from TS $this->config['orderBy'] = preg_replace('/( DESC| ASC)\b/i','',$this->config['orderBy']); } } $this->config['groupBy'] = trim($this->conf['listGroupBy']);

// if this is set, the first image is handled as preview image, which is only shown in list view $fImgPreview = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'firstImageIsPreview', 's_misc'); $this->config['firstImageIsPreview'] = $fImgPreview?$fImgPreview : $this->conf['firstImageIsPreview']; $forcefImgPreview = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'forceFirstImageIsPreview', 's_misc'); $this->config['forceFirstImageIsPreview'] = $forcefImgPreview?$fImgPreview : $this->conf['forceFirstImageIsPreview'];

// List start id $listStartId = intval($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'listStartId', 's_misc')); $this->config['listStartId'] = $listStartId?$listStartId:intval($this->conf['listStartId']); // supress pagebrowser $noPageBrowser = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'noPageBrowser', 's_misc'); $this->config['noPageBrowser'] = $noPageBrowser?$noPageBrowser:$this->conf['noPageBrowser'];

// image sizes given from FlexForms $this->config['FFimgH'] = intval($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'imageMaxHeight', 's_template')); $this->config['FFimgW'] = intval($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'imageMaxWidth', 's_template'));

// Get number of alternative Layouts (loop layout in LATEST and LIST view) default is 2: $altLayouts = intval($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'alternatingLayouts', 's_template')); $altLayouts = $altLayouts?$altLayouts:intval($this->conf['alternatingLayouts']); $this->alternatingLayouts = $altLayouts?$altLayouts:2;

// Get cropping lenght $this->config['croppingLenght'] = trim($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'croppingLenght', 's_template'));

$this->initTemplate();

// Configure caching $this->allowCaching = $this->conf['allowCaching']?1:0; if (!$this->allowCaching) { $GLOBALS['TSFE']->set_no_cache(); }

// get siteUrl for links in rss feeds. the 'dontInsert' option seems to be needed in some configurations depending on the baseUrl setting if (!$this->conf['displayXML.']['dontInsertSiteUrl']) { $this->config['siteUrl'] = t3lib_div::getIndpEnv('TYPO3_SITE_URL'); }}

/** * generates the News archive menu * * @returnstring html code of the archive menu */function newsArchiveMenu() {

$this->arcExclusive = 1; $selectConf = $this->getSelectConf('', 1); // Finding maximum and minimum values: $selectConf['selectFields'] = 'max(tt_news.datetime) as maxval, min(tt_news.datetime) as minval';

$res = $this->exec_getQuery('tt_news', $selectConf);

$row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res); if ($row['minval'] || $row['maxval']) { // if ($row['minval']) { $dateArr = array(); $arcMode = $this->config['archiveMode']; $c = 0; do { switch ($arcMode) { case 'month': $theDate = mktime (0, 0, 0, date('m', $row['minval']) + $c, 1, date('Y', $row['minval'])); break; case 'quarter': $theDate = mktime (0, 0, 0, floor(date('m', $row['minval']) / 3) + 1 + (3 * $c), 1, date('Y', $row['minval'])); break; case 'year': $theDate = mktime (0, 0, 0, 1, 1, date('Y', $row['minval']) + $c); break; } $dateArr[] = $theDate; $c++; if ($c > 1000) break; } while ($theDate < $GLOBALS['SIM_EXEC_TIME']);

reset($dateArr); $periodAccum = array();

$selectConf2['where'] = $selectConf['where']; while (list($k, $v) = each($dateArr)) { if (!isset($dateArr[$k + 1])) { break; }

$periodInfo = array(); $periodInfo['start'] = $dateArr[$k]; $periodInfo['stop'] = $dateArr[$k + 1]-1; $periodInfo['HRstart'] = date('d-m-Y', $periodInfo['start']); $periodInfo['HRstop'] = date('d-m-Y', $periodInfo['stop']); $periodInfo['quarter'] = floor(date('m', $dateArr[$k]) / 3) + 1; // execute a query to count the archive periods $selectConf['selectFields'] = 'count(distinct(tt_news.uid))'; $selectConf['where'] = $selectConf2['where'] . ' AND tt_news.datetime>=' . $periodInfo['start'] . ' AND tt_news.datetime<' . $periodInfo['stop'];

$res = $this->exec_getQuery('tt_news', $selectConf);

$row = $GLOBALS['TYPO3_DB']->sql_fetch_row($res); $periodInfo['count'] = $row[0];

if (!$this->conf['archiveMenuNoEmpty'] || $periodInfo['count']) { $periodAccum[] = $periodInfo; } }

// get template subpart $t['total'] = $this->getNewsSubpart($this->templateCode, $this->spMarker('###TEMPLATE_ARCHIVE###')); $t['item'] = $this->getLayouts($t['total'], $this->alternatingLayouts, 'MENUITEM'); $cc = 0;

$veryLocal_cObj = t3lib_div::makeInstance('tslib_cObj'); // reverse amenu order if 'reverseAMenu' is given if ($this->conf['reverseAMenu']) { arsort($periodAccum); }

$archiveLink = $this->conf['archiveTypoLink.']['parameter']; $this->conf['parent.']['addParams'] = $this->conf['archiveTypoLink.']['addParams']; reset($periodAccum); $itemsOutArr = array(); while (list(, $pArr) = each($periodAccum)) { // Print Item Title $wrappedSubpartArray = array();

if (!$this->conf['disableCategoriesInAmenuLinks']) { if ($this->config['catSelection'] && $this->config['amenuWithCatSelector']) { // use the catSelection from GPvars only if 'amenuWithCatSelector' is given. $amenuLinkCat = $this->config['catSelection']; } else { $amenuLinkCat = $this->catExclusive; } }

if ($this->conf['useHRDates']) { $year = date('Y',$pArr['start']); $month = date('m',$pArr['start']); if ($arcMode == 'year') { $archLinkArr = $this->pi_linkTP_keepPIvars('|', array('cat' => ($amenuLinkCat?$amenuLinkCat:null), 'year' => $year), $this->allowCaching, 1, ($archiveLink?$archiveLink:$GLOBALS['TSFE']->id)); } else { $archLinkArr = $this->pi_linkTP_keepPIvars('|', array('cat' => ($amenuLinkCat?$amenuLinkCat:null), 'year' => $year, 'month' => $month), $this->allowCaching, 1, ($archiveLink?$archiveLink:$GLOBALS['TSFE']->id)); } $wrappedSubpartArray['###LINK_ITEM###'] = explode('|', $archLinkArr); } else { $wrappedSubpartArray['###LINK_ITEM###'] = explode('|', $this->pi_linkTP_keepPIvars('|', array('cat' => ($amenuLinkCat?$amenuLinkCat:null), 'pS' => $pArr['start'], 'pL' => ($pArr['stop'] - $pArr['start']), 'arc' => 1), $this->allowCaching, 1, ($archiveLink?$archiveLink:$GLOBALS['TSFE']->id))); }

$markerArray = array(); $veryLocal_cObj->start($pArr, ''); $markerArray['###ARCHIVE_TITLE###'] = $veryLocal_cObj->cObjGetSingle($this->conf['archiveTitleCObject'], $this->conf['archiveTitleCObject.'], 'archiveTitle'); $markerArray['###ARCHIVE_COUNT###'] = $pArr['count']; $markerArray['###ARCHIVE_ITEMS###'] = $this->pi_getLL('archiveItems');

// fill the generated data to an array to pass it to a userfuction as a single variable $itemsOutArr[] = array('html' => $this->cObj->substituteMarkerArrayCached($t['item'][($cc % count($t['item']))], $markerArray, array(), $wrappedSubpartArray), 'data' => $pArr); $cc++; } // Pass to user defined function if ($this->conf['newsAmenuUserFunc']) { $itemsOutArr = $this->userProcess('newsAmenuUserFunc', $itemsOutArr); }

foreach ($itemsOutArr as $itemHtml) { $tmpItemsArr[] = $itemHtml['html']; }

if (is_array($tmpItemsArr)) { $itemsOut = implode('', $tmpItemsArr); }

// Reset: $subpartArray = array(); $wrappedSubpartArray = array(); $markerArray = array(); $markerArray['###ARCHIVE_HEADER###'] = $this->local_cObj->stdWrap($this->pi_getLL('archiveHeader'), $this->conf['archiveHeader_stdWrap.']); // Set content $subpartArray['###CONTENT###'] = $itemsOut; $content = $this->cObj->substituteMarkerArrayCached($t['total'], $markerArray, $subpartArray, $wrappedSubpartArray); } else { // if nothing is found in the archive display the TEMPLATE_ARCHIVE_NOITEMS message $markerArray['###ARCHIVE_HEADER###'] = $this->local_cObj->stdWrap($this->pi_getLL('archiveHeader'), $this->conf['archiveHeader_stdWrap.']); $markerArray['###ARCHIVE_EMPTY_MSG###'] = $this->local_cObj->stdWrap($this->pi_getLL('archiveEmptyMsg'), $this->conf['archiveEmptyMsg_stdWrap.']); $noItemsMsg = $this->getNewsSubpart($this->templateCode, $this->spMarker('###TEMPLATE_ARCHIVE_NOITEMS###')); $content = $this->cObj->substituteMarkerArrayCached($noItemsMsg, $markerArray); }

return $content;}

/** * Displays the "single view" of a news article. Is also used when displaying single news records with the "insert records" content element. * * @returnstring html-code for the "single view" */function displaySingle() { $singleWhere = 'tt_news.uid=' . intval($this->tt_news_uid); $singleWhere .= ' AND type NOT IN(1,2)' . $this->enableFields; // only real news -> type=0

$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery( '*', 'tt_news', $singleWhere);

$row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res); // get the translated record if the content language is not the default language if ($GLOBALS['TSFE']->sys_language_content) { $OLmode = ($this->sys_language_mode == 'strict'?'hideNonTranslated':''); $row = $GLOBALS['TSFE']->sys_page->getRecordOverlay('tt_news', $row, $GLOBALS['TSFE']->sys_language_content, $OLmode); } if ($this->versioningEnabled) { // get workspaces Overlay $GLOBALS['TSFE']->sys_page->versionOL('tt_news',$row); // fix pid for record from workspace $GLOBALS['TSFE']->sys_page->fixVersioningPid('tt_news',$row); } $GLOBALS['TSFE']->displayedNews[]=$row['uid'];

if (is_array($row) && ($row['pid'] > 0 || $this->vPrev)) { // never display versions of a news record (having pid=-1) for normal website users // Get the subpart code if ($this->conf['displayCurrentRecord']) { $item = trim($this->getNewsSubpart($this->templateCode, $this->spMarker('###TEMPLATE_SINGLE_RECORDINSERT###'), $row)); } if (!$item) { $item = $this->getNewsSubpart($this->templateCode, $this->spMarker('###TEMPLATE_SINGLE###'), $row); } // reset marker array $wrappedSubpartArray = array(); // build the backToList link if ($this->conf['useHRDates']) { $pointerName = 'pointer'; $wrappedSubpartArray['###LINK_ITEM###'] = explode('|', $this->pi_linkTP_keepPIvars('|', array( 'tt_news' => null, 'backPid' => null, $this->config['singleViewPointerName'] => null, 'pS' => null, 'pL' => null), $this->allowCaching, ($this->conf['dontUseBackPid']?1:0), $this->config['backPid'])); } else { $wrappedSubpartArray['###LINK_ITEM###'] = explode('|', $this->pi_linkTP_keepPIvars('|', array( 'tt_news' => null, 'backPid' => null, $this->config['singleViewPointerName'] => null), $this->allowCaching, ($this->conf['dontUseBackPid']?1:0), $this->config['backPid'])); } // set the title of the single view page to the title of the news record if ($this->conf['substitutePagetitle']) { $GLOBALS['TSFE']->page['title'] = $row['title']; // set pagetitle for indexed search to news title $GLOBALS['TSFE']->indexedDocTitle = $row['title']; } if ($this->conf['displaySingle.']['catOrderBy']) { $this->config['catOrderBy'] = $this->conf['displaySingle.']['catOrderBy']; } $markerArray = $this->getItemMarkerArray($row, 'displaySingle'); // Substitute $content = $this->cObj->substituteMarkerArrayCached($item, $markerArray, array(), $wrappedSubpartArray); } elseif ($this->sys_language_mode == 'strict' && $this->tt_news_uid && $GLOBALS['TSFE']->sys_language_content) { // not existing translation $noTranslMsg = $this->local_cObj->stdWrap($this->pi_getLL('noTranslMsg'), $this->conf['noNewsIdMsg_stdWrap.']); $content = $noTranslMsg; } elseif ($row['pid'] < 0) { // a non-public version of a record was requested $nonPlublicVersion = $this->local_cObj->stdWrap($this->pi_getLL('nonPlublicVersionMsg'), $this->conf['nonPlublicVersionMsg_stdWrap.']); $content = $nonPlublicVersion; } else { // if singleview is shown with no tt_news uid given from GETvars (&tx_ttnews[tt_news]=) an error message is displayed. $noNewsIdMsg = $this->local_cObj->stdWrap($this->pi_getLL('noNewsIdMsg'), $this->conf['noNewsIdMsg_stdWrap.']); $content = $noNewsIdMsg; } return $content;}

/** * Displays the "versioning preview". * The functions checks: * - if the extension "version" is loaded * - if a BE_user is logged in * - the plausibility of the requested "version preview". * If this is all OK, "displaySingle()" is executed to display the "versioning preview". * * @returnstring html code for the "versioning preview" */function displayVersionPreview () { if ($this->versioningEnabled) { $vPrev = t3lib_div::_GP('ADMCMD_vPrev'); if ($this->piVars['ADMCMD_vPrev']) { $piADMCMD = unserialize(rawurldecode($this->piVars['ADMCMD_vPrev'])); } if ((is_array($vPrev) || is_array($piADMCMD)) && is_object($GLOBALS['BE_USER'])) { // check if ADMCMD_vPrev is set and if a BE_user is logged in. $this->piVars['ADMCMD_vPrev'] is needed for previewing a "single view with pagebrowser" if (!is_array($vPrev)) { $vPrev = $piADMCMD; } list($table,$t3ver_oid) = explode(':',key($vPrev)); if ($table == 'tt_news') { if ($testrec = $this->pi_getRecord('tt_news', intval($vPrev[key($vPrev)]))) { // check if record exists before doing anything if ($testrec['t3ver_oid'] == intval($t3ver_oid) && $testrec['pid']==-1) { // check if requested t3ver_oid is the t3ver_oid of the requested tt_news record, and if the pid of the record is -1 (=non-plublic version) $GLOBALS['TSFE']->set_no_cache(); // version preview will never be cached // make version preview message with a link to the public version of hte record which is previewed $vPrevHeader = $this->local_cObj->stdWrap( $this->pi_getLL('versionPreviewMessage'). $this->local_cObj->typolink( $this->local_cObj->stdWrap( $this->pi_getLL('versionPreviewMessageLinkToOriginal'),$this->conf['versionPreviewMessageLinkToOriginal_stdWrap.'] ), array( 'parameter' => $this->config['singlePid'].' _blank', 'additionalParams' => '&tx_ttnews[tt_news]='.$t3ver_oid, 'no_cache' => 1 ) ), $this->conf['versionPreviewMessage_stdWrap.'] ); $this->tt_news_uid = intval($vPrev[key($vPrev)]); $this->piVars['tt_news'] = $this->tt_news_uid; $this->piVars['ADMCMD_vPrev'] = rawurlencode(serialize(array($table.':'.$t3ver_oid => $this->tt_news_uid))); $this->theCode = 'SINGLE'; $this->vPrev = true; $content = $vPrevHeader.$this->displaySingle(); } else { // error: t3ver_oid mismatch $GLOBALS['TT']->setTSlogMessage('tt_news: ERROR! The "t3ver_oid" of requested tt_news record and the "t3ver_oid" from GPvars doesn\'t match.'); } } } } } return $content;}

Page 38: Extbase and Beyond

control flow

business logic

CRUD data

other , eg. config

render output

Page 39: Extbase and Beyond

control flow

business logic

CRUD data

other , eg. config

render outputaggregate

Page 40: Extbase and Beyond

generalize

control flow

business logic

CRUD data

other , eg. config

render output

Page 41: Extbase and Beyond

partition

Page 42: Extbase and Beyond

useExtbase & Fluid

Page 43: Extbase and Beyond

control flow

business logic

CRUD data

other , eg. config

render output

Page 44: Extbase and Beyond

Controller

Domain Model

Domain Repository

other , eg. config

View

Page 45: Extbase and Beyond

TYPO3

Page 46: Extbase and Beyond

ExtbaseDispatcherTYPO3

userFunc

1

Page 47: Extbase and Beyond

ExtbaseDispatcher

Controller

Request

TYPO3

userFunc

12 BlogExample

Page 48: Extbase and Beyond

ExtbaseDispatcher

Controller

Repository

Request

findByTitle('MyBlog')

TYPO3

Domain Model

userFunc

12

3

Blog

Post

Comment Tag

BlogExample

Page 49: Extbase and Beyond

ExtbaseDispatcher

Controller

Repository

Request

findByTitle('MyBlog')

Blog

TYPO3

Domain Model

userFunc

12

3

4

Blog

Post

Comment Tag

BlogExample

Page 50: Extbase and Beyond

ExtbaseDispatcher

Controller

Repository View

Request

findByTitle('MyBlog')

Blog

assign(Blog)

TYPO3

Domain Model

render()

userFunc

12

3

4

5

Blog

Post

Comment Tag

BlogExample

Page 51: Extbase and Beyond

ExtbaseDispatcher

Controller

Repository View

Request

findByTitle('MyBlog')

Response

Blog

assign(Blog)

Response

TYPO3

Domain Model

HTML

render()

userFunc

12

3

4

5

6

Blog

Post

Comment Tag

BlogExample

Page 52: Extbase and Beyond

ExtbaseDispatcher

Controller

Repository View

Request

findByTitle('MyBlog')

Response

Blog

assign(Blog)

Response

TYPO3

Domain Model

HTML

render()

userFunc

12

3

4

5

6

Blog

Post

Comment Tag

BlogExample

Page 53: Extbase and Beyond

ExtbaseDispatcher

Controller

Repository View

Request

findByTitle('MyBlog')

Response

Blog

assign(Blog)

Response

TYPO3

Domain Model

HTML

render()

userFunc

12

3

4

5

6

Blog

Post

Comment Tag

BlogExample

View

Controller

Model

Page 54: Extbase and Beyond

Spaghetti code Lasagna code

Hmmm.Much better.

Page 55: Extbase and Beyond

What's coming

Page 56: Extbase and Beyond

PerformanceSQL queries

object trackingcaching

Page 57: Extbase and Beyond

Dev Experience

speaking exceptionsdocumentationkickstarter

Page 58: Extbase and Beyond

Catalysedispatcher

persistence backendprocess for patches

Page 59: Extbase and Beyond

And beyond Extbase?

Page 60: Extbase and Beyond

IMHO

Page 61: Extbase and Beyond

http://www.sxc.hu/photo/516864/

Generic Domain Models

Page 62: Extbase and Beyond

WRUVI

Page 63: Extbase and Beyond

William Street Rajan United States Virginia Indian

Page 64: Extbase and Beyond

William Street Rajan United States Virginia Indian

Page 65: Extbase and Beyond

William Street

Rajan

United States Virginia Indian

WRUVI

x

William Street Rajan United States Virginia Indian

Page 66: Extbase and Beyond

William Street

Rajan

United States Virginia Indian

WRUVI

x

William Street Rajan United States Virginia Indian

Page 67: Extbase and Beyond

William Street

Rajan

United States Virginia Indian

WRUVI

x

William Street Rajan United States Virginia Indian

Page 68: Extbase and Beyond
Page 69: Extbase and Beyond
Page 70: Extbase and Beyond
Page 71: Extbase and Beyond

Organization

Customer

Date

Event

Price

Invoice

Publication

Product

Article Location

NumberImage

Your Model

Page 72: Extbase and Beyond

based on high quality, open standardsOASIS CIQ 3.0 for persons, organizations, addresses, namesBMEcat for product, suppliers, catalogs, pricesiCalendar for calendar, events, datesetc.

challengesXML2PHPinteroperabilityconsistent semantics

@jochen: it's time for an example

Generic Domain Models

Page 73: Extbase and Beyond

Product Line Engineering

Page 74: Extbase and Beyond

Extbase Fluid

TYPO3 v4

ViewHelpersGeneric Domain Models

Page 75: Extbase and Beyond

Extbase Fluid

TYPO3 v4

Page 76: Extbase and Beyond

Extbase Fluid

TYPO3 v4

Page 77: Extbase and Beyond

Extbase Fluid

TYPO3 v4

Page 78: Extbase and Beyond

Extbase Fluid

TYPO3 v4

Page 79: Extbase and Beyond

FLOW3

Fluid

TYPO3 v5

ViewHelpersGeneric Domain Models

platform

Page 80: Extbase and Beyond

FLOW3

Fluid

TYPO3 v5

ViewHelpersGeneric Domain Models

building blocks

Page 81: Extbase and Beyond

FLOW3

Fluid

TYPO3 v5

ViewHelpersGeneric Domain Models

TYPO3

Page 82: Extbase and Beyond

FLOW3

Fluid

TYPO3 v5

ViewHelpersGeneric Domain Models

packagesP P P P P P P P PP

Page 83: Extbase and Beyond

FLOW3

Fluid

TYPO3 v5

ViewHelpersGeneric Domain Models

TYPO3 Social SiteP P P P P P P P PP

Page 84: Extbase and Beyond

FLOW3

Fluid

TYPO3 v5

ViewHelpersGeneric Domain Models

TYPO3 EnterprisePP P PP P P P P P

Page 85: Extbase and Beyond

FLOW3

Fluid

TYPO3 v5

ViewHelpersGeneric Domain Models

TYPO3 BlogPPPP PP PPPP

Page 86: Extbase and Beyond

FLOW3

Fluid

TYPO3 v5

ViewHelpersGeneric Domain Models

Product LinePPPP PP PPPP

Page 87: Extbase and Beyond

The meaning of things

Page 88: Extbase and Beyond
Page 89: Extbase and Beyond
Page 90: Extbase and Beyond
Page 91: Extbase and Beyond

http://webscience.org/people.html

Page 92: Extbase and Beyond
Page 93: Extbase and Beyond

Knublauch, Holger. KBeans Specification: Semantic Transparency for Components and Domain Models. Technical Report FAW-TR-01001, FAW Ulm, 2001.

Page 94: Extbase and Beyond

Semantic annotations

/** * A container for defining the unique characteristics of a person only * * @version $Id$ * @copyright Copyright belongs to the respective authors * @license http://www.gnu.org/licenses/gpl.html GNU General Public License, version 3 or later * @prefix foaf: <http://xmlns.com/foaf/0.1/> * @prefix owl: <http://www.w3.org/2002/07/owl#> * @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> * @prefix core: <http://www.typo3.org/semantic/core/> * @prefix gen: <http://www.typo3.org/semantic/ext/generic/domain/model/> * @semantic gen:Person rdfs:subClassOf gen:Party * @semantic gen:Person owl:disjointWith gen:Organization * @semantic gen:Person core:isMemberOf gen:Organization */class Tx_Generic_Domain_Model_Person extends Tx_Generic_Domain_Model_Party { /** * Party Names * @var Tx_Extbase_Persistence_ObjectStorage<Tx_Generic_Domain_Model_PersonName> * @semantic gen:partyNames gen:areOfType foaf:name */ protected $partyNames; /** * personInfo * @var Tx_Generic_Domain_Model_PersonInfo */ protected $personInfo;

Page 95: Extbase and Beyond

Semantic Query with SPARQL

## Find all authors of News Articles that are posted on a page with the english title "Welcome"PREFIX core:<http:://www.typo3.org/ontology/core/#>PREFIX generic:<http:://www.typo3.org/ontology/ext/generic/#>PREFIX rdfs:<http://www.w3.org/2000/01/rdf-schema#>SELECT $person $articleFROM <http:://localhost/repository.rdf>WHERE { $person rdfs:type generic:Person . $person core:authorOf $article . $article rdfs:type core:NewsArticle . $article core:isPlacedOn $page . $page core:title "Welcome"@en .}

Page 96: Extbase and Beyond

[TYPO3-dev] The state of support for the Semantic Web / RDFA / Web 3.0 in TYPO3Jochen Rau jochen.rau at typoplanet.de Mon Aug 31 16:26:51 CEST 2009

• Previous message: [TYPO3-dev] The state of support for the Semantic Web / RDFA / Web 3.0 in TYPO3• Next message: [TYPO3-dev] The state of support for the Semantic Web / RDFA / Web 3.0 in TYPO3• Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]

get Extbase ready ;-)de!ne generic domain modelsbind objects to an ontologyelaborate on the use cases of semantic contentmake the integration of semantic web technology a movement of the community

Page 97: Extbase and Beyond

Patrick Lobacher

Sebastian KurfürstBastian Waidelich

Ingmar Schlecht

and the TYPO3 V5 Team for all the inspiration and the beautiful code

Thank YouSteffen Kamper

Xavier Perseguers

Felix Oertel

Franz Koch

Sebastian Gebhard

Franz Ripfel