d8f97810288164fb46739b22450927dd8bda74a6
[Packages/TYPO3.CMS.git] / typo3 / sysext / statictemplates / media / scripts / wapversionLib.inc
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 1999-2009 Kasper Skårhøj (kasperYYYY@typo3.com)
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 * A copy is found in the textfile GPL.txt and important notices to the license
17 * from the author is found in LICENSE.txt distributed with these scripts.
18 *
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27 /**
28 * Contains class for creating WAP pages for TYPO3
29 *
30 * Revised for TYPO3 3.6 June/2003 by Kasper Skårhøj
31 *
32 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
33 */
34 /**
35 * Class that creates the current page and content element records as an WML structure using the library "t3lib_xml"
36 * It is demonstrated in use in the testsite package on page "59"
37 * The static template "plugin.alt.wap" is used to trigger this WML creation as well. That template contains this set of TypoScript lines which triggers the WML creation and disables all regular HTML headers
38 *
39 * ## Set up page/type:
40 * alt_wap >
41 * alt_wap = PAGE
42 * alt_wap {
43 * typeNum=97
44 * config.disableAllHeaderCode = 1
45 * config.additionalHeaders = Content-type: text/vnd.wap.wml
46 *
47 * ## Includes the newsLib:
48 * includeLibs.alt_wap = media/scripts/wapversionLib.inc
49 *
50 * ## Inserting the USER cObject for WAP/XML rendering
51 * 10 = USER
52 * 10 {
53 * userFunc = user_wapversion->main_wapversion
54 * debug=0
55 * preTitle = T3WAP
56 * navLabels.prev = Prev
57 * navLabels.next = Next
58 * navLabels.up = Up
59 * }
60 * }
61 *
62 * NOTICE:
63 *
64 * In the static template "plugin.alt.wap" there is a part in the end looking like this:
65 *
66 * ## If the browser is a WAP-device,
67 * [device=wap]
68 * alt_wap.typeNum=0
69 * [global]
70 *
71 * This means that IF the device coming to the URL is a WAP device they will get wap content even if they don't specify "&type=97" since the typeNum is changed to zero here!
72 * In fact they CANNOT get any wap-content at "&type=97" anymore! This has been a source of error and confusion for many people
73 *
74 * @package TYPO3
75 * @subpackage tslib
76 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
77 */
78 class user_wapversion {
79 var $cObj; // The backReference to the mother cObj object set at call time
80
81 var $idx=0;
82
83 /**
84 * Main function, called from TypoScript
85 *
86 * @param string Empty, ignore.
87 * @param array TypoScript properties for this content object/function call
88 * @return string WML content
89 */
90 function main_wapversion($content, $conf) {
91 $GLOBALS['TSFE']->set_no_cache();
92
93 $xmlObj = t3lib_div::makeInstance('t3lib_xml', 'wml');
94 $xmlObj->XMLdebug=$conf['debug'];
95
96 // Creating top level object
97 $xmlObj->WAPHeader();
98
99 // Creating back button:
100 $xmlObj->WAPback();
101
102 $pageRec = $GLOBALS['TSFE']->page;
103 if ($GLOBALS['TSFE']->idParts[1]) {
104 // Creating content card:
105 $xmlObj->newLevel('card',1,array(
106 'id' => 'content',
107 'title' => ($conf['preTitle']?$conf['preTitle'].': ':'').$pageRec['title']
108 ));
109
110 $cParts = $this->contentAll();
111 $pointer = t3lib_utility_Math::forceIntegerInRange($GLOBALS['TSFE']->idParts[1], 1, 10000);
112
113 $msg = '';
114 if ($pointer - 1) {
115 $msg .= $this->navLink(htmlspecialchars($conf['navLabels.']['prev']), $pointer - 1) . ' ';
116 }
117 $msg .= $this->navLink(htmlspecialchars($conf['navLabels.']['up']), 0) . ' ';
118 if ($pointer<count($cParts)) {
119 $msg .= $this->navLink(htmlspecialchars($conf['navLabels.']['next']), $pointer + 1) . ' ';
120 }
121 $msg.= '['.$pointer.'/'.count($cParts).']<br/>';
122
123 $xmlObj->lines[] = $this->paragraph($msg);
124 $xmlObj->lines[] = $this->paragraph($cParts[$pointer-1]);
125 $xmlObj->lines[] = $this->paragraph('<br/>'.$msg);
126
127 $xmlObj->newLevel('card', 0);
128 } else {
129 // Creating menu card:
130 $xmlObj->newLevel('card',1,array(
131 'id' => 'menu',
132 'title' => ($conf['preTitle']?$conf['preTitle'].': ':'').$pageRec['title']
133 ));
134 $xmlObj->lines[] = $this->contentAbstract();
135 $xmlObj->lines[] = '<p><br/>'.$this->bold('Menu:').'</p>';
136 $xmlObj->lines[] = $this->menuCurrentLevel($xmlObj->Icode);
137 $xmlObj->newLevel('card', 0);
138 }
139
140 // Footer
141 $xmlObj->renderFooter();
142 return $xmlObj->getResult();
143
144 }
145
146 /**
147 * Getting abstract of the first content elements header and bodytext for the menu
148 *
149 * @return string WML string
150 */
151 function contentAbstract() {
152 $res = $this->getContentResult('tt_content');
153 $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
154 $out = $this->bold(t3lib_div::fixed_lgd_cs(htmlspecialchars($row['header']), 20)) . '<br/>';
155 $out.= t3lib_div::fixed_lgd_cs(htmlspecialchars($row['bodytext']), 50);
156 $out = '<p>' . $out . ' <a href="' . htmlspecialchars('?id=' . $GLOBALS['TSFE']->id . ',1.' . $GLOBALS['TSFE']->type) . '">[more]</a></p>';
157 return $out;
158 }
159
160 /**
161 * Returns all page content, but in an array where the content is divided into chunks or a max length (for WAP clients with limited memory capabilities)
162 * Content is then displayed using the pointer value found in $GLOBALS['TSFE']->idParts[1], see main_wapversion()
163 *
164 * @param integer Max length of each content chunk
165 * @return array Array with the page content divided into chucks WML code (default length equals $chunkLgd; 850)
166 * @see main_wapversion()
167 */
168 function contentAll($chunkLgd=850) {
169 $res = $this->getContentResult('tt_content');
170 $overlap=5;
171 $idx=0;
172 $out=array();
173 while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
174 // Header:
175 $get = '<br/>'.$this->cHeader($row['header']).'<br/>';
176 if (strlen($out[$idx].$get)>$chunkLgd) {
177 $idx++;
178 }
179 $out[$idx].=$get;
180
181 switch($row['CType']) {
182 case 'text':
183 case 'bullets':
184 case 'table':
185 $bodyText = $row['bodytext'];
186 break;
187 case 'textpic':
188 case 'image':
189 if ($row['CType']!='image') {$bodyText = $row['bodytext'];}
190 $bodyText .= chr(10) . '[' . count(explode(',', $row['image'])) . 'images, caption: ' . $row['imagecaption'] . ']';
191 break;
192 case 'header':
193 $bodyText=$row['subheader'];
194 break;
195 default:
196 $bodyText = '[Un-rendered element, '.$row['CType'].']';
197 break;
198 }
199
200 // Bodytext:
201 $get = $this->cBodytext($bodyText).'<br/>';
202 $diff = $chunkLgd - strlen($out[$idx]);
203
204 if ($diff>strlen($get)) {
205 $out[$idx].=$get;
206 } else {
207 $out[$idx] .= $this->cBodytext($bodyText, 0, $diff + $overlap) . '<br/>';
208
209 $safe=0;
210 do {
211 $idx++;
212 $out[$idx] .= $this->cBodytext($bodyText, $diff + ($safe * $chunkLgd) - $overlap, $chunkLgd + $overlap) . '<br/>';
213 $safe++;
214 if ($safe>100) break;
215 } while (strlen($out[$idx])>$chunkLgd);
216 }
217 }
218 return $out;
219 }
220
221 /**
222 * Formats the header for a content element
223 *
224 * @param string Header value to format
225 * @return string Returns the formatted version, stripped from tags and htmlspecialchar()'ed
226 * @see contentAll()
227 */
228 function cHeader($str) {
229 $out = $this->bold(htmlspecialchars(strip_tags($str)));
230 return $out;
231 }
232
233 /**
234 * Formats the bodytext for a content element
235 *
236 * @param string The bodytext content
237 * @param integer Position where to start in the bodytext stream. If larger than zero a prefix, "...", is prepended.
238 * @param integer Max length
239 * @return string Prepared content
240 * @see contentAll()
241 */
242 function cBodytext($str, $start = 0, $max = 0) {
243 $out = t3lib_div::fixed_lgd_cs(($start? '...' : '') . substr($this->nl2br(htmlspecialchars(strip_tags($str))), $start), ($max ? $max : 100000));
244 // No & in WAP docs??? --> or maybe just htmlspecialchar() things as the LAST thing instead!)
245 $out = str_replace('&', '', $out);
246 return $out;
247 }
248
249 /**
250 * Local version of ml2br(). Replaces linebreaks with <br/> tags.
251 *
252 * @param string The input string to process
253 * @return string The processed value returned.
254 */
255 function nl2br($str) {
256 return str_replace(chr(10), '<br/>', $str);
257 }
258
259 /**
260 * Selects all records from $table having the current page id as PID (records belonging to that page)
261 * Used to select content elements from "tt_content"
262 *
263 * @param string A tablename found in $GLOBALS['TCA']
264 * @return pointer A database resource pointer
265 */
266 function getContentResult($table) {
267 if ($GLOBALS['TCA'][$table]) {
268 $orderBy = ($GLOBALS['TCA'][$table]['ctrl']['sortby']
269 ? 'ORDER BY ' . $GLOBALS['TCA'][$table]['ctrl']['sortby']
270 : $GLOBALS['TCA'][$table]['ctrl']['default_sortby']);
271 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $table, 'pid='.intval($GLOBALS['TSFE']->id).$this->cObj->enableFields($table), '', $GLOBALS['TYPO3_DB']->stripOrderBy($orderBy));
272 return $res;
273 }
274 }
275
276 /**
277 * Simulates bold type - basically setting it in uppercase
278 *
279 * @param string The string for format in "bold" (uppercase)
280 * @return string Processed output.
281 */
282 function bold($str) {
283 return strtoupper($str);
284 }
285
286 /**
287 * Wraps a string in <p>...</p> tags
288 *
289 * @param string The input string
290 * @return string The wrapped string
291 */
292 function paragraph($str) {
293 return '<p>'.$str.'</p>';
294 }
295
296 /**
297 * Adds a linebreak character to the end of $str
298 *
299 * @param string The string/line
300 * @return string The input string with '<br/>' prepended
301 */
302 function line($str) {
303 return $str.'<br/>';
304 }
305
306 /**
307 * Creates a navigation link to the next part of the page content!
308 *
309 * @param string The link text
310 * @param integer The pointer value
311 * @return string The input string, linked with the pointer value to the current page.
312 */
313 function navLink($str, $pointer) {
314 return '<a href="' . htmlspecialchars('?id=' . $GLOBALS['TSFE']->id . ',' . $pointer . '.' . $GLOBALS['TSFE']->type) . '">' . $str . '</a>';
315 }
316
317 /**
318 * Creates a menu for the current pagelevel. Navigation is both a path-menu (rootline) and a menu of current page subpages.
319 *
320 * @param string Indentation prefix string per menu item.
321 * @return string A paragraph with the menu items inside.
322 */
323 function menuCurrentLevel($indent) {
324 $rL = $GLOBALS['TSFE']->config['rootLine'];
325 $preSpace='';
326 $out=array();
327 // Hierarchy menu
328 foreach ($rL as $level => $data) {
329 $preSign = count($rL)-1 > $level ? '-' : '>';
330 $menuItem = htmlspecialchars($preSign.' '.$data['title']);
331 $menuItem = $this->link($preSpace . $menuItem, $data['uid']);
332 $out[] = $indent . $this->line($menuItem);
333 $preSpace.='..';
334 }
335 // Current page menu:
336 $menu = $this->cleanMenuArray($GLOBALS['TSFE']->sys_page->getMenu($GLOBALS['TSFE']->id));
337 foreach ($menu as $data) {
338 $preSign = count($this->cleanMenuArray($GLOBALS['TSFE']->sys_page->getMenu($data['uid']))) ? '+' : '*';
339 $menuItem = htmlspecialchars($preSign.' '.$data['title']);
340 $menuItem = $this->link($preSpace . $menuItem, $data['uid']);
341 $out[] = $indent . $this->line($menuItem);
342 }
343 return $this->paragraph(implode(chr(10), $out));
344 }
345
346 /**
347 * Creates a link around the input string to another page/deck
348 * Used to create menus
349 *
350 * @param string The string to be wrapped in <a> tags
351 * @param integer The page id to link to
352 * @param string The deck name, if any
353 * @return string String wrapped in <a> tags
354 * @see menuCurrentLevel()
355 */
356 function link($str, $id, $deck = '') {
357 if ($GLOBALS['TSFE']->id==$id && $deck) {
358 $out = '<a href="#'.$deck.'">'.$str.'</a>';
359 } else {
360 $type = $GLOBALS['TSFE']->type;
361 $out = '<a href="' . htmlspecialchars('?id=' . $id . ',' . ($GLOBALS['TSFE']->id == $id ? 1 : $this->idx) . '.' . $type) . '">' . $str . '</a>';
362 }
363 return $out;
364 }
365
366 /**
367 * Cleaning up the menu array returned from sys_page->getMenu(). Removing page types with doktype "5" (not in menu)
368 *
369 * @param array Menu item array
370 * @return array New menu item array with doktype-5 elements removed.
371 */
372 function cleanMenuArray($menu) {
373 $newMenu=array();
374 foreach ($menu as $data) {
375 if (!$data['nav_hide']) {
376 $newMenu[]=$data;
377 }
378 }
379 return $newMenu;
380 }
381 }
382
383
384 // AND HERE just some debugging content: Basically a valid WML deck.
385
386 /*
387 switch($id) {
388 case 1:
389 <wml>
390 <card id="Hallo" ontimer="#Login" title="wapportal.dk">
391 <timer value="35"/>
392 <p>
393 <img src="/images/logo.wbmp" alt="WAPPORTAL"/>
394 asf asdf asdf
395 </p>
396 </card>
397 <card id="Login" title="wapportal.dk" newcontext="true">
398 <p>Mobil nr:
399 <input name="Login" title="Mobil nr:" value="" format="*N" size="15"/>Kodeord:
400 <input name="Passwd" title="Kodeord:" value="" type="password" format="*N" size="12"/>
401 <anchor>Login !<go href="/wap/portal/DeckPortal/menu.wml?sid=FGBNRru&amp;rnd=107915&amp;login=$(Login:u)&amp;pwd=$(Passwd:u)"/></anchor>
402 <br/>
403 <anchor>G&#xe6;st<go href="/wap/portal/DeckPortal/menu.wml?sid=FGBNRru&amp;rnd=107916&amp;login=visitor&amp;pwd=visitor"></go></anchor>
404 </p>
405 </card>
406 </wml>
407 break;
408 default:
409 <wml>
410 <template>
411 <do type="accept" label="Back"><prev/></do>
412 </template>
413 <card id="index1" title="Hovedside">
414 <p>Hej Kasper.
415 Dette er noget
416 <img src="/images/logo.wbmp" alt="WAPPORTAL"/>
417 tekst.</p>
418
419 </card>
420 </wml>
421 break;
422 }
423 */
424
425
426
427
428 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['media/scripts/wapversionLib.inc'])) {
429 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['media/scripts/wapversionLib.inc']);
430 }
431
432
433 ?>