[BUGFIX] Invalid "unequal"-statement and string-quoting in SQL
[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-2011 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 * Plugin 'Content rendering' for the 'css_styled_content' extension.
29 *
30 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
31 */
32 /**
33 * Plugin class - instantiated from TypoScript.
34 * Rendering some content elements from tt_content table.
35 *
36 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
37 * @package TYPO3
38 * @subpackage tx_cssstyledcontent
39 */
40 class tx_cssstyledcontent_pi1 extends tslib_pibase {
41
42 // Default plugin variables:
43 var $prefixId = 'tx_cssstyledcontent_pi1'; // Same as class name
44 var $scriptRelPath = 'pi1/class.tx_cssstyledcontent_pi1.php'; // Path to this script relative to the extension dir.
45 var $extKey = 'css_styled_content'; // The extension key.
46 var $conf = array();
47
48
49
50
51
52
53
54 /***********************************
55 *
56 * Rendering of Content Elements:
57 *
58 ***********************************/
59
60 /**
61 * Rendering the "Bulletlist" type content element, called from TypoScript (tt_content.bullets.20)
62 *
63 * @param string Content input. Not used, ignore.
64 * @param array TypoScript configuration
65 * @return string HTML output.
66 * @access private
67 */
68 function render_bullets($content,$conf) {
69
70 // Look for hook before running default code for function
71 if ($hookObj = $this->hookRequest('render_bullets')) {
72 return $hookObj->render_bullets($content,$conf);
73 } else {
74
75 // Get bodytext field content, returning blank if empty:
76 $field = (isset($conf['field']) && trim($conf['field']) ? trim($conf['field']) : 'bodytext');
77 $content = trim($this->cObj->data[$field]);
78 if (!strcmp($content,'')) return '';
79
80 // Split into single lines:
81 $lines = t3lib_div::trimExplode(LF,$content);
82 foreach($lines as &$val) {
83 $val = '<li>'.$this->cObj->stdWrap($val,$conf['innerStdWrap.']).'</li>';
84 }
85 unset($val);
86
87 // Set header type:
88 $type = intval($this->cObj->data['layout']);
89
90 // Compile list:
91 $out = '
92 <ul class="csc-bulletlist csc-bulletlist-'.$type.'">'.
93 implode('',$lines).'
94 </ul>';
95
96 // Calling stdWrap:
97 if ($conf['stdWrap.']) {
98 $out = $this->cObj->stdWrap($out, $conf['stdWrap.']);
99 }
100
101 // Return value
102 return $out;
103 }
104 }
105
106 /**
107 * Rendering the "Table" type content element, called from TypoScript (tt_content.table.20)
108 *
109 * @param string Content input. Not used, ignore.
110 * @param array TypoScript configuration
111 * @return string HTML output.
112 * @access private
113 */
114 function render_table($content,$conf) {
115
116 // Look for hook before running default code for function
117 if ($hookObj = $this->hookRequest('render_table')) {
118 return $hookObj->render_table($content,$conf);
119 } else {
120 // Init FlexForm configuration
121 $this->pi_initPIflexForm();
122
123 // Get bodytext field content
124 $field = (isset($conf['field']) && trim($conf['field']) ? trim($conf['field']) : 'bodytext');
125 $content = trim($this->cObj->data[$field]);
126 if (!strcmp($content,'')) return '';
127
128 // get flexform values
129 $caption = trim(htmlspecialchars($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'acctables_caption')));
130 $useTfoot = trim($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'acctables_tfoot'));
131 $headerPos = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'acctables_headerpos');
132 $noStyles = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'acctables_nostyles');
133 $tableClass = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'acctables_tableclass');
134
135 $delimiter = trim($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'tableparsing_delimiter','s_parsing'));
136 if ($delimiter) {
137 $delimiter = chr(intval($delimiter));
138 } else {
139 $delimiter = '|';
140 }
141 $quotedInput = trim($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'tableparsing_quote','s_parsing'));
142 if ($quotedInput) {
143 $quotedInput = chr(intval($quotedInput));
144 } else {
145 $quotedInput = '';
146 }
147
148 // generate id prefix for accessible header
149 $headerScope = ($headerPos=='top'?'col':'row');
150 $headerIdPrefix = $headerScope.$this->cObj->data['uid'].'-';
151
152 // Split into single lines (will become table-rows):
153 $rows = t3lib_div::trimExplode(LF,$content);
154 reset($rows);
155
156 // Find number of columns to render:
157 $cols = t3lib_utility_Math::forceIntegerInRange($this->cObj->data['cols']?$this->cObj->data['cols']:count(explode($delimiter,current($rows))),0,100);
158
159 // Traverse rows (rendering the table here)
160 $rCount = count($rows);
161 foreach($rows as $k => $v) {
162 $cells = explode($delimiter,$v);
163 $newCells=array();
164 for($a=0;$a<$cols;$a++) {
165 // remove quotes if needed
166 if ($quotedInput && substr($cells[$a],0,1) == $quotedInput && substr($cells[$a],-1,1) == $quotedInput) {
167 $cells[$a] = substr($cells[$a],1,-1);
168 }
169
170 if (!strcmp(trim($cells[$a]),'')) $cells[$a]='&nbsp;';
171 $cellAttribs = ($noStyles?'':($a>0 && ($cols-1)==$a) ? ' class="td-last td-'.$a.'"' : ' class="td-'.$a.'"');
172 if (($headerPos == 'top' && !$k) || ($headerPos == 'left' && !$a)) {
173 $scope = ' scope="'.$headerScope.'"';
174 $scope .= ' id="'.$headerIdPrefix.(($headerScope=='col')?$a:$k).'"';
175
176 $newCells[$a] = '
177 <th'.$cellAttribs.$scope.'>'.$this->cObj->stdWrap($cells[$a],$conf['innerStdWrap.']).'</th>';
178 } else {
179 if (empty($headerPos)) {
180 $accessibleHeader = '';
181 } else {
182 $accessibleHeader = ' headers="'.$headerIdPrefix.(($headerScope=='col')?$a:$k).'"';
183 }
184 $newCells[$a] = '
185 <td'.$cellAttribs.$accessibleHeader.'>'.$this->cObj->stdWrap($cells[$a],$conf['innerStdWrap.']).'</td>';
186 }
187 }
188 if (!$noStyles) {
189 $oddEven = $k%2 ? 'tr-odd' : 'tr-even';
190 $rowAttribs = ($k>0 && ($rCount-1)==$k) ? ' class="'.$oddEven.' tr-last"' : ' class="'.$oddEven.' tr-'.$k.'"';
191 }
192 $rows[$k]='
193 <tr'.$rowAttribs.'>'.implode('',$newCells).'
194 </tr>';
195 }
196
197 $addTbody = 0;
198 $tableContents = '';
199 if ($caption) {
200 $tableContents .= '
201 <caption>'.$caption.'</caption>';
202 }
203 if ($headerPos == 'top' && $rows[0]) {
204 $tableContents .= '<thead>'. $rows[0] .'
205 </thead>';
206 unset($rows[0]);
207 $addTbody = 1;
208 }
209 if ($useTfoot) {
210 $tableContents .= '
211 <tfoot>'.$rows[$rCount-1].'</tfoot>';
212 unset($rows[$rCount-1]);
213 $addTbody = 1;
214 }
215 $tmpTable = implode('',$rows);
216 if ($addTbody) {
217 $tmpTable = '<tbody>'.$tmpTable.'</tbody>';
218 }
219 $tableContents .= $tmpTable;
220
221 // Set header type:
222 $type = intval($this->cObj->data['layout']);
223
224 // Table tag params.
225 $tableTagParams = $this->getTableAttributes($conf,$type);
226 if (!$noStyles) {
227 $tableTagParams['class'] = 'contenttable contenttable-' . $type .
228 ($tableClass ? ' ' . $tableClass : '') . $tableTagParams['class'];
229 } elseif ($tableClass) {
230 $tableTagParams['class'] = $tableClass;
231 }
232
233
234 // Compile table output:
235 $out = '
236 <table ' . t3lib_div::implodeAttributes($tableTagParams) . '>' .
237 $tableContents . '
238 </table>';
239
240 // Calling stdWrap:
241 if ($conf['stdWrap.']) {
242 $out = $this->cObj->stdWrap($out, $conf['stdWrap.']);
243 }
244
245 // Return value
246 return $out;
247 }
248 }
249
250 /**
251 * Rendering the "Filelinks" type content element, called from TypoScript (tt_content.uploads.20)
252 *
253 * @param string Content input. Not used, ignore.
254 * @param array TypoScript configuration
255 * @return string HTML output.
256 * @access private
257 */
258 function render_uploads($content,$conf) {
259
260 // Look for hook before running default code for function
261 if ($hookObj = $this->hookRequest('render_uploads')) {
262 return $hookObj->render_uploads($content,$conf);
263 } else {
264 // Loading language-labels
265 $this->pi_loadLL();
266
267 $out = '';
268
269 // Set layout type:
270 $type = intval($this->cObj->data['layout']);
271
272 // see if the file path variable is set, this takes precedence
273 $filePathConf = $this->cObj->stdWrap($conf['filePath'], $conf['filePath.']);
274 if ($filePathConf) {
275 $fileList = $this->cObj->filelist($filePathConf);
276 list($path) = explode('|', $filePathConf);
277 } else {
278 // Get the list of files from the field
279 $field = (trim($conf['field']) ? trim($conf['field']) : 'media');
280 $fileList = $this->cObj->data[$field];
281 t3lib_div::loadTCA('tt_content');
282 $path = 'uploads/media/';
283 if (is_array($GLOBALS['TCA']['tt_content']['columns'][$field]) && !empty($GLOBALS['TCA']['tt_content']['columns'][$field]['config']['uploadfolder'])) {
284 // in TCA-Array folders are saved without trailing slash, so $path.$fileName won't work
285 $path = $GLOBALS['TCA']['tt_content']['columns'][$field]['config']['uploadfolder'] .'/';
286 }
287 }
288 $path = trim($path);
289
290 // Explode into an array:
291 $fileArray = t3lib_div::trimExplode(',',$fileList,1);
292
293 // If there were files to list...:
294 if (count($fileArray)) {
295
296 // Get the descriptions for the files (if any):
297 $descriptions = t3lib_div::trimExplode(LF,$this->cObj->data['imagecaption']);
298
299 // Get the titles for the files (if any)
300 $titles = t3lib_div::trimExplode(LF, $this->cObj->data['titleText']);
301
302 // Get the alternative text for icons/thumbnails
303 $altTexts = t3lib_div::trimExplode(LF, $this->cObj->data['altText']);
304
305 // Add the target to linkProc when explicitly set
306 if ($this->cObj->data['target']) {
307 $conf['linkProc.']['target'] = $this->cObj->data['target'];
308 unset($conf['linkProc.']['target.']);
309 }
310
311 // Adding hardcoded TS to linkProc configuration:
312 $conf['linkProc.']['path.']['current'] = 1;
313 if ($conf['linkProc.']['combinedLink']) {
314 $conf['linkProc.']['icon'] = $type > 0 ? 1 : 0;
315 } else {
316 $conf['linkProc.']['icon'] = 1; // Always render icon - is inserted by PHP if needed.
317 $conf['linkProc.']['icon.']['wrap'] = ' | //**//'; // Temporary, internal split-token!
318 $conf['linkProc.']['icon_link'] = 1; // ALways link the icon
319 }
320 $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.
321
322 if ($conf['labelStdWrap.']) {
323 $conf['linkProc.']['labelStdWrap.'] = $conf['labelStdWrap.'];
324 }
325 if ($conf['useSpacesInLinkText'] || $conf['stripFileExtensionFromLinkText']) {
326 $conf['linkProc.']['removePrependedNumbers'] = 0;
327 }
328
329 // Traverse the files found:
330 $filesData = array();
331 foreach($fileArray as $key => $fileName) {
332 $absPath = t3lib_div::getFileAbsFileName($path.$fileName);
333 if (@is_file($absPath)) {
334 $fI = pathinfo($fileName);
335 $filesData[$key] = array();
336
337 $filesData[$key]['filename'] = $fileName;
338 $filesData[$key]['path'] = $path;
339 $filesData[$key]['filesize'] = filesize($absPath);
340 $filesData[$key]['fileextension'] = strtolower($fI['extension']);
341 $filesData[$key]['description'] = trim($descriptions[$key]);
342
343 $conf['linkProc.']['title'] = trim($titles[$key]);
344
345 if (isset($altTexts[$key]) && !empty($altTexts[$key])) {
346 $altText = trim($altTexts[$key]);
347 } else {
348 $altText = sprintf($this->pi_getLL('uploads.icon'), $fileName);
349 }
350 $conf['linkProc.']['altText'] = $conf['linkProc.']['iconCObject.']['altText'] = $altText;
351
352 $this->cObj->setCurrentVal($path);
353 $GLOBALS['TSFE']->register['ICON_REL_PATH'] = $path.$fileName;
354 $GLOBALS['TSFE']->register['filename'] = $filesData[$key]['filename'];
355 $GLOBALS['TSFE']->register['path'] = $filesData[$key]['path'];
356 $GLOBALS['TSFE']->register['fileSize'] = $filesData[$key]['filesize'];
357 $GLOBALS['TSFE']->register['fileExtension'] = $filesData[$key]['fileextension'];
358 $GLOBALS['TSFE']->register['description'] = $filesData[$key]['description'];
359
360 $filesData[$key]['linkedFilenameParts']
361 = $this->beautifyFileLink(
362 explode(
363 '//**//',
364 $this->cObj->filelink(
365 $fileName, $conf['linkProc.']
366 )
367 ),
368 $fileName,
369 $conf['useSpacesInLinkText'],
370 $conf['stripFileExtensionFromLinkText']
371 );
372 }
373 }
374
375 // optionSplit applied to conf to allow differnt settings per file
376 $splitConf = $GLOBALS['TSFE']->tmpl->splitConfArray($conf, count($filesData));
377
378 // Now, lets render the list!
379 $outputEntries = array();
380 foreach ($filesData as $key => $fileData) {
381 $GLOBALS['TSFE']->register['linkedIcon'] = $fileData['linkedFilenameParts'][0];
382 $GLOBALS['TSFE']->register['linkedLabel'] = $fileData['linkedFilenameParts'][1];
383 $GLOBALS['TSFE']->register['filename'] = $fileData['filename'];
384 $GLOBALS['TSFE']->register['path'] = $fileData['path'];
385 $GLOBALS['TSFE']->register['description'] = $fileData['description'];
386 $GLOBALS['TSFE']->register['fileSize'] = $fileData['filesize'];
387 $GLOBALS['TSFE']->register['fileExtension'] = $fileData['fileextension'];
388 $outputEntries[] = $this->cObj->cObjGetSingle($splitConf[$key]['itemRendering'], $splitConf[$key]['itemRendering.']);
389 }
390
391 if (isset($conf['outerWrap'])) {
392 // Wrap around the whole content
393 $outerWrap = $this->cObj->stdWrap($conf['outerWrap'], $conf['outerWrap.']);
394 } else {
395 // Table tag params
396 $tableTagParams = $this->getTableAttributes($conf,$type);
397 $tableTagParams['class'] = 'csc-uploads csc-uploads-'.$type;
398 $outerWrap = '<table ' . t3lib_div::implodeAttributes($tableTagParams) . '>|</table>';
399 }
400
401 // Compile it all into table tags:
402 $out = $this->cObj->wrap(implode('', $outputEntries), $outerWrap);
403 }
404
405 // Calling stdWrap:
406 if ($conf['stdWrap.']) {
407 $out = $this->cObj->stdWrap($out, $conf['stdWrap.']);
408 }
409
410 // Return value
411 return $out;
412 }
413 }
414
415 /**
416 * returns an array containing width relations for $colCount columns.
417 *
418 * tries to use "colRelations" setting given by TS.
419 * uses "1:1" column relations by default.
420 *
421 * @param array $conf TS configuration for img
422 * @param int $colCount number of columns
423 * @return array
424 */
425 protected function getImgColumnRelations($conf, $colCount) {
426 $relations = array();
427 $equalRelations= array_fill(0, $colCount, 1);
428 $colRelationsTypoScript = trim($this->cObj->stdWrap($conf['colRelations'], $conf['colRelations.']));
429
430 if ($colRelationsTypoScript) {
431 // try to use column width relations given by TS
432 $relationParts = explode(':', $colRelationsTypoScript);
433 // enough columns defined?
434 if (count($relationParts) >= $colCount) {
435 $out = array();
436 for ($a = 0; $a < $colCount; $a++) {
437 $currentRelationValue = intval($relationParts[$a]);
438 if ($currentRelationValue >= 1) {
439 $out[$a] = $currentRelationValue;
440 } else {
441 t3lib_div::devLog('colRelations used with a value smaller than 1 therefore colRelations setting is ignored.', $this->extKey, 2);
442 unset($out);
443 break;
444 }
445 }
446 if (max($out) / min($out) <= 10) {
447 $relations = $out;
448 } else {
449 t3lib_div::devLog('The difference in size between the largest and smallest colRelation was not within a factor of ten therefore colRelations setting is ignored..', $this->extKey, 2);
450 }
451 }
452 }
453 return $relations ? $relations : $equalRelations;
454 }
455
456 /**
457 * returns an array containing the image widths for an image row with $colCount columns.
458 *
459 * @param array $conf TS configuration of img
460 * @param int $colCount number of columns
461 * @param int $netW max usable width for images (without spaces and borders)
462 * @return array
463 */
464 protected function getImgColumnWidths($conf, $colCount, $netW) {
465 $columnWidths = array();
466 $colRelations = $this->getImgColumnRelations($conf, $colCount);
467
468 $accumWidth = 0;
469 $accumDesiredWidth = 0;
470 $relUnitCount = array_sum($colRelations);
471
472 for ($a = 0; $a < $colCount; $a++) {
473 $availableWidth = $netW - $accumWidth; // this much width is available for the remaining images in this row (int)
474 $desiredWidth = $netW / $relUnitCount * $colRelations[$a]; // theoretical width of resized image. (float)
475 $accumDesiredWidth += $desiredWidth; // add this width. $accumDesiredWidth becomes the desired horizontal position
476 // calculate width by comparing actual and desired horizontal position.
477 // this evenly distributes rounding errors across all images in this row.
478 $suggestedWidth = round($accumDesiredWidth - $accumWidth);
479 $finalImgWidth = (int) min($availableWidth, $suggestedWidth); // finalImgWidth may not exceed $availableWidth
480 $accumWidth += $finalImgWidth;
481 $columnWidths[$a] = $finalImgWidth;
482 }
483 return $columnWidths;
484 }
485
486 /**
487 * Rendering the IMGTEXT content element, called from TypoScript (tt_content.textpic.20)
488 *
489 * @param string Content input. Not used, ignore.
490 * @param array TypoScript configuration. See TSRef "IMGTEXT". This function aims to be compatible.
491 * @return string HTML output.
492 * @access private
493 * @coauthor Ernesto Baschny <ernst@cron-it.de>
494 * @coauthor Patrick Broens <patrick@patrickbroens.nl>
495 */
496 function render_textpic($content, $conf) {
497 // Look for hook before running default code for function
498 if (method_exists($this, 'hookRequest') && $hookObj = $this->hookRequest('render_textpic')) {
499 return $hookObj->render_textpic($content,$conf);
500 }
501
502 $renderMethod = $this->cObj->stdWrap($conf['renderMethod'], $conf['renderMethod.']);
503
504 // Render using the default IMGTEXT code (table-based)
505 if (!$renderMethod || $renderMethod == 'table') {
506 return $this->cObj->IMGTEXT($conf);
507 }
508
509 // Specific configuration for the chosen rendering method
510 if (is_array($conf['rendering.'][$renderMethod . '.'])) {
511 $conf = $this->cObj->joinTSarrays($conf, $conf['rendering.'][$renderMethod . '.']);
512 }
513
514 // Image or Text with Image?
515 if (is_array($conf['text.'])) {
516 $content = $this->cObj->stdWrap($this->cObj->cObjGet($conf['text.'], 'text.'), $conf['text.']);
517 }
518
519 $imgList = trim($this->cObj->stdWrap($conf['imgList'], $conf['imgList.']));
520
521 if (!$imgList) {
522 // No images, that's easy
523 if (is_array($conf['stdWrap.'])) {
524 return $this->cObj->stdWrap($content, $conf['stdWrap.']);
525 }
526 return $content;
527 }
528
529 $imgs = t3lib_div::trimExplode(',', $imgList);
530 $imgStart = intval($this->cObj->stdWrap($conf['imgStart'], $conf['imgStart.']));
531 $imgCount = count($imgs) - $imgStart;
532 $imgMax = intval($this->cObj->stdWrap($conf['imgMax'], $conf['imgMax.']));
533 if ($imgMax) {
534 $imgCount = t3lib_utility_Math::forceIntegerInRange($imgCount, 0, $imgMax); // reduce the number of images.
535 }
536
537 $imgPath = $this->cObj->stdWrap($conf['imgPath'], $conf['imgPath.']);
538
539 // Does we need to render a "global caption" (below the whole image block)?
540 $renderGlobalCaption = !$conf['captionSplit'] && !$conf['imageTextSplit'] && is_array($conf['caption.']);
541 if ($imgCount == 1) {
542 // If we just have one image, the caption relates to the image, so it is not "global"
543 $renderGlobalCaption = FALSE;
544 }
545
546 // Use the calculated information (amount of images, if global caption is wanted) to choose a different rendering method for the images-block
547 $GLOBALS['TSFE']->register['imageCount'] = $imgCount;
548 $GLOBALS['TSFE']->register['renderGlobalCaption'] = $renderGlobalCaption;
549 $fallbackRenderMethod = $this->cObj->cObjGetSingle($conf['fallbackRendering'], $conf['fallbackRendering.']);
550 if ($fallbackRenderMethod && is_array($conf['rendering.'][$fallbackRenderMethod . '.'])) {
551 $conf = $this->cObj->joinTSarrays($conf, $conf['rendering.'][$fallbackRenderMethod . '.']);
552 }
553
554 // Set the accessibility mode which uses a different type of markup, used 4.7+
555 $accessibilityMode = FALSE;
556 if (strpos(strtolower($renderMethod), 'caption') || strpos(strtolower($fallbackRenderMethod), 'caption')) {
557 $accessibilityMode = TRUE;
558 }
559
560 // Global caption
561 $globalCaption = '';
562 if ($renderGlobalCaption) {
563 $globalCaption = $this->cObj->stdWrap($this->cObj->cObjGet($conf['caption.'], 'caption.'), $conf['caption.']);
564 }
565
566 // Positioning
567 $position = $this->cObj->stdWrap($conf['textPos'], $conf['textPos.']);
568
569 $imagePosition = $position&7; // 0,1,2 = center,right,left
570 $contentPosition = $position&24; // 0,8,16,24 (above,below,intext,intext-wrap)
571 $align = $this->cObj->align[$imagePosition];
572 $textMargin = intval($this->cObj->stdWrap($conf['textMargin'],$conf['textMargin.']));
573 if (!$conf['textMargin_outOfText'] && $contentPosition < 16) {
574 $textMargin = 0;
575 }
576
577 $colspacing = intval($this->cObj->stdWrap($conf['colSpace'], $conf['colSpace.']));
578 $rowspacing = intval($this->cObj->stdWrap($conf['rowSpace'], $conf['rowSpace.']));
579
580 $border = intval($this->cObj->stdWrap($conf['border'], $conf['border.'])) ? 1:0;
581 $borderColor = $this->cObj->stdWrap($conf['borderCol'], $conf['borderCol.']);
582 $borderThickness = intval($this->cObj->stdWrap($conf['borderThick'], $conf['borderThick.']));
583
584 $borderColor = $borderColor?$borderColor:'black';
585 $borderThickness = $borderThickness?$borderThickness:1;
586 $borderSpace = (($conf['borderSpace']&&$border) ? intval($conf['borderSpace']) : 0);
587
588 // Generate cols
589 $cols = intval($this->cObj->stdWrap($conf['cols'],$conf['cols.']));
590 $colCount = ($cols > 1) ? $cols : 1;
591 if ($colCount > $imgCount) {$colCount = $imgCount;}
592 $rowCount = ceil($imgCount / $colCount);
593
594 // Generate rows
595 $rows = intval($this->cObj->stdWrap($conf['rows'],$conf['rows.']));
596 if ($rows>1) {
597 $rowCount = $rows;
598 if ($rowCount > $imgCount) {$rowCount = $imgCount;}
599 $colCount = ($rowCount>1) ? ceil($imgCount / $rowCount) : $imgCount;
600 }
601
602 // Max Width
603 $maxW = intval($this->cObj->stdWrap($conf['maxW'], $conf['maxW.']));
604 $maxWInText = intval($this->cObj->stdWrap($conf['maxWInText'], $conf['maxWInText.']));
605 $fiftyPercentWidthInText = round($maxW / 100 * 50);
606
607 if ($contentPosition>=16) { // in Text
608 if (!$maxWInText) {
609 // If maxWInText is not set, it's calculated to the 50% of the max
610 $maxW = $fiftyPercentWidthInText;
611 } else {
612 $maxW = $maxWInText;
613 }
614 }
615
616 // Set the margin for image + text, no wrap always to avoid multiple stylesheets
617 if ($accessibilityMode) {
618 $noWrapMargin = (integer) (($maxWInText ? $maxWInText : $fiftyPercentWidthInText) +
619 intval($this->cObj->stdWrap($conf['textMargin'],$conf['textMargin.'])));
620
621 $this->addPageStyle(
622 '.csc-textpic-intext-right-nowrap .csc-textpic-text',
623 'margin-right: ' . $noWrapMargin . 'px;'
624 );
625
626 $this->addPageStyle(
627 '.csc-textpic-intext-left-nowrap .csc-textpic-text',
628 'margin-left: ' . $noWrapMargin . 'px;'
629 );
630 }
631
632 // max usuable width for images (without spacers and borders)
633 $netW = $maxW - $colspacing * ($colCount - 1) - $colCount * $border * ($borderThickness + $borderSpace) * 2;
634
635 // Specify the maximum width for each column
636 $columnWidths = $this->getImgColumnWidths($conf, $colCount, $netW);
637
638 $image_compression = intval($this->cObj->stdWrap($conf['image_compression'],$conf['image_compression.']));
639 $image_effects = intval($this->cObj->stdWrap($conf['image_effects'],$conf['image_effects.']));
640 $image_frames = intval($this->cObj->stdWrap($conf['image_frames.']['key'],$conf['image_frames.']['key.']));
641
642 // EqualHeight
643 $equalHeight = intval($this->cObj->stdWrap($conf['equalH'],$conf['equalH.']));
644 if ($equalHeight) {
645 // Initiate gifbuilder object in order to get dimensions AND calculate the imageWidth's
646 $gifCreator = t3lib_div::makeInstance('tslib_gifbuilder');
647 $gifCreator->init();
648 $relations_cols = Array();
649 $imgWidths = array(); // contains the individual width of all images after scaling to $equalHeight
650 for ($a=0; $a<$imgCount; $a++) {
651 $imgKey = $a+$imgStart;
652 $imgInfo = $gifCreator->getImageDimensions($imgPath.$imgs[$imgKey]);
653 $rel = $imgInfo[1] / $equalHeight; // relationship between the original height and the wished height
654 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.
655 $imgWidths[$a] = $imgInfo[0] / $rel;
656 $relations_cols[floor($a/$colCount)] += $imgWidths[$a]; // counts the total width of the row with the new height taken into consideration.
657 }
658 }
659 }
660
661 // Fetches pictures
662 $splitArr = array();
663 $splitArr['imgObjNum'] = $conf['imgObjNum'];
664 $splitArr = $GLOBALS['TSFE']->tmpl->splitConfArray($splitArr, $imgCount);
665
666 $imageRowsFinalWidths = Array(); // contains the width of every image row
667 $imgsTag = array(); // array index of $imgsTag will be the same as in $imgs, but $imgsTag only contains the images that are actually shown
668 $origImages = array();
669 $rowIdx = 0;
670 for ($a=0; $a<$imgCount; $a++) {
671 $imgKey = $a+$imgStart;
672 $totalImagePath = $imgPath.$imgs[$imgKey];
673
674 $GLOBALS['TSFE']->register['IMAGE_NUM'] = $imgKey; // register IMG_NUM is kept for backwards compatibility
675 $GLOBALS['TSFE']->register['IMAGE_NUM_CURRENT'] = $imgKey;
676 $GLOBALS['TSFE']->register['ORIG_FILENAME'] = $totalImagePath;
677
678 $this->cObj->data[$this->cObj->currentValKey] = $totalImagePath;
679 $imgObjNum = intval($splitArr[$a]['imgObjNum']);
680 $imgConf = $conf[$imgObjNum.'.'];
681
682 if ($equalHeight) {
683
684 if ($a % $colCount == 0) {
685 // a new row startsS
686 $accumWidth = 0; // reset accumulated net width
687 $accumDesiredWidth = 0; // reset accumulated desired width
688 $rowTotalMaxW = $relations_cols[$rowIdx];
689 if ($rowTotalMaxW > $netW) {
690 $scale = $rowTotalMaxW / $netW;
691 } else {
692 $scale = 1;
693 }
694 $desiredHeight = $equalHeight / $scale;
695 $rowIdx++;
696 }
697
698 $availableWidth= $netW - $accumWidth; // this much width is available for the remaining images in this row (int)
699 $desiredWidth= $imgWidths[$a] / $scale; // theoretical width of resized image. (float)
700 $accumDesiredWidth += $desiredWidth; // add this width. $accumDesiredWidth becomes the desired horizontal position
701 // calculate width by comparing actual and desired horizontal position.
702 // this evenly distributes rounding errors across all images in this row.
703 $suggestedWidth = round($accumDesiredWidth - $accumWidth);
704 $finalImgWidth = (int) min($availableWidth, $suggestedWidth); // finalImgWidth may not exceed $availableWidth
705 $accumWidth += $finalImgWidth;
706 $imgConf['file.']['width'] = $finalImgWidth;
707 $imgConf['file.']['height'] = round($desiredHeight);
708
709 // other stuff will be calculated accordingly:
710 unset($imgConf['file.']['maxW']);
711 unset($imgConf['file.']['maxH']);
712 unset($imgConf['file.']['minW']);
713 unset($imgConf['file.']['minH']);
714 unset($imgConf['file.']['width.']);
715 unset($imgConf['file.']['maxW.']);
716 unset($imgConf['file.']['maxH.']);
717 unset($imgConf['file.']['minW.']);
718 unset($imgConf['file.']['minH.']);
719 } else {
720 $imgConf['file.']['maxW'] = $columnWidths[($a%$colCount)];
721 }
722
723 $titleInLink = $this->cObj->stdWrap($imgConf['titleInLink'], $imgConf['titleInLink.']);
724 $titleInLinkAndImg = $this->cObj->stdWrap($imgConf['titleInLinkAndImg'], $imgConf['titleInLinkAndImg.']);
725 $oldATagParms = $GLOBALS['TSFE']->ATagParams;
726 if ($titleInLink) {
727 // Title in A-tag instead of IMG-tag
728 $titleText = trim($this->cObj->stdWrap($imgConf['titleText'], $imgConf['titleText.']));
729 if ($titleText) {
730 // This will be used by the IMAGE call later:
731 $GLOBALS['TSFE']->ATagParams .= ' title="'. $titleText .'"';
732 }
733 }
734
735 if ($imgConf || $imgConf['file']) {
736 if ($this->cObj->image_effects[$image_effects]) {
737 $imgConf['file.']['params'] .= ' '.$this->cObj->image_effects[$image_effects];
738 }
739 if ($image_frames) {
740 if (is_array($conf['image_frames.'][$image_frames.'.'])) {
741 $imgConf['file.']['m.'] = $conf['image_frames.'][$image_frames.'.'];
742 }
743 }
744 if ($image_compression && $imgConf['file'] != 'GIFBUILDER') {
745 if ($image_compression == 1) {
746 $tempImport = $imgConf['file.']['import'];
747 $tempImport_dot = $imgConf['file.']['import.'];
748 unset($imgConf['file.']);
749 $imgConf['file.']['import'] = $tempImport;
750 $imgConf['file.']['import.'] = $tempImport_dot;
751 } elseif (isset($this->cObj->image_compression[$image_compression])) {
752 $imgConf['file.']['params'] .= ' '.$this->cObj->image_compression[$image_compression]['params'];
753 $imgConf['file.']['ext'] = $this->cObj->image_compression[$image_compression]['ext'];
754 unset($imgConf['file.']['ext.']);
755 }
756 }
757 if ($titleInLink && ! $titleInLinkAndImg) {
758 // Check if the image will be linked
759 $link = $this->cObj->imageLinkWrap('', $totalImagePath, $imgConf['imageLinkWrap.']);
760 if ($link) {
761 // Title in A-tag only (set above: ATagParams), not in IMG-tag
762 unset($imgConf['titleText']);
763 unset($imgConf['titleText.']);
764 $imgConf['emptyTitleHandling'] = 'removeAttr';
765 }
766 }
767 $imgsTag[$imgKey] = $this->cObj->IMAGE($imgConf);
768 } else {
769 $imgsTag[$imgKey] = $this->cObj->IMAGE(Array('file' => $totalImagePath)); // currentValKey !!!
770 }
771 // Restore our ATagParams
772 $GLOBALS['TSFE']->ATagParams = $oldATagParms;
773 // Store the original filepath
774 $origImages[$imgKey] = $GLOBALS['TSFE']->lastImageInfo;
775
776 if ($GLOBALS['TSFE']->lastImageInfo[0]==0) {
777 $imageRowsFinalWidths[floor($a/$colCount)] += $this->cObj->data['imagewidth'];
778 } else {
779 $imageRowsFinalWidths[floor($a/$colCount)] += $GLOBALS['TSFE']->lastImageInfo[0];
780 }
781
782 }
783 // How much space will the image-block occupy?
784 $imageBlockWidth = max($imageRowsFinalWidths)+ $colspacing*($colCount-1) + $colCount*$border*($borderSpace+$borderThickness)*2;
785 $GLOBALS['TSFE']->register['rowwidth'] = $imageBlockWidth;
786 $GLOBALS['TSFE']->register['rowWidthPlusTextMargin'] = $imageBlockWidth + $textMargin;
787
788 // noRows is in fact just one ROW, with the amount of columns specified, where the images are placed in.
789 // noCols is just one COLUMN, each images placed side by side on each row
790 $noRows = $this->cObj->stdWrap($conf['noRows'],$conf['noRows.']);
791 $noCols = $this->cObj->stdWrap($conf['noCols'],$conf['noCols.']);
792 if ($noRows) {$noCols=0;} // noRows overrides noCols. They cannot exist at the same time.
793
794 $rowCount_temp = 1;
795 $colCount_temp = $colCount;
796 if ($noRows) {
797 $rowCount_temp = $rowCount;
798 $rowCount = 1;
799 }
800 if ($noCols) {
801 $colCount = 1;
802 $columnWidths = array();
803 }
804
805 // Edit icons:
806 if (!is_array($conf['editIcons.'])) {
807 $conf['editIcons.'] = array();
808 }
809 $editIconsHTML = $conf['editIcons']&&$GLOBALS['TSFE']->beUserLogin ? $this->cObj->editIcons('',$conf['editIcons'],$conf['editIcons.']) : '';
810
811 // If noRows, we need multiple imagecolumn wraps
812 $imageWrapCols = 1;
813 if ($noRows) { $imageWrapCols = $colCount; }
814
815 // User wants to separate the rows, but only do that if we do have rows
816 $separateRows = $this->cObj->stdWrap($conf['separateRows'], $conf['separateRows.']);
817 if ($noRows) { $separateRows = 0; }
818 if ($rowCount == 1) { $separateRows = 0; }
819
820 if ($accessibilityMode) {
821 $imagesInColumns = round(($imgCount / ($rowCount * $colCount)), 0 , PHP_ROUND_HALF_UP);
822
823 // Apply optionSplit to the list of classes that we want to add to each column
824 $addClassesCol = $conf['addClassesCol'];
825 if (isset($conf['addClassesCol.'])) {
826 $addClassesCol = $this->cObj->stdWrap($addClassesCol, $conf['addClassesCol.']);
827 }
828 $addClassesColConf = $GLOBALS['TSFE']->tmpl->splitConfArray(array('addClassesCol' => $addClassesCol), $colCount);
829
830 // Apply optionSplit to the list of classes that we want to add to each image
831 $addClassesImage = $conf['addClassesImage'];
832 if (isset($conf['addClassesImage.'])) {
833 $addClassesImage = $this->cObj->stdWrap($addClassesImage, $conf['addClassesImage.']);
834 }
835 $addClassesImageConf = $GLOBALS['TSFE']->tmpl->splitConfArray(array('addClassesImage' => $addClassesImage), $imagesInColumns);
836
837 $rows = array();
838 $currentImage = 0;
839
840 // Set the class for the caption (split or global)
841 $classCaptionAlign = array(
842 'center' => 'csc-textpic-caption-c',
843 'right' => 'csc-textpic-caption-r',
844 'left' => 'csc-textpic-caption-l',
845 );
846
847 $captionAlign = $this->cObj->stdWrap($conf['captionAlign'], $conf['captionAlign.']);
848
849 // Iterate over the rows
850 for ($rowCounter = 1; $rowCounter <= $rowCount; $rowCounter++) {
851 $rowColumns = array();
852 // Iterate over the columns
853 for ($columnCounter = 1; $columnCounter <= $colCount; $columnCounter++) {
854 $columnImages = array();
855 // Iterate over the amount of images allowed in a column
856 for ($imagesCounter = 1; $imagesCounter <= $imagesInColumns; $imagesCounter++) {
857 $image = NULL;
858 $splitCaption = NULL;
859 $imageMarkers = $captionMarkers = array();
860 $single = '&nbsp;';
861
862 // Set the key of the current image
863 $imageKey = $currentImage + $imgStart;
864
865 // Register IMAGE_NUM_CURRENT for the caption
866 $GLOBALS['TSFE']->register['IMAGE_NUM_CURRENT'] = $imageKey;
867 $this->cObj->data[$this->cObj->currentValKey] = $origImages[$imageKey]['origFile'];
868
869 // Get the image if not an empty cell
870 if (isset($imgsTag[$imageKey])) {
871 $image = $this->cObj->stdWrap($imgsTag[$imageKey], $conf['imgTagStdWrap.']);
872
873 // Add the edit icons
874 if ($editIconsHTML) {
875 $image .= $this->cObj->stdWrap($editIconsHTML, $conf['editIconsStdWrap.']);
876 }
877
878 // Wrap the single image
879 $single = $this->cObj->stdWrap($image, $conf['singleStdWrap.']);
880
881 // Get the caption
882 if (!$renderGlobalCaption) {
883 $imageMarkers['caption'] = $this->cObj->stdWrap(
884 $this->cObj->cObjGet($conf['caption.'], 'caption.'), $conf['caption.']
885 );
886 if ($captionAlign) {
887 $captionMarkers['classes'] = ' ' . $classCaptionAlign[$captionAlign];
888 }
889
890 $imageMarkers['caption'] = $this->cObj->substituteMarkerArray(
891 $imageMarkers['caption'],
892 $captionMarkers,
893 '###|###',
894 1,
895 1
896 );
897 }
898
899 if ($addClassesImageConf[$imagesCounter - 1]['addClassesImage']) {
900 $imageMarkers['classes'] = ' ' . $addClassesImageConf[$imagesCounter - 1]['addClassesImage'];
901 }
902 }
903
904 $columnImages[] = $this->cObj->substituteMarkerArray(
905 $single,
906 $imageMarkers,
907 '###|###',
908 1,
909 1
910 );
911
912 $currentImage++;
913 }
914
915 $rowColumn = $this->cObj->stdWrap(
916 implode(LF, $columnImages),
917 $conf['columnStdWrap.']
918 );
919
920 // Start filling the markers for columnStdWrap
921 $columnMarkers = array();
922
923 if ($addClassesColConf[$columnCounter - 1]['addClassesCol']) {
924 $columnMarkers['classes'] = ' ' . $addClassesColConf[$columnCounter - 1]['addClassesCol'];
925 }
926
927 $rowColumns[] = $this->cObj->substituteMarkerArray(
928 $rowColumn,
929 $columnMarkers,
930 '###|###',
931 1,
932 1
933 );
934 }
935 if ($noRows) {
936 $rowConfiguration = $conf['noRowsStdWrap.'];
937 } elseif ($rowCounter == $rowCount) {
938 $rowConfiguration = $conf['lastRowStdWrap.'];
939 } else {
940 $rowConfiguration = $conf['rowStdWrap.'];
941 }
942
943 $row = $this->cObj->stdWrap(
944 implode(LF, $rowColumns),
945 $rowConfiguration
946 );
947
948 // Start filling the markers for columnStdWrap
949 $rowMarkers = array();
950
951 $rows[] = $this->cObj->substituteMarkerArray(
952 $row,
953 $rowMarkers,
954 '###|###',
955 1,
956 1
957 );
958 }
959
960 $images = $this->cObj->stdWrap(
961 implode(LF, $rows),
962 $conf['allStdWrap.']
963 );
964 // Start filling the markers for allStdWrap
965 $allMarkers = array();
966 $classes = array();
967
968 // Add the global caption to the allStdWrap marker array if set
969 if ($globalCaption) {
970 $allMarkers['caption'] = $globalCaption;
971 if ($captionAlign) {
972 $classes[] = $classCaptionAlign[$captionAlign];
973 }
974 }
975
976 // Add the border class if needed
977 if ($border){
978 $classes[] = $conf['borderClass'] ? $conf['borderClass'] : 'csc-textpic-border';
979 }
980
981 // Add the class for equal height if needed
982 if ($equalHeight) {
983 $classes[] = 'csc-textpic-equalheight';
984 }
985
986 $addClasses = $this->cObj->stdWrap($conf['addClasses'], $conf['addClasses.']);
987 if ($addClasses) {
988 $classes[] = $addClasses;
989 }
990
991 if ($classes) {
992 $class = ' ' . implode(' ', $classes);
993 }
994
995 // Fill the markers for the allStdWrap
996 $images = $this->cObj->substituteMarkerArray(
997 $images,
998 $allMarkers,
999 '###|###',
1000 1,
1001 1
1002 );
1003 } else {
1004 // Apply optionSplit to the list of classes that we want to add to each image
1005 $addClassesImage = $conf['addClassesImage'];
1006 if (isset($conf['addClassesImage.'])) {
1007 $addClassesImage = $this->cObj->stdWrap($addClassesImage, $conf['addClassesImage.']);
1008 }
1009 $addClassesImageConf = $GLOBALS['TSFE']->tmpl->splitConfArray(array('addClassesImage' => $addClassesImage), $colCount);
1010
1011 // Render the images
1012 $images = '';
1013 for ($c = 0; $c < $imageWrapCols; $c++) {
1014 $tmpColspacing = $colspacing;
1015 if (($c == $imageWrapCols - 1 && $imagePosition == 2) || ($c == 0 && ($imagePosition == 1 || $imagePosition == 0))) {
1016 // Do not add spacing after column if we are first column (left) or last column (center/right)
1017 $tmpColspacing = 0;
1018 }
1019
1020 $thisImages = '';
1021 $allRows = '';
1022 $maxImageSpace = 0;
1023 for ($i = $c; $i < count($imgsTag); $i = $i + $imageWrapCols) {
1024 $imgKey = $i + $imgStart;
1025 $colPos = $i % $colCount;
1026 if ($separateRows && $colPos == 0) {
1027 $thisRow = '';
1028 }
1029
1030 // Render one image
1031 if($origImages[$imgKey][0]==0) {
1032 $imageSpace = $this->cObj->data['imagewidth'] + $border * ($borderSpace + $borderThickness) * 2;
1033 } else {
1034 $imageSpace = $origImages[$imgKey][0] + $border * ($borderSpace + $borderThickness) * 2;
1035 }
1036
1037 $GLOBALS['TSFE']->register['IMAGE_NUM'] = $imgKey;
1038 $GLOBALS['TSFE']->register['IMAGE_NUM_CURRENT'] = $imgKey;
1039 $GLOBALS['TSFE']->register['ORIG_FILENAME'] = $origImages[$imgKey]['origFile'];
1040 $GLOBALS['TSFE']->register['imagewidth'] = $origImages[$imgKey][0];
1041 $GLOBALS['TSFE']->register['imagespace'] = $imageSpace;
1042 $GLOBALS['TSFE']->register['imageheight'] = $origImages[$imgKey][1];
1043 if ($imageSpace > $maxImageSpace) {
1044 $maxImageSpace = $imageSpace;
1045 }
1046 $thisImage = '';
1047 $thisImage .= $this->cObj->stdWrap($imgsTag[$imgKey], $conf['imgTagStdWrap.']);
1048
1049 if (!$renderGlobalCaption) {
1050 $thisImage .= $this->cObj->stdWrap($this->cObj->cObjGet($conf['caption.'], 'caption.'), $conf['caption.']);
1051 }
1052 if ($editIconsHTML) {
1053 $thisImage .= $this->cObj->stdWrap($editIconsHTML, $conf['editIconsStdWrap.']);
1054 }
1055 $thisImage = $this->cObj->stdWrap($thisImage, $conf['oneImageStdWrap.']);
1056 $classes = '';
1057 if ($addClassesImageConf[$colPos]['addClassesImage']) {
1058 $classes = ' ' . $addClassesImageConf[$colPos]['addClassesImage'];
1059 }
1060 $thisImage = str_replace('###CLASSES###', $classes, $thisImage);
1061
1062 if ($separateRows) {
1063 $thisRow .= $thisImage;
1064 } else {
1065 $allRows .= $thisImage;
1066 }
1067 $GLOBALS['TSFE']->register['columnwidth'] = $maxImageSpace + $tmpColspacing;
1068
1069
1070 // Close this row at the end (colCount), or the last row at the final end
1071 if ($separateRows && ($i + 1 == count($imgsTag))) {
1072 // Close the very last row with either normal configuration or lastRow stdWrap
1073 $allRows .= $this->cObj->stdWrap($thisRow, (is_array($conf['imageLastRowStdWrap.']) ? $conf['imageLastRowStdWrap.'] : $conf['imageRowStdWrap.']));
1074 } elseif ($separateRows && $colPos == $colCount - 1) {
1075 $allRows .= $this->cObj->stdWrap($thisRow, $conf['imageRowStdWrap.']);
1076 }
1077 }
1078 if ($separateRows) {
1079 $thisImages .= $allRows;
1080 } else {
1081 $thisImages .= $this->cObj->stdWrap($allRows, $conf['noRowsStdWrap.']);
1082 }
1083 if ($noRows) {
1084 // Only needed to make columns, rather than rows:
1085 $images .= $this->cObj->stdWrap($thisImages, $conf['imageColumnStdWrap.']);
1086 } else {
1087 $images .= $thisImages;
1088 }
1089 }
1090
1091 // Add the global caption, if not split
1092 if ($globalCaption) {
1093 $images .= $globalCaption;
1094 }
1095
1096 // CSS-classes
1097 $captionClass = '';
1098 $classCaptionAlign = array(
1099 'center' => 'csc-textpic-caption-c',
1100 'right' => 'csc-textpic-caption-r',
1101 'left' => 'csc-textpic-caption-l',
1102 );
1103 $captionAlign = $this->cObj->stdWrap($conf['captionAlign'], $conf['captionAlign.']);
1104 if ($captionAlign) {
1105 $captionClass = $classCaptionAlign[$captionAlign];
1106 }
1107 $borderClass = '';
1108 if ($border) {
1109 $borderClass = $conf['borderClass'] ? $conf['borderClass'] : 'csc-textpic-border';
1110 }
1111
1112 // Multiple classes with all properties, to be styled in CSS
1113 $class = '';
1114 $class .= ($borderClass ? ' ' . $borderClass : '');
1115 $class .= ($captionClass ? ' ' . $captionClass : '');
1116 $class .= ($equalHeight ? ' csc-textpic-equalheight' : '');
1117 $addClasses = $this->cObj->stdWrap($conf['addClasses'], $conf['addClasses.']);
1118 $class .= ($addClasses ? ' ' . $addClasses : '');
1119
1120 // Do we need a width in our wrap around images?
1121 $imgWrapWidth = '';
1122 if ($position == 0 || $position == 8) {
1123 // For 'center' we always need a width: without one, the margin:auto trick won't work
1124 $imgWrapWidth = $imageBlockWidth;
1125 }
1126 if ($rowCount > 1) {
1127 // For multiple rows we also need a width, so that the images will wrap
1128 $imgWrapWidth = $imageBlockWidth;
1129 }
1130 if ($globalCaption) {
1131 // If we have a global caption, we need the width so that the caption will wrap
1132 $imgWrapWidth = $imageBlockWidth;
1133 }
1134
1135 // Wrap around the whole image block
1136 $GLOBALS['TSFE']->register['totalwidth'] = $imgWrapWidth;
1137 if ($imgWrapWidth) {
1138 $images = $this->cObj->stdWrap($images, $conf['imageStdWrap.']);
1139 } else {
1140 $images = $this->cObj->stdWrap($images, $conf['imageStdWrapNoWidth.']);
1141 }
1142 }
1143
1144 $output = $this->cObj->cObjGetSingle($conf['layout'], $conf['layout.']);
1145 $output = str_replace('###TEXT###', $content, $output);
1146 $output = str_replace('###IMAGES###', $images, $output);
1147 $output = str_replace('###CLASSES###', $class, $output);
1148
1149 if ($conf['stdWrap.']) {
1150 $output = $this->cObj->stdWrap($output, $conf['stdWrap.']);
1151 }
1152
1153 return $output;
1154 }
1155
1156 /***********************************
1157 *
1158 * Rendering of Content Element properties:
1159 *
1160 ***********************************/
1161
1162 /**
1163 * Add top or bottom margin to the content element
1164 *
1165 * Constructs and adds a class to the content element. This class selector
1166 * and its declaration are added to the specific page styles.
1167 *
1168 * @param string $content Content input. Not used, ignore.
1169 * @param array $configuration TypoScript configuration
1170 * @return string The class name
1171 */
1172 public function renderSpace($content, array $configuration) {
1173 // Look for hook before running default code for function
1174 if (method_exists($this, 'hookRequest') && $hookObject = $this->hookRequest('renderSpace')) {
1175 return $hookObject->renderSpace($content, $configuration);
1176 }
1177
1178 if (isset($configuration['space']) && in_array($configuration['space'], array('before', 'after'))) {
1179 $constant = (int) $configuration['constant'];
1180
1181 if ($configuration['space'] === 'before') {
1182 $value = $constant + $this->cObj->data['spaceBefore'];
1183 $declaration = 'margin-top: ' . $value .'px;';
1184 } else {
1185 $value = $constant + $this->cObj->data['spaceAfter'];
1186 $declaration = 'margin-bottom: ' . $value . 'px;';
1187 }
1188
1189 if (!empty($value)) {
1190 if ($configuration['stdWrap.']) {
1191 $className = $this->cObj->stdWrap($value, $configuration['stdWrap.']);
1192 } else {
1193 $className = $value;
1194 }
1195
1196 $selector = '.' . trim($className);
1197
1198 $this->addPageStyle($selector, $declaration);
1199
1200 return $className;
1201 }
1202 }
1203 }
1204
1205
1206
1207
1208
1209
1210
1211
1212 /************************************
1213 *
1214 * Helper functions
1215 *
1216 ************************************/
1217
1218 /**
1219 * Returns a link text string which replaces underscores in filename with
1220 * blanks.
1221 *
1222 * Has the possibility to cut off FileType.
1223
1224 * @param array $links
1225 * array with [0] linked file icon, [1] text link
1226 * @param string $fileName
1227 * the name of the file to be linked (without path)
1228 * @param boolean $useSpaces
1229 * whether underscores in the file name should be replaced with spaces
1230 * @param boolean $cutFileExtension
1231 * whether the file extension should be removed
1232 *
1233 * @return array modified array with new link text
1234 */
1235 protected function beautifyFileLink(
1236 array $links, $fileName, $useSpaces = FALSE, $cutFileExtension = FALSE
1237 ) {
1238 $linkText = $fileName;
1239 if ($useSpaces) {
1240 $linkText = str_replace('_', ' ', $linkText);
1241 }
1242 if ($cutFileExtension) {
1243 $pos = strrpos($linkText, '.');
1244 $linkText = substr($linkText, 0, $pos);
1245 }
1246 $links[1] = str_replace(
1247 '>' . $fileName . '<', '>' . $linkText . '<', $links[1]
1248 );
1249 return $links;
1250 }
1251
1252 /**
1253 * Returns table attributes for uploads / tables.
1254 *
1255 * @param array TypoScript configuration array
1256 * @param integer The "layout" type
1257 * @return array Array with attributes inside.
1258 */
1259 function getTableAttributes($conf, $type) {
1260
1261 // Initializing:
1262 $tableTagParams_conf = $conf['tableParams_'.$type.'.'];
1263
1264 $border = $this->cObj->data['table_border'] ? intval($this->cObj->data['table_border']) : $tableTagParams_conf['border'];
1265 $cellSpacing = $this->cObj->data['table_cellspacing'] ? intval($this->cObj->data['table_cellspacing']) : $tableTagParams_conf['cellspacing'];
1266 $cellPadding = $this->cObj->data['table_cellpadding'] ? intval($this->cObj->data['table_cellpadding']) : $tableTagParams_conf['cellpadding'];
1267 $summary = trim(htmlspecialchars($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'acctables_summary')));
1268
1269 // Create table attributes and classes array:
1270 $tableTagParams = $classes = array();
1271
1272 // Table attributes for all doctypes except HTML5
1273 if ($GLOBALS['TSFE']->config['config']['doctype'] !== 'html5') {
1274 $tableTagParams['border'] = $border;
1275 $tableTagParams['cellspacing'] = $cellSpacing;
1276 $tableTagParams['cellpadding'] = $cellPadding;
1277 if ($summary) {
1278 $tableTagParams['summary'] = $summary;
1279 }
1280
1281 // Some attributes are obsolete or have been changed in HTML5
1282 } else {
1283 if ($border) {
1284 // Border property has changed, now with class
1285 $borderClass = 'contenttable-border-' . $border;
1286 $borderDeclaration = 'border-width: ' . $border . 'px; border-style: solid;';
1287
1288 $this->addPageStyle('.' . $borderClass, $borderDeclaration);
1289
1290 $classes[] = $borderClass;
1291 }
1292 if ($cellSpacing) {
1293 // Border attribute for HTML5 is 1 when there is cell spacing
1294 $tableTagParams['border'] = 1;
1295 // Use CSS3 border-spacing in class to have cell spacing
1296 $cellSpacingClass = 'contenttable-cellspacing-' . $cellSpacing;
1297 $cellSpacingDeclaration = 'border-spacing: ' . $cellSpacing . 'px;';
1298
1299 $this->addPageStyle('.' . $cellSpacingClass, $cellSpacingDeclaration);
1300
1301 $classes[] = $cellSpacingClass;
1302 }
1303 if ($cellPadding) {
1304 // Cell padding property has changed, now with class
1305 $cellPaddingClass = 'contenttable-cellpadding-' . $cellPadding;
1306 $cellSpacingSelector = '.' . $cellPaddingClass . ' td, .' . $cellPaddingClass . ' th';
1307 $cellPaddingDeclaration = 'padding: ' . $cellPadding . 'px;';
1308
1309 $this->addPageStyle($cellSpacingSelector, $cellPaddingDeclaration);
1310
1311 $classes[] = $cellPaddingClass;
1312 }
1313 }
1314 // Background color is class
1315 if (
1316 isset($conf['color.'][$this->cObj->data['table_bgColor']]) &&
1317 !empty($conf['color.'][$this->cObj->data['table_bgColor']])
1318 ) {
1319 $classes[] = 'contenttable-color-' . $this->cObj->data['table_bgColor'];
1320 }
1321
1322 if (!empty($classes)) {
1323 $tableTagParams['class'] = ' ' . implode(' ', $classes);
1324 }
1325
1326 // Return result:
1327 return $tableTagParams;
1328 }
1329
1330 /**
1331 * Add a style to the page, specific for this page
1332 *
1333 * The selector can be a contextual selector, like '#id .class p'
1334 * The presence of the selector is checked to avoid multiple entries of the
1335 * same selector.
1336 *
1337 * @param string $selector The selector
1338 * @param string $declaration The declaration
1339 * @return void
1340 */
1341 protected function addPageStyle($selector, $declaration) {
1342 if (!isset($GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_cssstyledcontent.']['_CSS_PAGE_STYLE'])) {
1343 $GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_cssstyledcontent.']['_CSS_PAGE_STYLE'] = array();
1344 }
1345
1346 if (!isset($GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_cssstyledcontent.']['_CSS_PAGE_STYLE'][$selector])) {
1347 $GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_cssstyledcontent.']['_CSS_PAGE_STYLE'][$selector] = TAB . $selector .
1348 ' { ' . $declaration . ' }';
1349 }
1350 }
1351
1352 /**
1353 * Returns an object reference to the hook object if any
1354 *
1355 * @param string Name of the function you want to call / hook key
1356 * @return object Hook object, if any. Otherwise NULL.
1357 */
1358 function hookRequest($functionName) {
1359 global $TYPO3_CONF_VARS;
1360
1361 // Hook: menuConfig_preProcessModMenu
1362 if ($TYPO3_CONF_VARS['EXTCONF']['css_styled_content']['pi1_hooks'][$functionName]) {
1363 $hookObj = t3lib_div::getUserObj($TYPO3_CONF_VARS['EXTCONF']['css_styled_content']['pi1_hooks'][$functionName]);
1364 if (method_exists ($hookObj, $functionName)) {
1365 $hookObj->pObj = $this;
1366 return $hookObj;
1367 }
1368 }
1369 }
1370 }
1371
1372
1373
1374 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/css_styled_content/pi1/class.tx_cssstyledcontent_pi1.php'])) {
1375 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/css_styled_content/pi1/class.tx_cssstyledcontent_pi1.php']);
1376 }
1377
1378 ?>