[TASK] CGL violations FunctionCallArgumentSpacing in /typo3/sysext/c*/
[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(t3lib_div::resolveBackPath($path . $fileName));
333 if (@is_file($absPath)) {
334 $fI = pathinfo($fileName);
335 $filesData[$key] = array();
336
337 $currentPath = $path;
338 if (t3lib_div::isFirstPartOfStr($fileName, '../../')) {
339 $currentPath = '';
340 $fileName = substr($fileName, 6);
341 }
342
343 $filesData[$key]['filename'] = $fileName;
344 $filesData[$key]['path'] = $currentPath;
345 $filesData[$key]['filesize'] = filesize($absPath);
346 $filesData[$key]['fileextension'] = strtolower($fI['extension']);
347 $filesData[$key]['description'] = trim($descriptions[$key]);
348
349 $conf['linkProc.']['title'] = trim($titles[$key]);
350
351 if (isset($altTexts[$key]) && !empty($altTexts[$key])) {
352 $altText = trim($altTexts[$key]);
353 } else {
354 $altText = sprintf($this->pi_getLL('uploads.icon'), $fileName);
355 }
356 $conf['linkProc.']['altText'] = $conf['linkProc.']['iconCObject.']['altText'] = $altText;
357
358 $this->cObj->setCurrentVal($currentPath);
359 $GLOBALS['TSFE']->register['ICON_REL_PATH'] = $currentPath . $fileName;
360 $GLOBALS['TSFE']->register['filename'] = $filesData[$key]['filename'];
361 $GLOBALS['TSFE']->register['path'] = $filesData[$key]['path'];
362 $GLOBALS['TSFE']->register['fileSize'] = $filesData[$key]['filesize'];
363 $GLOBALS['TSFE']->register['fileExtension'] = $filesData[$key]['fileextension'];
364 $GLOBALS['TSFE']->register['description'] = $filesData[$key]['description'];
365
366 $filesData[$key]['linkedFilenameParts']
367 = $this->beautifyFileLink(
368 explode(
369 '//**//',
370 $this->cObj->filelink(
371 $fileName, $conf['linkProc.']
372 )
373 ),
374 $fileName,
375 $conf['useSpacesInLinkText'],
376 $conf['stripFileExtensionFromLinkText']
377 );
378 }
379 }
380
381 // optionSplit applied to conf to allow differnt settings per file
382 $splitConf = $GLOBALS['TSFE']->tmpl->splitConfArray($conf, count($filesData));
383
384 // Now, lets render the list!
385 $outputEntries = array();
386 foreach ($filesData as $key => $fileData) {
387 $GLOBALS['TSFE']->register['linkedIcon'] = $fileData['linkedFilenameParts'][0];
388 $GLOBALS['TSFE']->register['linkedLabel'] = $fileData['linkedFilenameParts'][1];
389 $GLOBALS['TSFE']->register['filename'] = $fileData['filename'];
390 $GLOBALS['TSFE']->register['path'] = $fileData['path'];
391 $GLOBALS['TSFE']->register['description'] = $fileData['description'];
392 $GLOBALS['TSFE']->register['fileSize'] = $fileData['filesize'];
393 $GLOBALS['TSFE']->register['fileExtension'] = $fileData['fileextension'];
394 $outputEntries[] = $this->cObj->cObjGetSingle($splitConf[$key]['itemRendering'], $splitConf[$key]['itemRendering.']);
395 }
396
397 if (isset($conf['outerWrap'])) {
398 // Wrap around the whole content
399 $outerWrap = $this->cObj->stdWrap($conf['outerWrap'], $conf['outerWrap.']);
400 } else {
401 // Table tag params
402 $tableTagParams = $this->getTableAttributes($conf, $type);
403 $tableTagParams['class'] = 'csc-uploads csc-uploads-'.$type;
404 $outerWrap = '<table ' . t3lib_div::implodeAttributes($tableTagParams) . '>|</table>';
405 }
406
407 // Compile it all into table tags:
408 $out = $this->cObj->wrap(implode('', $outputEntries), $outerWrap);
409 }
410
411 // Calling stdWrap:
412 if ($conf['stdWrap.']) {
413 $out = $this->cObj->stdWrap($out, $conf['stdWrap.']);
414 }
415
416 // Return value
417 return $out;
418 }
419 }
420
421 /**
422 * returns an array containing width relations for $colCount columns.
423 *
424 * tries to use "colRelations" setting given by TS.
425 * uses "1:1" column relations by default.
426 *
427 * @param array $conf TS configuration for img
428 * @param int $colCount number of columns
429 * @return array
430 */
431 protected function getImgColumnRelations($conf, $colCount) {
432 $relations = array();
433 $equalRelations= array_fill(0, $colCount, 1);
434 $colRelationsTypoScript = trim($this->cObj->stdWrap($conf['colRelations'], $conf['colRelations.']));
435
436 if ($colRelationsTypoScript) {
437 // try to use column width relations given by TS
438 $relationParts = explode(':', $colRelationsTypoScript);
439 // enough columns defined?
440 if (count($relationParts) >= $colCount) {
441 $out = array();
442 for ($a = 0; $a < $colCount; $a++) {
443 $currentRelationValue = intval($relationParts[$a]);
444 if ($currentRelationValue >= 1) {
445 $out[$a] = $currentRelationValue;
446 } else {
447 t3lib_div::devLog('colRelations used with a value smaller than 1 therefore colRelations setting is ignored.', $this->extKey, 2);
448 unset($out);
449 break;
450 }
451 }
452 if (max($out) / min($out) <= 10) {
453 $relations = $out;
454 } else {
455 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);
456 }
457 }
458 }
459 return $relations ? $relations : $equalRelations;
460 }
461
462 /**
463 * returns an array containing the image widths for an image row with $colCount columns.
464 *
465 * @param array $conf TS configuration of img
466 * @param int $colCount number of columns
467 * @param int $netW max usable width for images (without spaces and borders)
468 * @return array
469 */
470 protected function getImgColumnWidths($conf, $colCount, $netW) {
471 $columnWidths = array();
472 $colRelations = $this->getImgColumnRelations($conf, $colCount);
473
474 $accumWidth = 0;
475 $accumDesiredWidth = 0;
476 $relUnitCount = array_sum($colRelations);
477
478 for ($a = 0; $a < $colCount; $a++) {
479 $availableWidth = $netW - $accumWidth; // this much width is available for the remaining images in this row (int)
480 $desiredWidth = $netW / $relUnitCount * $colRelations[$a]; // theoretical width of resized image. (float)
481 $accumDesiredWidth += $desiredWidth; // add this width. $accumDesiredWidth becomes the desired horizontal position
482 // calculate width by comparing actual and desired horizontal position.
483 // this evenly distributes rounding errors across all images in this row.
484 $suggestedWidth = round($accumDesiredWidth - $accumWidth);
485 $finalImgWidth = (int) min($availableWidth, $suggestedWidth); // finalImgWidth may not exceed $availableWidth
486 $accumWidth += $finalImgWidth;
487 $columnWidths[$a] = $finalImgWidth;
488 }
489 return $columnWidths;
490 }
491
492 /**
493 * Rendering the IMGTEXT content element, called from TypoScript (tt_content.textpic.20)
494 *
495 * @param string Content input. Not used, ignore.
496 * @param array TypoScript configuration. See TSRef "IMGTEXT". This function aims to be compatible.
497 * @return string HTML output.
498 * @access private
499 * @coauthor Ernesto Baschny <ernst@cron-it.de>
500 * @coauthor Patrick Broens <patrick@patrickbroens.nl>
501 */
502 function render_textpic($content, $conf) {
503 // Look for hook before running default code for function
504 if (method_exists($this, 'hookRequest') && $hookObj = $this->hookRequest('render_textpic')) {
505 return $hookObj->render_textpic($content, $conf);
506 }
507
508 $renderMethod = $this->cObj->stdWrap($conf['renderMethod'], $conf['renderMethod.']);
509
510 // Render using the default IMGTEXT code (table-based)
511 if (!$renderMethod || $renderMethod == 'table') {
512 return $this->cObj->IMGTEXT($conf);
513 }
514
515 // Specific configuration for the chosen rendering method
516 if (is_array($conf['rendering.'][$renderMethod . '.'])) {
517 $conf = $this->cObj->joinTSarrays($conf, $conf['rendering.'][$renderMethod . '.']);
518 }
519
520 // Image or Text with Image?
521 if (is_array($conf['text.'])) {
522 $content = $this->cObj->stdWrap($this->cObj->cObjGet($conf['text.'], 'text.'), $conf['text.']);
523 }
524
525 $imgList = trim($this->cObj->stdWrap($conf['imgList'], $conf['imgList.']));
526
527 if (!$imgList) {
528 // No images, that's easy
529 if (is_array($conf['stdWrap.'])) {
530 return $this->cObj->stdWrap($content, $conf['stdWrap.']);
531 }
532 return $content;
533 }
534
535 $imgs = t3lib_div::trimExplode(',', $imgList);
536 $imgStart = intval($this->cObj->stdWrap($conf['imgStart'], $conf['imgStart.']));
537 $imgCount = count($imgs) - $imgStart;
538 $imgMax = intval($this->cObj->stdWrap($conf['imgMax'], $conf['imgMax.']));
539 if ($imgMax) {
540 $imgCount = t3lib_utility_Math::forceIntegerInRange($imgCount, 0, $imgMax); // reduce the number of images.
541 }
542
543 $imgPath = $this->cObj->stdWrap($conf['imgPath'], $conf['imgPath.']);
544
545 // Does we need to render a "global caption" (below the whole image block)?
546 $renderGlobalCaption = !$conf['captionSplit'] && !$conf['imageTextSplit'] && is_array($conf['caption.']);
547 if ($imgCount == 1) {
548 // If we just have one image, the caption relates to the image, so it is not "global"
549 $renderGlobalCaption = FALSE;
550 }
551
552 // Use the calculated information (amount of images, if global caption is wanted) to choose a different rendering method for the images-block
553 $GLOBALS['TSFE']->register['imageCount'] = $imgCount;
554 $GLOBALS['TSFE']->register['renderGlobalCaption'] = $renderGlobalCaption;
555 $fallbackRenderMethod = $this->cObj->cObjGetSingle($conf['fallbackRendering'], $conf['fallbackRendering.']);
556 if ($fallbackRenderMethod && is_array($conf['rendering.'][$fallbackRenderMethod . '.'])) {
557 $conf = $this->cObj->joinTSarrays($conf, $conf['rendering.'][$fallbackRenderMethod . '.']);
558 }
559
560 // Set the accessibility mode which uses a different type of markup, used 4.7+
561 $accessibilityMode = FALSE;
562 if (strpos(strtolower($renderMethod), 'caption') || strpos(strtolower($fallbackRenderMethod), 'caption')) {
563 $accessibilityMode = TRUE;
564 }
565
566 // Global caption
567 $globalCaption = '';
568 if ($renderGlobalCaption) {
569 $globalCaption = $this->cObj->stdWrap($this->cObj->cObjGet($conf['caption.'], 'caption.'), $conf['caption.']);
570 }
571
572 // Positioning
573 $position = $this->cObj->stdWrap($conf['textPos'], $conf['textPos.']);
574
575 $imagePosition = $position&7; // 0,1,2 = center,right,left
576 $contentPosition = $position&24; // 0,8,16,24 (above,below,intext,intext-wrap)
577 $align = $this->cObj->align[$imagePosition];
578 $textMargin = intval($this->cObj->stdWrap($conf['textMargin'], $conf['textMargin.']));
579 if (!$conf['textMargin_outOfText'] && $contentPosition < 16) {
580 $textMargin = 0;
581 }
582
583 $colspacing = intval($this->cObj->stdWrap($conf['colSpace'], $conf['colSpace.']));
584 $rowspacing = intval($this->cObj->stdWrap($conf['rowSpace'], $conf['rowSpace.']));
585
586 $border = intval($this->cObj->stdWrap($conf['border'], $conf['border.'])) ? 1:0;
587 $borderColor = $this->cObj->stdWrap($conf['borderCol'], $conf['borderCol.']);
588 $borderThickness = intval($this->cObj->stdWrap($conf['borderThick'], $conf['borderThick.']));
589
590 $borderColor = $borderColor?$borderColor:'black';
591 $borderThickness = $borderThickness?$borderThickness:1;
592 $borderSpace = (($conf['borderSpace'] && $border) ? intval($conf['borderSpace']) : 0);
593
594 // Generate cols
595 $cols = intval($this->cObj->stdWrap($conf['cols'], $conf['cols.']));
596 $colCount = ($cols > 1) ? $cols : 1;
597 if ($colCount > $imgCount) {$colCount = $imgCount;}
598 $rowCount = ceil($imgCount / $colCount);
599
600 // Generate rows
601 $rows = intval($this->cObj->stdWrap($conf['rows'], $conf['rows.']));
602 if ($rows>1) {
603 $rowCount = $rows;
604 if ($rowCount > $imgCount) {$rowCount = $imgCount;}
605 $colCount = ($rowCount>1) ? ceil($imgCount / $rowCount) : $imgCount;
606 }
607
608 // Max Width
609 $maxW = intval($this->cObj->stdWrap($conf['maxW'], $conf['maxW.']));
610 $maxWInText = intval($this->cObj->stdWrap($conf['maxWInText'], $conf['maxWInText.']));
611 $fiftyPercentWidthInText = round($maxW / 100 * 50);
612
613 if ($contentPosition>=16) { // in Text
614 if (!$maxWInText) {
615 // If maxWInText is not set, it's calculated to the 50% of the max
616 $maxW = $fiftyPercentWidthInText;
617 } else {
618 $maxW = $maxWInText;
619 }
620 }
621
622 // Set the margin for image + text, no wrap always to avoid multiple stylesheets
623 if ($accessibilityMode) {
624 $noWrapMargin = (integer) (($maxWInText ? $maxWInText : $fiftyPercentWidthInText) +
625 intval($this->cObj->stdWrap($conf['textMargin'], $conf['textMargin.'])));
626
627 $this->addPageStyle(
628 '.csc-textpic-intext-right-nowrap .csc-textpic-text',
629 'margin-right: ' . $noWrapMargin . 'px;'
630 );
631
632 $this->addPageStyle(
633 '.csc-textpic-intext-left-nowrap .csc-textpic-text',
634 'margin-left: ' . $noWrapMargin . 'px;'
635 );
636 }
637
638 // max usuable width for images (without spacers and borders)
639 $netW = $maxW - $colspacing * ($colCount - 1) - $colCount * $border * ($borderThickness + $borderSpace) * 2;
640
641 // Specify the maximum width for each column
642 $columnWidths = $this->getImgColumnWidths($conf, $colCount, $netW);
643
644 $image_compression = intval($this->cObj->stdWrap($conf['image_compression'], $conf['image_compression.']));
645 $image_effects = intval($this->cObj->stdWrap($conf['image_effects'], $conf['image_effects.']));
646 $image_frames = intval($this->cObj->stdWrap($conf['image_frames.']['key'], $conf['image_frames.']['key.']));
647
648 // EqualHeight
649 $equalHeight = intval($this->cObj->stdWrap($conf['equalH'], $conf['equalH.']));
650 if ($equalHeight) {
651 // Initiate gifbuilder object in order to get dimensions AND calculate the imageWidth's
652 $gifCreator = t3lib_div::makeInstance('tslib_gifbuilder');
653 $gifCreator->init();
654 $relations_cols = Array();
655 $imgWidths = array(); // contains the individual width of all images after scaling to $equalHeight
656 for ($a=0; $a<$imgCount; $a++) {
657 $imgKey = $a+$imgStart;
658 $imgInfo = $gifCreator->getImageDimensions($imgPath.$imgs[$imgKey]);
659 $rel = $imgInfo[1] / $equalHeight; // relationship between the original height and the wished height
660 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.
661 $imgWidths[$a] = $imgInfo[0] / $rel;
662 $relations_cols[floor($a/$colCount)] += $imgWidths[$a]; // counts the total width of the row with the new height taken into consideration.
663 }
664 }
665 }
666
667 // Fetches pictures
668 $splitArr = array();
669 $splitArr['imgObjNum'] = $conf['imgObjNum'];
670 $splitArr = $GLOBALS['TSFE']->tmpl->splitConfArray($splitArr, $imgCount);
671
672 $imageRowsFinalWidths = Array(); // contains the width of every image row
673 $imgsTag = array(); // array index of $imgsTag will be the same as in $imgs, but $imgsTag only contains the images that are actually shown
674 $origImages = array();
675 $rowIdx = 0;
676 for ($a=0; $a<$imgCount; $a++) {
677 $imgKey = $a+$imgStart;
678 $totalImagePath = $imgPath.$imgs[$imgKey];
679
680 $GLOBALS['TSFE']->register['IMAGE_NUM'] = $imgKey; // register IMG_NUM is kept for backwards compatibility
681 $GLOBALS['TSFE']->register['IMAGE_NUM_CURRENT'] = $imgKey;
682 $GLOBALS['TSFE']->register['ORIG_FILENAME'] = $totalImagePath;
683
684 $this->cObj->data[$this->cObj->currentValKey] = $totalImagePath;
685 $imgObjNum = intval($splitArr[$a]['imgObjNum']);
686 $imgConf = $conf[$imgObjNum.'.'];
687
688 if ($equalHeight) {
689
690 if ($a % $colCount == 0) {
691 // a new row startsS
692 $accumWidth = 0; // reset accumulated net width
693 $accumDesiredWidth = 0; // reset accumulated desired width
694 $rowTotalMaxW = $relations_cols[$rowIdx];
695 if ($rowTotalMaxW > $netW && $netW > 0) {
696 $scale = $rowTotalMaxW / $netW;
697 } else {
698 $scale = 1;
699 }
700 $desiredHeight = $equalHeight / $scale;
701 $rowIdx++;
702 }
703
704 $availableWidth= $netW - $accumWidth; // this much width is available for the remaining images in this row (int)
705 $desiredWidth= $imgWidths[$a] / $scale; // theoretical width of resized image. (float)
706 $accumDesiredWidth += $desiredWidth; // add this width. $accumDesiredWidth becomes the desired horizontal position
707 // calculate width by comparing actual and desired horizontal position.
708 // this evenly distributes rounding errors across all images in this row.
709 $suggestedWidth = round($accumDesiredWidth - $accumWidth);
710 $finalImgWidth = (int) min($availableWidth, $suggestedWidth); // finalImgWidth may not exceed $availableWidth
711 $accumWidth += $finalImgWidth;
712 $imgConf['file.']['width'] = $finalImgWidth;
713 $imgConf['file.']['height'] = round($desiredHeight);
714
715 // other stuff will be calculated accordingly:
716 unset($imgConf['file.']['maxW']);
717 unset($imgConf['file.']['maxH']);
718 unset($imgConf['file.']['minW']);
719 unset($imgConf['file.']['minH']);
720 unset($imgConf['file.']['width.']);
721 unset($imgConf['file.']['maxW.']);
722 unset($imgConf['file.']['maxH.']);
723 unset($imgConf['file.']['minW.']);
724 unset($imgConf['file.']['minH.']);
725 } else {
726 $imgConf['file.']['maxW'] = $columnWidths[($a%$colCount)];
727 }
728
729 $titleInLink = $this->cObj->stdWrap($imgConf['titleInLink'], $imgConf['titleInLink.']);
730 $titleInLinkAndImg = $this->cObj->stdWrap($imgConf['titleInLinkAndImg'], $imgConf['titleInLinkAndImg.']);
731 $oldATagParms = $GLOBALS['TSFE']->ATagParams;
732 if ($titleInLink) {
733 // Title in A-tag instead of IMG-tag
734 $titleText = trim($this->cObj->stdWrap($imgConf['titleText'], $imgConf['titleText.']));
735 if ($titleText) {
736 // This will be used by the IMAGE call later:
737 $GLOBALS['TSFE']->ATagParams .= ' title="'. $titleText .'"';
738 }
739 }
740
741 if ($imgConf || $imgConf['file']) {
742 if ($this->cObj->image_effects[$image_effects]) {
743 $imgConf['file.']['params'] .= ' '.$this->cObj->image_effects[$image_effects];
744 }
745 if ($image_frames) {
746 if (is_array($conf['image_frames.'][$image_frames.'.'])) {
747 $imgConf['file.']['m.'] = $conf['image_frames.'][$image_frames.'.'];
748 }
749 }
750 if ($image_compression && $imgConf['file'] != 'GIFBUILDER') {
751 if ($image_compression == 1) {
752 $tempImport = $imgConf['file.']['import'];
753 $tempImport_dot = $imgConf['file.']['import.'];
754 unset($imgConf['file.']);
755 $imgConf['file.']['import'] = $tempImport;
756 $imgConf['file.']['import.'] = $tempImport_dot;
757 } elseif (isset($this->cObj->image_compression[$image_compression])) {
758 $imgConf['file.']['params'] .= ' '.$this->cObj->image_compression[$image_compression]['params'];
759 $imgConf['file.']['ext'] = $this->cObj->image_compression[$image_compression]['ext'];
760 unset($imgConf['file.']['ext.']);
761 }
762 }
763 if ($titleInLink && ! $titleInLinkAndImg) {
764 // Check if the image will be linked
765 $link = $this->cObj->imageLinkWrap('', $totalImagePath, $imgConf['imageLinkWrap.']);
766 if ($link) {
767 // Title in A-tag only (set above: ATagParams), not in IMG-tag
768 unset($imgConf['titleText']);
769 unset($imgConf['titleText.']);
770 $imgConf['emptyTitleHandling'] = 'removeAttr';
771 }
772 }
773 $imgsTag[$imgKey] = $this->cObj->IMAGE($imgConf);
774 } else {
775 $imgsTag[$imgKey] = $this->cObj->IMAGE(Array('file' => $totalImagePath)); // currentValKey !!!
776 }
777 // Restore our ATagParams
778 $GLOBALS['TSFE']->ATagParams = $oldATagParms;
779 // Store the original filepath
780 $origImages[$imgKey] = $GLOBALS['TSFE']->lastImageInfo;
781
782 if ($GLOBALS['TSFE']->lastImageInfo[0]==0) {
783 $imageRowsFinalWidths[floor($a/$colCount)] += $this->cObj->data['imagewidth'];
784 } else {
785 $imageRowsFinalWidths[floor($a/$colCount)] += $GLOBALS['TSFE']->lastImageInfo[0];
786 }
787
788 }
789 // How much space will the image-block occupy?
790 $imageBlockWidth = max($imageRowsFinalWidths)+ $colspacing*($colCount-1) + $colCount*$border*($borderSpace+$borderThickness)*2;
791 $GLOBALS['TSFE']->register['rowwidth'] = $imageBlockWidth;
792 $GLOBALS['TSFE']->register['rowWidthPlusTextMargin'] = $imageBlockWidth + $textMargin;
793
794 // noRows is in fact just one ROW, with the amount of columns specified, where the images are placed in.
795 // noCols is just one COLUMN, each images placed side by side on each row
796 $noRows = $this->cObj->stdWrap($conf['noRows'], $conf['noRows.']);
797 $noCols = $this->cObj->stdWrap($conf['noCols'], $conf['noCols.']);
798 if ($noRows) {$noCols=0;} // noRows overrides noCols. They cannot exist at the same time.
799
800 $rowCount_temp = 1;
801 $colCount_temp = $colCount;
802 if ($noRows) {
803 $rowCount_temp = $rowCount;
804 $rowCount = 1;
805 }
806 if ($noCols) {
807 $colCount = 1;
808 $columnWidths = array();
809 }
810
811 // Edit icons:
812 if (!is_array($conf['editIcons.'])) {
813 $conf['editIcons.'] = array();
814 }
815 $editIconsHTML = $conf['editIcons'] && $GLOBALS['TSFE']->beUserLogin ? $this->cObj->editIcons('', $conf['editIcons'], $conf['editIcons.']) : '';
816
817 // If noRows, we need multiple imagecolumn wraps
818 $imageWrapCols = 1;
819 if ($noRows) { $imageWrapCols = $colCount; }
820
821 // User wants to separate the rows, but only do that if we do have rows
822 $separateRows = $this->cObj->stdWrap($conf['separateRows'], $conf['separateRows.']);
823 if ($noRows) { $separateRows = 0; }
824 if ($rowCount == 1) { $separateRows = 0; }
825
826 if ($accessibilityMode) {
827 $imagesInColumns = round(($imgCount / ($rowCount * $colCount)), 0, PHP_ROUND_HALF_UP);
828
829 // Apply optionSplit to the list of classes that we want to add to each column
830 $addClassesCol = $conf['addClassesCol'];
831 if (isset($conf['addClassesCol.'])) {
832 $addClassesCol = $this->cObj->stdWrap($addClassesCol, $conf['addClassesCol.']);
833 }
834 $addClassesColConf = $GLOBALS['TSFE']->tmpl->splitConfArray(array('addClassesCol' => $addClassesCol), $colCount);
835
836 // Apply optionSplit to the list of classes that we want to add to each image
837 $addClassesImage = $conf['addClassesImage'];
838 if (isset($conf['addClassesImage.'])) {
839 $addClassesImage = $this->cObj->stdWrap($addClassesImage, $conf['addClassesImage.']);
840 }
841 $addClassesImageConf = $GLOBALS['TSFE']->tmpl->splitConfArray(array('addClassesImage' => $addClassesImage), $imagesInColumns);
842
843 $rows = array();
844 $currentImage = 0;
845
846 // Set the class for the caption (split or global)
847 $classCaptionAlign = array(
848 'center' => 'csc-textpic-caption-c',
849 'right' => 'csc-textpic-caption-r',
850 'left' => 'csc-textpic-caption-l',
851 );
852
853 $captionAlign = $this->cObj->stdWrap($conf['captionAlign'], $conf['captionAlign.']);
854
855 // Iterate over the rows
856 for ($rowCounter = 1; $rowCounter <= $rowCount; $rowCounter++) {
857 $rowColumns = array();
858 // Iterate over the columns
859 for ($columnCounter = 1; $columnCounter <= $colCount; $columnCounter++) {
860 $columnImages = array();
861 // Iterate over the amount of images allowed in a column
862 for ($imagesCounter = 1; $imagesCounter <= $imagesInColumns; $imagesCounter++) {
863 $image = NULL;
864 $splitCaption = NULL;
865 $imageMarkers = $captionMarkers = array();
866 $single = '&nbsp;';
867
868 // Set the key of the current image
869 $imageKey = $currentImage + $imgStart;
870
871 // Register IMAGE_NUM_CURRENT for the caption
872 $GLOBALS['TSFE']->register['IMAGE_NUM_CURRENT'] = $imageKey;
873 $this->cObj->data[$this->cObj->currentValKey] = $origImages[$imageKey]['origFile'];
874
875 // Get the image if not an empty cell
876 if (isset($imgsTag[$imageKey])) {
877 $image = $this->cObj->stdWrap($imgsTag[$imageKey], $conf['imgTagStdWrap.']);
878
879 // Add the edit icons
880 if ($editIconsHTML) {
881 $image .= $this->cObj->stdWrap($editIconsHTML, $conf['editIconsStdWrap.']);
882 }
883
884 // Wrap the single image
885 $single = $this->cObj->stdWrap($image, $conf['singleStdWrap.']);
886
887 // Get the caption
888 if (!$renderGlobalCaption) {
889 $imageMarkers['caption'] = $this->cObj->stdWrap(
890 $this->cObj->cObjGet($conf['caption.'], 'caption.'), $conf['caption.']
891 );
892 if ($captionAlign) {
893 $captionMarkers['classes'] = ' ' . $classCaptionAlign[$captionAlign];
894 }
895
896 $imageMarkers['caption'] = $this->cObj->substituteMarkerArray(
897 $imageMarkers['caption'],
898 $captionMarkers,
899 '###|###',
900 1,
901 1
902 );
903 }
904
905 if ($addClassesImageConf[$imagesCounter - 1]['addClassesImage']) {
906 $imageMarkers['classes'] = ' ' . $addClassesImageConf[$imagesCounter - 1]['addClassesImage'];
907 }
908 }
909
910 $columnImages[] = $this->cObj->substituteMarkerArray(
911 $single,
912 $imageMarkers,
913 '###|###',
914 1,
915 1
916 );
917
918 $currentImage++;
919 }
920
921 $rowColumn = $this->cObj->stdWrap(
922 implode(LF, $columnImages),
923 $conf['columnStdWrap.']
924 );
925
926 // Start filling the markers for columnStdWrap
927 $columnMarkers = array();
928
929 if ($addClassesColConf[$columnCounter - 1]['addClassesCol']) {
930 $columnMarkers['classes'] = ' ' . $addClassesColConf[$columnCounter - 1]['addClassesCol'];
931 }
932
933 $rowColumns[] = $this->cObj->substituteMarkerArray(
934 $rowColumn,
935 $columnMarkers,
936 '###|###',
937 1,
938 1
939 );
940 }
941 if ($noRows) {
942 $rowConfiguration = $conf['noRowsStdWrap.'];
943 } elseif ($rowCounter == $rowCount) {
944 $rowConfiguration = $conf['lastRowStdWrap.'];
945 } else {
946 $rowConfiguration = $conf['rowStdWrap.'];
947 }
948
949 $row = $this->cObj->stdWrap(
950 implode(LF, $rowColumns),
951 $rowConfiguration
952 );
953
954 // Start filling the markers for columnStdWrap
955 $rowMarkers = array();
956
957 $rows[] = $this->cObj->substituteMarkerArray(
958 $row,
959 $rowMarkers,
960 '###|###',
961 1,
962 1
963 );
964 }
965
966 $images = $this->cObj->stdWrap(
967 implode(LF, $rows),
968 $conf['allStdWrap.']
969 );
970 // Start filling the markers for allStdWrap
971 $allMarkers = array();
972 $classes = array();
973
974 // Add the global caption to the allStdWrap marker array if set
975 if ($globalCaption) {
976 $allMarkers['caption'] = $globalCaption;
977 if ($captionAlign) {
978 $classes[] = $classCaptionAlign[$captionAlign];
979 }
980 }
981
982 // Add the border class if needed
983 if ($border){
984 $classes[] = $conf['borderClass'] ? $conf['borderClass'] : 'csc-textpic-border';
985 }
986
987 // Add the class for equal height if needed
988 if ($equalHeight) {
989 $classes[] = 'csc-textpic-equalheight';
990 }
991
992 $addClasses = $this->cObj->stdWrap($conf['addClasses'], $conf['addClasses.']);
993 if ($addClasses) {
994 $classes[] = $addClasses;
995 }
996
997 if ($classes) {
998 $class = ' ' . implode(' ', $classes);
999 }
1000
1001 // Fill the markers for the allStdWrap
1002 $images = $this->cObj->substituteMarkerArray(
1003 $images,
1004 $allMarkers,
1005 '###|###',
1006 1,
1007 1
1008 );
1009 } else {
1010 // Apply optionSplit to the list of classes that we want to add to each image
1011 $addClassesImage = $conf['addClassesImage'];
1012 if (isset($conf['addClassesImage.'])) {
1013 $addClassesImage = $this->cObj->stdWrap($addClassesImage, $conf['addClassesImage.']);
1014 }
1015 $addClassesImageConf = $GLOBALS['TSFE']->tmpl->splitConfArray(array('addClassesImage' => $addClassesImage), $colCount);
1016
1017 // Render the images
1018 $images = '';
1019 for ($c = 0; $c < $imageWrapCols; $c++) {
1020 $tmpColspacing = $colspacing;
1021 if (($c == $imageWrapCols - 1 && $imagePosition == 2) || ($c == 0 && ($imagePosition == 1 || $imagePosition == 0))) {
1022 // Do not add spacing after column if we are first column (left) or last column (center/right)
1023 $tmpColspacing = 0;
1024 }
1025
1026 $thisImages = '';
1027 $allRows = '';
1028 $maxImageSpace = 0;
1029 for ($i = $c; $i < count($imgsTag); $i = $i + $imageWrapCols) {
1030 $imgKey = $i + $imgStart;
1031 $colPos = $i % $colCount;
1032 if ($separateRows && $colPos == 0) {
1033 $thisRow = '';
1034 }
1035
1036 // Render one image
1037 if($origImages[$imgKey][0]==0) {
1038 $imageSpace = $this->cObj->data['imagewidth'] + $border * ($borderSpace + $borderThickness) * 2;
1039 } else {
1040 $imageSpace = $origImages[$imgKey][0] + $border * ($borderSpace + $borderThickness) * 2;
1041 }
1042
1043 $GLOBALS['TSFE']->register['IMAGE_NUM'] = $imgKey;
1044 $GLOBALS['TSFE']->register['IMAGE_NUM_CURRENT'] = $imgKey;
1045 $GLOBALS['TSFE']->register['ORIG_FILENAME'] = $origImages[$imgKey]['origFile'];
1046 $GLOBALS['TSFE']->register['imagewidth'] = $origImages[$imgKey][0];
1047 $GLOBALS['TSFE']->register['imagespace'] = $imageSpace;
1048 $GLOBALS['TSFE']->register['imageheight'] = $origImages[$imgKey][1];
1049 if ($imageSpace > $maxImageSpace) {
1050 $maxImageSpace = $imageSpace;
1051 }
1052 $thisImage = '';
1053 $thisImage .= $this->cObj->stdWrap($imgsTag[$imgKey], $conf['imgTagStdWrap.']);
1054
1055 if (!$renderGlobalCaption) {
1056 $thisImage .= $this->cObj->stdWrap($this->cObj->cObjGet($conf['caption.'], 'caption.'), $conf['caption.']);
1057 }
1058 if ($editIconsHTML) {
1059 $thisImage .= $this->cObj->stdWrap($editIconsHTML, $conf['editIconsStdWrap.']);
1060 }
1061 $thisImage = $this->cObj->stdWrap($thisImage, $conf['oneImageStdWrap.']);
1062 $classes = '';
1063 if ($addClassesImageConf[$colPos]['addClassesImage']) {
1064 $classes = ' ' . $addClassesImageConf[$colPos]['addClassesImage'];
1065 }
1066 $thisImage = str_replace('###CLASSES###', $classes, $thisImage);
1067
1068 if ($separateRows) {
1069 $thisRow .= $thisImage;
1070 } else {
1071 $allRows .= $thisImage;
1072 }
1073 $GLOBALS['TSFE']->register['columnwidth'] = $maxImageSpace + $tmpColspacing;
1074
1075
1076 // Close this row at the end (colCount), or the last row at the final end
1077 if ($separateRows && ($i + 1 == count($imgsTag))) {
1078 // Close the very last row with either normal configuration or lastRow stdWrap
1079 $allRows .= $this->cObj->stdWrap($thisRow, (is_array($conf['imageLastRowStdWrap.']) ? $conf['imageLastRowStdWrap.'] : $conf['imageRowStdWrap.']));
1080 } elseif ($separateRows && $colPos == $colCount - 1) {
1081 $allRows .= $this->cObj->stdWrap($thisRow, $conf['imageRowStdWrap.']);
1082 }
1083 }
1084 if ($separateRows) {
1085 $thisImages .= $allRows;
1086 } else {
1087 $thisImages .= $this->cObj->stdWrap($allRows, $conf['noRowsStdWrap.']);
1088 }
1089 if ($noRows) {
1090 // Only needed to make columns, rather than rows:
1091 $images .= $this->cObj->stdWrap($thisImages, $conf['imageColumnStdWrap.']);
1092 } else {
1093 $images .= $thisImages;
1094 }
1095 }
1096
1097 // Add the global caption, if not split
1098 if ($globalCaption) {
1099 $images .= $globalCaption;
1100 }
1101
1102 // CSS-classes
1103 $captionClass = '';
1104 $classCaptionAlign = array(
1105 'center' => 'csc-textpic-caption-c',
1106 'right' => 'csc-textpic-caption-r',
1107 'left' => 'csc-textpic-caption-l',
1108 );
1109 $captionAlign = $this->cObj->stdWrap($conf['captionAlign'], $conf['captionAlign.']);
1110 if ($captionAlign) {
1111 $captionClass = $classCaptionAlign[$captionAlign];
1112 }
1113 $borderClass = '';
1114 if ($border) {
1115 $borderClass = $conf['borderClass'] ? $conf['borderClass'] : 'csc-textpic-border';
1116 }
1117
1118 // Multiple classes with all properties, to be styled in CSS
1119 $class = '';
1120 $class .= ($borderClass ? ' ' . $borderClass : '');
1121 $class .= ($captionClass ? ' ' . $captionClass : '');
1122 $class .= ($equalHeight ? ' csc-textpic-equalheight' : '');
1123 $addClasses = $this->cObj->stdWrap($conf['addClasses'], $conf['addClasses.']);
1124 $class .= ($addClasses ? ' ' . $addClasses : '');
1125
1126 // Do we need a width in our wrap around images?
1127 $imgWrapWidth = '';
1128 if ($position == 0 || $position == 8) {
1129 // For 'center' we always need a width: without one, the margin:auto trick won't work
1130 $imgWrapWidth = $imageBlockWidth;
1131 }
1132 if ($rowCount > 1) {
1133 // For multiple rows we also need a width, so that the images will wrap
1134 $imgWrapWidth = $imageBlockWidth;
1135 }
1136 if ($globalCaption) {
1137 // If we have a global caption, we need the width so that the caption will wrap
1138 $imgWrapWidth = $imageBlockWidth;
1139 }
1140
1141 // Wrap around the whole image block
1142 $GLOBALS['TSFE']->register['totalwidth'] = $imgWrapWidth;
1143 if ($imgWrapWidth) {
1144 $images = $this->cObj->stdWrap($images, $conf['imageStdWrap.']);
1145 } else {
1146 $images = $this->cObj->stdWrap($images, $conf['imageStdWrapNoWidth.']);
1147 }
1148 }
1149
1150 $output = $this->cObj->cObjGetSingle($conf['layout'], $conf['layout.']);
1151 $output = str_replace('###TEXT###', $content, $output);
1152 $output = str_replace('###IMAGES###', $images, $output);
1153 $output = str_replace('###CLASSES###', $class, $output);
1154
1155 if ($conf['stdWrap.']) {
1156 $output = $this->cObj->stdWrap($output, $conf['stdWrap.']);
1157 }
1158
1159 return $output;
1160 }
1161
1162 /***********************************
1163 *
1164 * Rendering of Content Element properties:
1165 *
1166 ***********************************/
1167
1168 /**
1169 * Add top or bottom margin to the content element
1170 *
1171 * Constructs and adds a class to the content element. This class selector
1172 * and its declaration are added to the specific page styles.
1173 *
1174 * @param string $content Content input. Not used, ignore.
1175 * @param array $configuration TypoScript configuration
1176 * @return string The class name
1177 */
1178 public function renderSpace($content, array $configuration) {
1179 // Look for hook before running default code for function
1180 if (method_exists($this, 'hookRequest') && $hookObject = $this->hookRequest('renderSpace')) {
1181 return $hookObject->renderSpace($content, $configuration);
1182 }
1183
1184 if (isset($configuration['space']) && in_array($configuration['space'], array('before', 'after'))) {
1185 $constant = (int) $configuration['constant'];
1186
1187 if ($configuration['space'] === 'before') {
1188 $value = $constant + $this->cObj->data['spaceBefore'];
1189 $declaration = 'margin-top: ' . $value .'px;';
1190 } else {
1191 $value = $constant + $this->cObj->data['spaceAfter'];
1192 $declaration = 'margin-bottom: ' . $value . 'px;';
1193 }
1194
1195 if (!empty($value)) {
1196 if ($configuration['stdWrap.']) {
1197 $className = $this->cObj->stdWrap($value, $configuration['stdWrap.']);
1198 } else {
1199 $className = $value;
1200 }
1201
1202 $selector = '.' . trim($className);
1203
1204 $this->addPageStyle($selector, $declaration);
1205
1206 return $className;
1207 }
1208 }
1209 }
1210
1211
1212
1213
1214
1215
1216
1217
1218 /************************************
1219 *
1220 * Helper functions
1221 *
1222 ************************************/
1223
1224 /**
1225 * Returns a link text string which replaces underscores in filename with
1226 * blanks.
1227 *
1228 * Has the possibility to cut off FileType.
1229
1230 * @param array $links
1231 * array with [0] linked file icon, [1] text link
1232 * @param string $fileName
1233 * the name of the file to be linked (without path)
1234 * @param boolean $useSpaces
1235 * whether underscores in the file name should be replaced with spaces
1236 * @param boolean $cutFileExtension
1237 * whether the file extension should be removed
1238 *
1239 * @return array modified array with new link text
1240 */
1241 protected function beautifyFileLink(
1242 array $links, $fileName, $useSpaces = FALSE, $cutFileExtension = FALSE
1243 ) {
1244 $linkText = $fileName;
1245 if ($useSpaces) {
1246 $linkText = str_replace('_', ' ', $linkText);
1247 }
1248 if ($cutFileExtension) {
1249 $pos = strrpos($linkText, '.');
1250 $linkText = substr($linkText, 0, $pos);
1251 }
1252 $links[1] = str_replace(
1253 '>' . $fileName . '<', '>' . htmlspecialchars($linkText) . '<', $links[1]
1254 );
1255 return $links;
1256 }
1257
1258 /**
1259 * Returns table attributes for uploads / tables.
1260 *
1261 * @param array TypoScript configuration array
1262 * @param integer The "layout" type
1263 * @return array Array with attributes inside.
1264 */
1265 function getTableAttributes($conf, $type) {
1266
1267 // Initializing:
1268 $tableTagParams_conf = $conf['tableParams_'.$type.'.'];
1269
1270 $border = $this->cObj->data['table_border'] ? intval($this->cObj->data['table_border']) : $tableTagParams_conf['border'];
1271 $cellSpacing = $this->cObj->data['table_cellspacing'] ? intval($this->cObj->data['table_cellspacing']) : $tableTagParams_conf['cellspacing'];
1272 $cellPadding = $this->cObj->data['table_cellpadding'] ? intval($this->cObj->data['table_cellpadding']) : $tableTagParams_conf['cellpadding'];
1273 $summary = trim(htmlspecialchars($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'acctables_summary')));
1274
1275 // Create table attributes and classes array:
1276 $tableTagParams = $classes = array();
1277
1278 // Table attributes for all doctypes except HTML5
1279 if ($GLOBALS['TSFE']->config['config']['doctype'] !== 'html5') {
1280 $tableTagParams['border'] = $border;
1281 $tableTagParams['cellspacing'] = $cellSpacing;
1282 $tableTagParams['cellpadding'] = $cellPadding;
1283 if ($summary) {
1284 $tableTagParams['summary'] = $summary;
1285 }
1286
1287 // Some attributes are obsolete or have been changed in HTML5
1288 } else {
1289 if ($border) {
1290 // Border property has changed, now with class
1291 $borderClass = 'contenttable-border-' . $border;
1292 $borderDeclaration = 'border-width: ' . $border . 'px; border-style: solid;';
1293
1294 $this->addPageStyle('.' . $borderClass, $borderDeclaration);
1295
1296 $classes[] = $borderClass;
1297 }
1298 if ($cellSpacing) {
1299 // Border attribute for HTML5 is 1 when there is cell spacing
1300 $tableTagParams['border'] = 1;
1301 // Use CSS3 border-spacing in class to have cell spacing
1302 $cellSpacingClass = 'contenttable-cellspacing-' . $cellSpacing;
1303 $cellSpacingDeclaration = 'border-spacing: ' . $cellSpacing . 'px;';
1304
1305 $this->addPageStyle('.' . $cellSpacingClass, $cellSpacingDeclaration);
1306
1307 $classes[] = $cellSpacingClass;
1308 }
1309 if ($cellPadding) {
1310 // Cell padding property has changed, now with class
1311 $cellPaddingClass = 'contenttable-cellpadding-' . $cellPadding;
1312 $cellSpacingSelector = '.' . $cellPaddingClass . ' td, .' . $cellPaddingClass . ' th';
1313 $cellPaddingDeclaration = 'padding: ' . $cellPadding . 'px;';
1314
1315 $this->addPageStyle($cellSpacingSelector, $cellPaddingDeclaration);
1316
1317 $classes[] = $cellPaddingClass;
1318 }
1319 }
1320 // Background color is class
1321 if (
1322 isset($conf['color.'][$this->cObj->data['table_bgColor']]) &&
1323 !empty($conf['color.'][$this->cObj->data['table_bgColor']])
1324 ) {
1325 $classes[] = 'contenttable-color-' . $this->cObj->data['table_bgColor'];
1326 }
1327
1328 if (!empty($classes)) {
1329 $tableTagParams['class'] = ' ' . implode(' ', $classes);
1330 }
1331
1332 // Return result:
1333 return $tableTagParams;
1334 }
1335
1336 /**
1337 * Add a style to the page, specific for this page
1338 *
1339 * The selector can be a contextual selector, like '#id .class p'
1340 * The presence of the selector is checked to avoid multiple entries of the
1341 * same selector.
1342 *
1343 * @param string $selector The selector
1344 * @param string $declaration The declaration
1345 * @return void
1346 */
1347 protected function addPageStyle($selector, $declaration) {
1348 if (!isset($GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_cssstyledcontent.']['_CSS_PAGE_STYLE'])) {
1349 $GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_cssstyledcontent.']['_CSS_PAGE_STYLE'] = array();
1350 }
1351
1352 if (!isset($GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_cssstyledcontent.']['_CSS_PAGE_STYLE'][$selector])) {
1353 $GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_cssstyledcontent.']['_CSS_PAGE_STYLE'][$selector] = TAB . $selector .
1354 ' { ' . $declaration . ' }';
1355 }
1356 }
1357
1358 /**
1359 * Returns an object reference to the hook object if any
1360 *
1361 * @param string Name of the function you want to call / hook key
1362 * @return object Hook object, if any. Otherwise NULL.
1363 */
1364 function hookRequest($functionName) {
1365 global $TYPO3_CONF_VARS;
1366
1367 // Hook: menuConfig_preProcessModMenu
1368 if ($TYPO3_CONF_VARS['EXTCONF']['css_styled_content']['pi1_hooks'][$functionName]) {
1369 $hookObj = t3lib_div::getUserObj($TYPO3_CONF_VARS['EXTCONF']['css_styled_content']['pi1_hooks'][$functionName]);
1370 if (method_exists ($hookObj, $functionName)) {
1371 $hookObj->pObj = $this;
1372 return $hookObj;
1373 }
1374 }
1375 }
1376 }
1377 ?>