Fixed bug #6902: Add an imagespace to Text w/ Image when image width is not available...
[Packages/TYPO3.CMS.git] / typo3 / sysext / css_styled_content / pi1 / class.tx_cssstyledcontent_pi1.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 1999-2005 Kasper Skaarhoj (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 * Plugin 'Content rendering' for the 'css_styled_content' extension.
29 *
30 * $Id$
31 *
32 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
33 */
34 /**
35 * [CLASS/FUNCTION INDEX of SCRIPT]
36 *
37 *
38 *
39 * 68: class tx_cssstyledcontent_pi1 extends tslib_pibase
40 *
41 * SECTION: Rendering of Content Elements:
42 * 96: function render_bullets($content,$conf)
43 * 141: function render_table($content,$conf)
44 * 283: function render_uploads($content,$conf)
45 * 395: function render_textpic($content, $conf)
46 *
47 * SECTION: Helper functions
48 * 832: function getTableAttributes($conf,$type)
49 * 861: function &hookRequest($functionName)
50 *
51 * TOTAL FUNCTIONS: 6
52 * (This index is automatically created/updated by the extension "extdeveval")
53 *
54 */
55
56 require_once(PATH_tslib.'class.tslib_pibase.php');
57
58
59
60 /**
61 * Plugin class - instantiated from TypoScript.
62 * Rendering some content elements from tt_content table.
63 *
64 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
65 * @package TYPO3
66 * @subpackage tx_cssstyledcontent
67 */
68 class tx_cssstyledcontent_pi1 extends tslib_pibase {
69
70 // Default plugin variables:
71 var $prefixId = 'tx_cssstyledcontent_pi1'; // Same as class name
72 var $scriptRelPath = 'pi1/class.tx_cssstyledcontent_pi1.php'; // Path to this script relative to the extension dir.
73 var $extKey = 'css_styled_content'; // The extension key.
74 var $conf = array();
75
76
77
78
79
80
81
82 /***********************************
83 *
84 * Rendering of Content Elements:
85 *
86 ***********************************/
87
88 /**
89 * Rendering the "Bulletlist" type content element, called from TypoScript (tt_content.bullets.20)
90 *
91 * @param string Content input. Not used, ignore.
92 * @param array TypoScript configuration
93 * @return string HTML output.
94 * @access private
95 */
96 function render_bullets($content,$conf) {
97
98 // Look for hook before running default code for function
99 if ($hookObj = &$this->hookRequest('render_bullets')) {
100 return $hookObj->render_bullets($content,$conf);
101 } else {
102
103 // Get bodytext field content, returning blank if empty:
104 $field = (isset($conf['field']) && trim($conf['field']) ? trim($conf['field']) : 'bodytext');
105 $content = trim($this->cObj->data[$field]);
106 if (!strcmp($content,'')) return '';
107
108 // Split into single lines:
109 $lines = t3lib_div::trimExplode(chr(10),$content);
110 foreach($lines as &$val) {
111 $val = '<li>'.$this->cObj->stdWrap($val,$conf['innerStdWrap.']).'</li>';
112 }
113
114 // Set header type:
115 $type = intval($this->cObj->data['layout']);
116
117 // Compile list:
118 $out = '
119 <ul class="csc-bulletlist csc-bulletlist-'.$type.'">'.
120 implode('',$lines).'
121 </ul>';
122
123 // Calling stdWrap:
124 if ($conf['stdWrap.']) {
125 $out = $this->cObj->stdWrap($out, $conf['stdWrap.']);
126 }
127
128 // Return value
129 return $out;
130 }
131 }
132
133 /**
134 * Rendering the "Table" type content element, called from TypoScript (tt_content.table.20)
135 *
136 * @param string Content input. Not used, ignore.
137 * @param array TypoScript configuration
138 * @return string HTML output.
139 * @access private
140 */
141 function render_table($content,$conf) {
142
143 // Look for hook before running default code for function
144 if ($hookObj = &$this->hookRequest('render_table')) {
145 return $hookObj->render_table($content,$conf);
146 } else {
147 // Init FlexForm configuration
148 $this->pi_initPIflexForm();
149
150 // Get bodytext field content
151 $field = (isset($conf['field']) && trim($conf['field']) ? trim($conf['field']) : 'bodytext');
152 $content = trim($this->cObj->data[$field]);
153 if (!strcmp($content,'')) return '';
154
155 // get flexform values
156 $caption = trim(htmlspecialchars($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'acctables_caption')));
157 $summary = trim(htmlspecialchars($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'acctables_summary')));
158 $useTfoot = trim($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'acctables_tfoot'));
159 $headerPos = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'acctables_headerpos');
160 $noStyles = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'acctables_nostyles');
161 $tableClass = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'acctables_tableclass');
162
163 $delimiter = trim($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'tableparsing_delimiter','s_parsing'));
164 if ($delimiter) {
165 $delimiter = chr(intval($delimiter));
166 } else {
167 $delimiter = '|';
168 }
169 $quotedInput = trim($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'tableparsing_quote','s_parsing'));
170 if ($quotedInput) {
171 $quotedInput = chr(intval($quotedInput));
172 } else {
173 $quotedInput = '';
174 }
175
176 // generate id prefix for accessible header
177 $headerScope = ($headerPos=='top'?'col':'row');
178 $headerIdPrefix = $headerScope.$this->cObj->data['uid'].'-';
179
180 // Split into single lines (will become table-rows):
181 $rows = t3lib_div::trimExplode(chr(10),$content);
182 reset($rows);
183
184 // Find number of columns to render:
185 $cols = t3lib_div::intInRange($this->cObj->data['cols']?$this->cObj->data['cols']:count(explode($delimiter,current($rows))),0,100);
186
187 // Traverse rows (rendering the table here)
188 $rCount = count($rows);
189 foreach($rows as $k => $v) {
190 $cells = explode($delimiter,$v);
191 $newCells=array();
192 for($a=0;$a<$cols;$a++) {
193 // remove quotes if needed
194 if ($quotedInput && substr($cells[$a],0,1) == $quotedInput && substr($cells[$a],-1,1) == $quotedInput) {
195 $cells[$a] = substr($cells[$a],1,-1);
196 }
197
198 if (!strcmp(trim($cells[$a]),'')) $cells[$a]='&nbsp;';
199 $cellAttribs = ($noStyles?'':($a>0 && ($cols-1)==$a) ? ' class="td-last td-'.$a.'"' : ' class="td-'.$a.'"');
200 if (($headerPos == 'top' && !$k) || ($headerPos == 'left' && !$a)) {
201 $scope = ' scope="'.$headerScope.'"';
202 $scope .= ' id="'.$headerIdPrefix.(($headerScope=='col')?$a:$k).'"';
203
204 $newCells[$a] = '
205 <th'.$cellAttribs.$scope.'>'.$this->cObj->stdWrap($cells[$a],$conf['innerStdWrap.']).'</th>';
206 } else {
207 if (empty($headerPos)) {
208 $accessibleHeader = '';
209 } else {
210 $accessibleHeader = ' headers="'.$headerIdPrefix.(($headerScope=='col')?$a:$k).'"';
211 }
212 $newCells[$a] = '
213 <td'.$cellAttribs.$accessibleHeader.'>'.$this->cObj->stdWrap($cells[$a],$conf['innerStdWrap.']).'</td>';
214 }
215 }
216 if (!$noStyles) {
217 $oddEven = $k%2 ? 'tr-odd' : 'tr-even';
218 $rowAttribs = ($k>0 && ($rCount-1)==$k) ? ' class="'.$oddEven.' tr-last"' : ' class="'.$oddEven.' tr-'.$k.'"';
219 }
220 $rows[$k]='
221 <tr'.$rowAttribs.'>'.implode('',$newCells).'
222 </tr>';
223 }
224
225 $addTbody = 0;
226 $tableContents = '';
227 if ($caption) {
228 $tableContents .= '
229 <caption>'.$caption.'</caption>';
230 }
231 if ($headerPos == 'top' && $rows[0]) {
232 $tableContents .= '<thead>'. $rows[0] .'
233 </thead>';
234 unset($rows[0]);
235 $addTbody = 1;
236 }
237 if ($useTfoot) {
238 $tableContents .= '
239 <tfoot>'.$rows[$rCount-1].'</tfoot>';
240 unset($rows[$rCount-1]);
241 $addTbody = 1;
242 }
243 $tmpTable = implode('',$rows);
244 if ($addTbody) {
245 $tmpTable = '<tbody>'.$tmpTable.'</tbody>';
246 }
247 $tableContents .= $tmpTable;
248
249 // Set header type:
250 $type = intval($this->cObj->data['layout']);
251
252 // Table tag params.
253 $tableTagParams = $this->getTableAttributes($conf,$type);
254 if (!$noStyles) {
255 $tableTagParams['class'] = 'contenttable contenttable-'.$type.($tableClass?' '.$tableClass:'');
256 } elseif ($tableClass) {
257 $tableTagParams['class'] = $tableClass;
258 }
259
260
261 // Compile table output:
262 $out = '
263 <table '.t3lib_div::implodeAttributes($tableTagParams).($summary?' summary="'.$summary.'"':'').'>'. // Omitted xhtmlSafe argument TRUE - none of the values will be needed to be converted anyways, no need to spend processing time on that.
264 $tableContents.'
265 </table>';
266
267 // Calling stdWrap:
268 if ($conf['stdWrap.']) {
269 $out = $this->cObj->stdWrap($out, $conf['stdWrap.']);
270 }
271
272 // Return value
273 return $out;
274 }
275 }
276
277 /**
278 * Rendering the "Filelinks" type content element, called from TypoScript (tt_content.uploads.20)
279 *
280 * @param string Content input. Not used, ignore.
281 * @param array TypoScript configuration
282 * @return string HTML output.
283 * @access private
284 */
285 function render_uploads($content,$conf) {
286
287 // Look for hook before running default code for function
288 if ($hookObj = &$this->hookRequest('render_uploads')) {
289 return $hookObj->render_uploads($content,$conf);
290 } else {
291
292 $out = '';
293
294 // Set layout type:
295 $type = intval($this->cObj->data['layout']);
296
297 // Get the list of files (using stdWrap function since that is easiest)
298 $lConf = array();
299 $lConf['override.']['filelist.']['field'] = 'select_key';
300 $field = (isset($conf['field']) && trim($conf['field']) ? trim($conf['field']) : 'media');
301 $fileList = $this->cObj->stdWrap($this->cObj->data[$field],$lConf);
302
303 // Explode into an array:
304 $fileArray = t3lib_div::trimExplode(',',$fileList,1);
305
306 // If there were files to list...:
307 if (count($fileArray)) {
308
309 // Get the path from which the images came:
310 $selectKeyValues = explode('|',$this->cObj->data['select_key']);
311 $path = trim($selectKeyValues[0]) ? trim($selectKeyValues[0]) : 'uploads/media/';
312
313 // Get the descriptions for the files (if any):
314 $descriptions = t3lib_div::trimExplode(chr(10),$this->cObj->data['imagecaption']);
315
316 // Adding hardcoded TS to linkProc configuration:
317 $conf['linkProc.']['path.']['current'] = 1;
318 $conf['linkProc.']['icon'] = 1; // Always render icon - is inserted by PHP if needed.
319 $conf['linkProc.']['icon.']['wrap'] = ' | //**//'; // Temporary, internal split-token!
320 $conf['linkProc.']['icon_link'] = 1; // ALways link the icon
321 $conf['linkProc.']['icon_image_ext_list'] = ($type==2 || $type==3) ? $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'] : ''; // If the layout is type 2 or 3 we will render an image based icon if possible.
322
323 // Traverse the files found:
324 $filesData = array();
325 foreach($fileArray as $key => $fileName) {
326 $absPath = t3lib_div::getFileAbsFileName($path.$fileName);
327 if (@is_file($absPath)) {
328 $fI = pathinfo($fileName);
329 $filesData[$key] = array();
330
331 $filesData[$key]['filename'] = $fileName;
332 $filesData[$key]['path'] = $path;
333 $filesData[$key]['filesize'] = filesize($absPath);
334 $filesData[$key]['fileextension'] = strtolower($fI['extension']);
335 $filesData[$key]['description'] = trim($descriptions[$key]);
336
337 $this->cObj->setCurrentVal($path);
338 $GLOBALS['TSFE']->register['ICON_REL_PATH'] = $path.$fileName;
339 $filesData[$key]['linkedFilenameParts'] = explode('//**//',$this->cObj->filelink($fileName, $conf['linkProc.']));
340 }
341 }
342
343 // Now, lets render the list!
344 $tRows = array();
345 foreach($filesData as $key => $fileD) {
346
347 // Setting class of table row for odd/even rows:
348 $oddEven = $key%2 ? 'tr-odd' : 'tr-even';
349
350 // Render row, based on the "layout" setting
351 $tRows[]='
352 <tr class="'.$oddEven.'">'.($type>0 ? '
353 <td class="csc-uploads-icon">
354 '.$fileD['linkedFilenameParts'][0].'
355 </td>' : '').'
356 <td class="csc-uploads-fileName">
357 <p>'.$fileD['linkedFilenameParts'][1].'</p>'.
358 ($fileD['description'] ? '
359 <p class="csc-uploads-description">'.htmlspecialchars($fileD['description']).'</p>' : '').'
360 </td>'.($this->cObj->data['filelink_size'] ? '
361 <td class="csc-uploads-fileSize">
362 <p>'.t3lib_div::formatSize($fileD['filesize']).'</p>
363 </td>' : '').'
364 </tr>';
365 }
366
367 // Table tag params.
368 $tableTagParams = $this->getTableAttributes($conf,$type);
369 $tableTagParams['class'] = 'csc-uploads csc-uploads-'.$type;
370
371
372 // Compile it all into table tags:
373 $out = '
374 <table '.t3lib_div::implodeAttributes($tableTagParams).'>
375 '.implode('',$tRows).'
376 </table>';
377 }
378
379 // Calling stdWrap:
380 if ($conf['stdWrap.']) {
381 $out = $this->cObj->stdWrap($out, $conf['stdWrap.']);
382 }
383
384 // Return value
385 return $out;
386 }
387 }
388
389 /**
390 * Rendering the IMGTEXT content element, called from TypoScript (tt_content.textpic.20)
391 *
392 * @param string Content input. Not used, ignore.
393 * @param array TypoScript configuration. See TSRef "IMGTEXT". This function aims to be compatible.
394 * @return string HTML output.
395 * @access private
396 * @coauthor Ernesto Baschny <ernst@cron-it.de>
397 */
398 function render_textpic($content, $conf) {
399 // Look for hook before running default code for function
400 if (method_exists($this, 'hookRequest') && $hookObj = &$this->hookRequest('render_textpic')) {
401 return $hookObj->render_textpic($content,$conf);
402 }
403
404 $renderMethod = $this->cObj->stdWrap($conf['renderMethod'], $conf['renderMethod.']);
405
406 // Render using the default IMGTEXT code (table-based)
407 if (!$renderMethod || $renderMethod == 'table') {
408 return $this->cObj->IMGTEXT($conf);
409 }
410
411 // Specific configuration for the chosen rendering method
412 if (is_array($conf['rendering.'][$renderMethod . '.'])) {
413 $conf = $this->cObj->joinTSarrays($conf, $conf['rendering.'][$renderMethod . '.']);
414 }
415
416 // Image or Text with Image?
417 if (is_array($conf['text.'])) {
418 $content = $this->cObj->stdWrap($this->cObj->cObjGet($conf['text.'], 'text.'), $conf['text.']);
419 }
420
421 $imgList = trim($this->cObj->stdWrap($conf['imgList'], $conf['imgList.']));
422
423 if (!$imgList) {
424 // No images, that's easy
425 if (is_array($conf['stdWrap.'])) {
426 return $this->cObj->stdWrap($content, $conf['stdWrap.']);
427 }
428 return $content;
429 }
430
431 $imgs = t3lib_div::trimExplode(',', $imgList);
432 $imgStart = intval($this->cObj->stdWrap($conf['imgStart'], $conf['imgStart.']));
433 $imgCount = count($imgs) - $imgStart;
434 $imgMax = intval($this->cObj->stdWrap($conf['imgMax'], $conf['imgMax.']));
435 if ($imgMax) {
436 $imgCount = t3lib_div::intInRange($imgCount, 0, $imgMax); // reduce the number of images.
437 }
438
439 $imgPath = $this->cObj->stdWrap($conf['imgPath'], $conf['imgPath.']);
440
441 // Global caption
442 $caption = '';
443 if (!$conf['captionSplit'] && !$conf['imageTextSplit'] && is_array($conf['caption.'])) {
444 $caption = $this->cObj->stdWrap($this->cObj->cObjGet($conf['caption.'], 'caption.'), $conf['caption.']);
445 }
446
447 // Positioning
448 $position = $this->cObj->stdWrap($conf['textPos'], $conf['textPos.']);
449
450 $imagePosition = $position&7; // 0,1,2 = center,right,left
451 $contentPosition = $position&24; // 0,8,16,24 (above,below,intext,intext-wrap)
452 $align = $this->cObj->align[$imagePosition];
453 $textMargin = intval($this->cObj->stdWrap($conf['textMargin'],$conf['textMargin.']));
454 if (!$conf['textMargin_outOfText'] && $contentPosition < 16) {
455 $textMargin = 0;
456 }
457
458 $colspacing = intval($this->cObj->stdWrap($conf['colSpace'], $conf['colSpace.']));
459 $rowspacing = intval($this->cObj->stdWrap($conf['rowSpace'], $conf['rowSpace.']));
460
461 $border = intval($this->cObj->stdWrap($conf['border'], $conf['border.'])) ? 1:0;
462 $borderColor = $this->cObj->stdWrap($conf['borderCol'], $conf['borderCol.']);
463 $borderThickness = intval($this->cObj->stdWrap($conf['borderThick'], $conf['borderThick.']));
464
465 $borderColor = $borderColor?$borderColor:'black';
466 $borderThickness = $borderThickness?$borderThickness:1;
467 $borderSpace = (($conf['borderSpace']&&$border) ? intval($conf['borderSpace']) : 0);
468
469 // Generate cols
470 $cols = intval($this->cObj->stdWrap($conf['cols'],$conf['cols.']));
471 $colCount = ($cols > 1) ? $cols : 1;
472 if ($colCount > $imgCount) {$colCount = $imgCount;}
473 $rowCount = ceil($imgCount / $colCount);
474
475 // Generate rows
476 $rows = intval($this->cObj->stdWrap($conf['rows'],$conf['rows.']));
477 if ($rows>1) {
478 $rowCount = $rows;
479 if ($rowCount > $imgCount) {$rowCount = $imgCount;}
480 $colCount = ($rowCount>1) ? ceil($imgCount / $rowCount) : $imgCount;
481 }
482
483 // Max Width
484 $maxW = intval($this->cObj->stdWrap($conf['maxW'], $conf['maxW.']));
485
486 if ($contentPosition>=16) { // in Text
487 $maxWInText = intval($this->cObj->stdWrap($conf['maxWInText'],$conf['maxWInText.']));
488 if (!$maxWInText) {
489 // If maxWInText is not set, it's calculated to the 50% of the max
490 $maxW = round($maxW/100*50);
491 } else {
492 $maxW = $maxWInText;
493 }
494 }
495
496 // All columns have the same width:
497 $defaultColumnWidth = ceil(($maxW-$colspacing*($colCount-1)-$colCount*$border*($borderThickness+$borderSpace)*2)/$colCount);
498
499 // Specify the maximum width for each column
500 $columnWidths = array();
501 $colRelations = trim($this->cObj->stdWrap($conf['colRelations'],$conf['colRelations.']));
502 if (!$colRelations) {
503 // Default 1:1-proportion, all columns same width
504 for ($a=0;$a<$colCount;$a++) {
505 $columnWidths[$a] = $defaultColumnWidth;
506 }
507 } else {
508 // We need another proportion
509 $rel_parts = explode(':',$colRelations);
510 $rel_total = 0;
511 for ($a=0;$a<$colCount;$a++) {
512 $rel_parts[$a] = intval($rel_parts[$a]);
513 $rel_total+= $rel_parts[$a];
514 }
515 if ($rel_total) {
516 for ($a=0;$a<$colCount;$a++) {
517 $columnWidths[$a] = round(($defaultColumnWidth*$colCount)/$rel_total*$rel_parts[$a]);
518 }
519 if (min($columnWidths)<=0 || max($rel_parts)/min($rel_parts)>10) {
520 // The difference in size between the largest and smalles must be within a factor of ten.
521 for ($a=0;$a<$colCount;$a++) {
522 $columnWidths[$a] = $defaultColumnWidth;
523 }
524 }
525 }
526 }
527 $image_compression = intval($this->cObj->stdWrap($conf['image_compression'],$conf['image_compression.']));
528 $image_effects = intval($this->cObj->stdWrap($conf['image_effects'],$conf['image_effects.']));
529 $image_frames = intval($this->cObj->stdWrap($conf['image_frames.']['key'],$conf['image_frames.']['key.']));
530
531 // EqualHeight
532 $equalHeight = intval($this->cObj->stdWrap($conf['equalH'],$conf['equalH.']));
533 if ($equalHeight) {
534 // Initiate gifbuilder object in order to get dimensions AND calculate the imageWidth's
535 $gifCreator = t3lib_div::makeInstance('tslib_gifbuilder');
536 $gifCreator->init();
537 $relations_cols = Array();
538 for ($a=0; $a<$imgCount; $a++) {
539 $imgKey = $a+$imgStart;
540 $imgInfo = $gifCreator->getImageDimensions($imgPath.$imgs[$imgKey]);
541 $rel = $imgInfo[1] / $equalHeight; // relationship between the original height and the wished height
542 if ($rel) { // if relations is zero, then the addition of this value is omitted as the image is not expected to display because of some error.
543 $relations_cols[floor($a/$colCount)] += $imgInfo[0]/$rel; // counts the total width of the row with the new height taken into consideration.
544 }
545 }
546 }
547
548 // Fetches pictures
549 $splitArr = array();
550 $splitArr['imgObjNum'] = $conf['imgObjNum'];
551 $splitArr = $GLOBALS['TSFE']->tmpl->splitConfArray($splitArr, $imgCount);
552
553 $imageRowsFinalWidths = Array(); // contains the width of every image row
554 $imgsTag = array(); // array index of $imgsTag will be the same as in $imgs, but $imgsTag only contains the images that are actually shown
555 $origImages = array();
556 for ($a=0; $a<$imgCount; $a++) {
557 $imgKey = $a+$imgStart;
558 $totalImagePath = $imgPath.$imgs[$imgKey];
559
560 $GLOBALS['TSFE']->register['IMAGE_NUM'] = $imgKey; // register IMG_NUM is kept for backwards compatibility
561 $GLOBALS['TSFE']->register['IMAGE_NUM_CURRENT'] = $imgKey;
562 $GLOBALS['TSFE']->register['ORIG_FILENAME'] = $totalImagePath;
563
564 $this->cObj->data[$this->cObj->currentValKey] = $totalImagePath;
565 $imgObjNum = intval($splitArr[$a]['imgObjNum']);
566 $imgConf = $conf[$imgObjNum.'.'];
567
568 if ($equalHeight) {
569 $scale = 1;
570 $totalMaxW = $defaultColumnWidth*$colCount;
571 $rowTotalMaxW = $relations_cols[floor($a/$colCount)];
572 if ($rowTotalMaxW > $totalMaxW) {
573 $scale = $rowTotalMaxW / $totalMaxW;
574 }
575
576 // transfer info to the imageObject. Please note, that
577 $imgConf['file.']['height'] = round($equalHeight/$scale);
578
579 // other stuff will be calculated accordingly:
580 unset($imgConf['file.']['width']);
581 unset($imgConf['file.']['maxW']);
582 unset($imgConf['file.']['maxH']);
583 unset($imgConf['file.']['minW']);
584 unset($imgConf['file.']['minH']);
585 unset($imgConf['file.']['width.']);
586 unset($imgConf['file.']['maxW.']);
587 unset($imgConf['file.']['maxH.']);
588 unset($imgConf['file.']['minW.']);
589 unset($imgConf['file.']['minH.']);
590 } else {
591 $imgConf['file.']['maxW'] = $columnWidths[($a%$colCount)];
592 }
593
594 $titleInLink = $this->cObj->stdWrap($imgConf['titleInLink'], $imgConf['titleInLink.']);
595 $titleInLinkAndImg = $this->cObj->stdWrap($imgConf['titleInLinkAndImg'], $imgConf['titleInLinkAndImg.']);
596 $oldATagParms = $GLOBALS['TSFE']->ATagParams;
597 if ($titleInLink) {
598 // Title in A-tag instead of IMG-tag
599 $titleText = trim($this->cObj->stdWrap($imgConf['titleText'], $imgConf['titleText.']));
600 if ($titleText) {
601 // This will be used by the IMAGE call later:
602 $GLOBALS['TSFE']->ATagParams .= ' title="'. $titleText .'"';
603 }
604 }
605
606 if ($imgConf || $imgConf['file']) {
607 if ($this->cObj->image_effects[$image_effects]) {
608 $imgConf['file.']['params'] .= ' '.$this->cObj->image_effects[$image_effects];
609 }
610 if ($image_frames) {
611 if (is_array($conf['image_frames.'][$image_frames.'.'])) {
612 $imgConf['file.']['m.'] = $conf['image_frames.'][$image_frames.'.'];
613 }
614 }
615 if ($image_compression && $imgConf['file'] != 'GIFBUILDER') {
616 if ($image_compression == 1) {
617 $tempImport = $imgConf['file.']['import'];
618 $tempImport_dot = $imgConf['file.']['import.'];
619 unset($imgConf['file.']);
620 $imgConf['file.']['import'] = $tempImport;
621 $imgConf['file.']['import.'] = $tempImport_dot;
622 } elseif (isset($this->cObj->image_compression[$image_compression])) {
623 $imgConf['file.']['params'] .= ' '.$this->cObj->image_compression[$image_compression]['params'];
624 $imgConf['file.']['ext'] = $this->cObj->image_compression[$image_compression]['ext'];
625 unset($imgConf['file.']['ext.']);
626 }
627 }
628 if ($titleInLink && ! $titleInLinkAndImg) {
629 // Check if the image will be linked
630 $link = $this->cObj->imageLinkWrap('', $totalImagePath, $imgConf['imageLinkWrap.']);
631 if ($link) {
632 // Title in A-tag only (set above: ATagParams), not in IMG-tag
633 unset($imgConf['titleText']);
634 unset($imgConf['titleText.']);
635 $imgConf['emptyTitleHandling'] = 'removeAttr';
636 }
637 }
638 $imgsTag[$imgKey] = $this->cObj->IMAGE($imgConf);
639 } else {
640 $imgsTag[$imgKey] = $this->cObj->IMAGE(Array('file' => $totalImagePath)); // currentValKey !!!
641 }
642 // Restore our ATagParams
643 $GLOBALS['TSFE']->ATagParams = $oldATagParms;
644 // Store the original filepath
645 $origImages[$imgKey] = $GLOBALS['TSFE']->lastImageInfo;
646
647 if ($GLOBALS['TSFE']->lastImageInfo[0]==0) {
648 $imageRowsFinalWidths[floor($a/$colCount)] += $this->cObj->data['imagewidth'];
649 } else {
650 $imageRowsFinalWidths[floor($a/$colCount)] += $GLOBALS['TSFE']->lastImageInfo[0];
651 }
652
653 }
654 // How much space will the image-block occupy?
655 $imageBlockWidth = max($imageRowsFinalWidths)+ $colspacing*($colCount-1) + $colCount*$border*($borderSpace+$borderThickness)*2;
656 $GLOBALS['TSFE']->register['rowwidth'] = $imageBlockWidth;
657 $GLOBALS['TSFE']->register['rowWidthPlusTextMargin'] = $imageBlockWidth + $textMargin;
658
659 // noRows is in fact just one ROW, with the amount of columns specified, where the images are placed in.
660 // noCols is just one COLUMN, each images placed side by side on each row
661 $noRows = $this->cObj->stdWrap($conf['noRows'],$conf['noRows.']);
662 $noCols = $this->cObj->stdWrap($conf['noCols'],$conf['noCols.']);
663 if ($noRows) {$noCols=0;} // noRows overrides noCols. They cannot exist at the same time.
664
665 $rowCount_temp = 1;
666 $colCount_temp = $colCount;
667 if ($noRows) {
668 $rowCount_temp = $rowCount;
669 $rowCount = 1;
670 }
671 if ($noCols) {
672 $colCount = 1;
673 $columnWidths = array();
674 }
675
676 // Edit icons:
677 $editIconsHTML = $conf['editIcons']&&$GLOBALS['TSFE']->beUserLogin ? $this->cObj->editIcons('',$conf['editIcons'],$conf['editIcons.']) : '';
678
679 // If noRows, we need multiple imagecolumn wraps
680 $imageWrapCols = 1;
681 if ($noRows) { $imageWrapCols = $colCount; }
682
683 // User wants to separate the rows, but only do that if we do have rows
684 $separateRows = $this->cObj->stdWrap($conf['separateRows'], $conf['separateRows.']);
685 if ($noRows) { $separateRows = 0; }
686 if ($rowCount == 1) { $separateRows = 0; }
687
688 // Apply optionSplit to the list of classes that we want to add to each image
689 $addClassesImage = $conf['addClassesImage'];
690 if ($conf['addClassesImage.']) {
691 $addClassesImage = $this->cObj->stdWrap($addClassesImage, $conf['addClassesImage.']);
692 }
693 $addClassesImageConf = $GLOBALS['TSFE']->tmpl->splitConfArray(array('addClassesImage' => $addClassesImage), $colCount);
694
695 // Render the images
696 $images = '';
697 for ($c = 0; $c < $imageWrapCols; $c++) {
698 $tmpColspacing = $colspacing;
699 if (($c==$imageWrapCols-1 && $imagePosition==2) || ($c==0 && ($imagePosition==1||$imagePosition==0))) {
700 // Do not add spacing after column if we are first column (left) or last column (center/right)
701 $tmpColspacing = 0;
702 }
703
704 $thisImages = '';
705 $allRows = '';
706 $maxImageSpace = 0;
707 for ($i = $c; $i<count($imgsTag); $i=$i+$imageWrapCols) {
708 $imgKey = $i+$imgStart;
709 $colPos = $i%$colCount;
710 if ($separateRows && $colPos == 0) {
711 $thisRow = '';
712 }
713
714 // Render one image
715 if($origImages[$imgKey][0]==0) {
716 $imageSpace=$this->cObj->data['imagewidth'] + $border*($borderSpace+$borderThickness)*2;
717 } else {
718 $imageSpace = $origImages[$imgKey][0] + $border*($borderSpace+$borderThickness)*2;
719 }
720
721 $GLOBALS['TSFE']->register['IMAGE_NUM'] = $imgKey;
722 $GLOBALS['TSFE']->register['IMAGE_NUM_CURRENT'] = $imgKey;
723 $GLOBALS['TSFE']->register['ORIG_FILENAME'] = $origImages[$imgKey]['origFile'];
724 $GLOBALS['TSFE']->register['imagewidth'] = $origImages[$imgKey][0];
725 $GLOBALS['TSFE']->register['imagespace'] = $imageSpace;
726 $GLOBALS['TSFE']->register['imageheight'] = $origImages[$imgKey][1];
727 if ($imageSpace > $maxImageSpace) {
728 $maxImageSpace = $imageSpace;
729 }
730 $thisImage = '';
731 $thisImage .= $this->cObj->stdWrap($imgsTag[$imgKey], $conf['imgTagStdWrap.']);
732
733 if ($conf['captionSplit'] || $conf['imageTextSplit']) {
734 $thisImage .= $this->cObj->stdWrap($this->cObj->cObjGet($conf['caption.'], 'caption.'), $conf['caption.']);
735 }
736 if ($editIconsHTML) {
737 $thisImage .= $this->cObj->stdWrap($editIconsHTML, $conf['editIconsStdWrap.']);
738 }
739 $thisImage = $this->cObj->stdWrap($thisImage, $conf['oneImageStdWrap.']);
740 $classes = '';
741 if ($addClassesImageConf[$colPos]['addClassesImage']) {
742 $classes = ' ' . $addClassesImageConf[$colPos]['addClassesImage'];
743 }
744 $thisImage = str_replace('###CLASSES###', $classes, $thisImage);
745
746 if ($separateRows) {
747 $thisRow .= $thisImage;
748 } else {
749 $allRows .= $thisImage;
750 }
751 $GLOBALS['TSFE']->register['columnwidth'] = $maxImageSpace + $tmpColspacing;
752
753
754 // Close this row at the end (colCount), or the last row at the final end
755 if ($separateRows && ($i+1 == count($imgsTag))) {
756 // Close the very last row with either normal configuration or lastRow stdWrap
757 $allRows .= $this->cObj->stdWrap($thisRow, (is_array($conf['imageLastRowStdWrap.']) ? $conf['imageLastRowStdWrap.'] : $conf['imageRowStdWrap.']));
758 } elseif ($separateRows && $colPos == $colCount-1) {
759 $allRows .= $this->cObj->stdWrap($thisRow, $conf['imageRowStdWrap.']);
760 }
761 }
762 if ($separateRows) {
763 $thisImages .= $allRows;
764 } else {
765 $thisImages .= $this->cObj->stdWrap($allRows, $conf['noRowsStdWrap.']);
766 }
767 if ($noRows) {
768 // Only needed to make columns, rather than rows:
769 $images .= $this->cObj->stdWrap($thisImages, $conf['imageColumnStdWrap.']);
770 } else {
771 $images .= $thisImages;
772 }
773 }
774
775 // Add the global caption, if not split
776 if ($caption) {
777 $images .= $caption;
778 }
779
780 // CSS-classes
781 $captionClass = '';
782 $classCaptionAlign = array(
783 'center' => 'csc-textpic-caption-c',
784 'right' => 'csc-textpic-caption-r',
785 'left' => 'csc-textpic-caption-l',
786 );
787 $captionAlign = $this->cObj->stdWrap($conf['captionAlign'], $conf['captionAlign.']);
788 if ($captionAlign) {
789 $captionClass = $classCaptionAlign[$captionAlign];
790 }
791 $borderClass = '';
792 if ($border) {
793 $borderClass = 'csc-textpic-border';
794 }
795
796 // Multiple classes with all properties, to be styled in CSS
797 $class = '';
798 $class .= ($borderClass? ' '.$borderClass:'');
799 $class .= ($captionClass? ' '.$captionClass:'');
800 $class .= ($equalHeight? ' csc-textpic-equalheight':'');
801 $addClasses = $this->cObj->stdWrap($conf['addClasses'], $conf['addClasses.']);
802 $class .= ($addClasses ? ' '.$addClasses:'');
803
804 // Do we need a width in our wrap around images?
805 $imgWrapWidth = '';
806 if ($position == 0 || $position == 8) {
807 // For 'center' we always need a width: without one, the margin:auto trick won't work
808 $imgWrapWidth = $imageBlockWidth;
809 }
810 if ($rowCount > 1) {
811 // For multiple rows we also need a width, so that the images will wrap
812 $imgWrapWidth = $imageBlockWidth;
813 }
814 if ($caption) {
815 // If we have a global caption, we need the width so that the caption will wrap
816 $imgWrapWidth = $imageBlockWidth;
817 }
818
819 // Wrap around the whole image block
820 $GLOBALS['TSFE']->register['totalwidth'] = $imgWrapWidth;
821 if ($imgWrapWidth) {
822 $images = $this->cObj->stdWrap($images, $conf['imageStdWrap.']);
823 } else {
824 $images = $this->cObj->stdWrap($images, $conf['imageStdWrapNoWidth.']);
825 }
826
827 $output = $this->cObj->cObjGetSingle($conf['layout'], $conf['layout.']);
828 $output = str_replace('###TEXT###', $content, $output);
829 $output = str_replace('###IMAGES###', $images, $output);
830 $output = str_replace('###CLASSES###', $class, $output);
831
832 if ($conf['stdWrap.']) {
833 $output = $this->cObj->stdWrap($output, $conf['stdWrap.']);
834 }
835
836 return $output;
837 }
838
839
840
841
842
843
844
845
846
847
848
849
850 /************************************
851 *
852 * Helper functions
853 *
854 ************************************/
855
856 /**
857 * Returns table attributes for uploads / tables.
858 *
859 * @param array TypoScript configuration array
860 * @param integer The "layout" type
861 * @return array Array with attributes inside.
862 */
863 function getTableAttributes($conf,$type) {
864
865 // Initializing:
866 $tableTagParams_conf = $conf['tableParams_'.$type.'.'];
867
868 $conf['color.'][200] = '';
869 $conf['color.'][240] = 'black';
870 $conf['color.'][241] = 'white';
871 $conf['color.'][242] = '#333333';
872 $conf['color.'][243] = 'gray';
873 $conf['color.'][244] = 'silver';
874
875 // Create table attributes array:
876 $tableTagParams = array();
877 $tableTagParams['border'] = $this->cObj->data['table_border'] ? intval($this->cObj->data['table_border']) : $tableTagParams_conf['border'];
878 $tableTagParams['cellspacing'] = $this->cObj->data['table_cellspacing'] ? intval($this->cObj->data['table_cellspacing']) : $tableTagParams_conf['cellspacing'];
879 $tableTagParams['cellpadding'] = $this->cObj->data['table_cellpadding'] ? intval($this->cObj->data['table_cellpadding']) : $tableTagParams_conf['cellpadding'];
880 $tableTagParams['bgcolor'] = isset($conf['color.'][$this->cObj->data['table_bgColor']]) ? $conf['color.'][$this->cObj->data['table_bgColor']] : $conf['color.']['default'];
881
882 // Return result:
883 return $tableTagParams;
884 }
885
886 /**
887 * Returns an object reference to the hook object if any
888 *
889 * @param string Name of the function you want to call / hook key
890 * @return object Hook object, if any. Otherwise null.
891 */
892 function &hookRequest($functionName) {
893 global $TYPO3_CONF_VARS;
894
895 // Hook: menuConfig_preProcessModMenu
896 if ($TYPO3_CONF_VARS['EXTCONF']['css_styled_content']['pi1_hooks'][$functionName]) {
897 $hookObj = &t3lib_div::getUserObj($TYPO3_CONF_VARS['EXTCONF']['css_styled_content']['pi1_hooks'][$functionName]);
898 if (method_exists ($hookObj, $functionName)) {
899 $hookObj->pObj = &$this;
900 return $hookObj;
901 }
902 }
903 }
904 }
905
906
907
908 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/css_styled_content/pi1/class.tx_cssstyledcontent_pi1.php']) {
909 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/css_styled_content/pi1/class.tx_cssstyledcontent_pi1.php']);
910 }
911 ?>