TYPO3 CMS  TYPO3_6-2
CssStyledContentController.php
Go to the documentation of this file.
1 <?php
3 
19 
27 
33  public $prefixId = 'tx_cssstyledcontent_pi1';
34 
40  public $scriptRelPath = 'pi1/class.tx_cssstyledcontent_pi1.php';
41 
47  public $extKey = 'css_styled_content';
48 
52  public $conf = array();
53 
54  /***********************************
55  * Rendering of Content Elements:
56  ***********************************/
57 
65  public function render_bullets($content, $conf) {
66  // Look for hook before running default code for function
67  if ($hookObj = $this->hookRequest('render_bullets')) {
68  return $hookObj->render_bullets($content, $conf);
69  } else {
70  // Get bodytext field content, returning blank if empty:
71  $field = isset($conf['field']) && trim($conf['field']) ? trim($conf['field']) : 'bodytext';
72  $content = trim($this->cObj->data[$field]);
73  if ($content === '') {
74  return '';
75  }
76  // Split into single lines:
77  $lines = GeneralUtility::trimExplode(LF, $content);
78  foreach ($lines as &$val) {
79  $val = '<li>' . $this->cObj->stdWrap($val, $conf['innerStdWrap.']) . '</li>';
80  }
81  unset($val);
82  // Set header type:
83  $type = (int)$this->cObj->data['layout'];
84  // Compile list:
85  $out = '
86  <ul class="csc-bulletlist csc-bulletlist-' . $type . '">' . implode('', $lines) . '
87  </ul>';
88  // Return value
89  return $out;
90  }
91  }
92 
100  public function render_table($content, $conf) {
101  // Look for hook before running default code for function
102  if ($hookObj = $this->hookRequest('render_table')) {
103  return $hookObj->render_table($content, $conf);
104  } else {
105  // Init FlexForm configuration
106  $this->pi_initPIflexForm();
107  // Get bodytext field content
108  $field = isset($conf['field']) && trim($conf['field']) ? trim($conf['field']) : 'bodytext';
109  $content = trim($this->cObj->data[$field]);
110  if ($content === '') {
111  return '';
112  }
113  // get flexform values
114  $caption = trim(htmlspecialchars($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'acctables_caption')));
115  $useTfoot = trim($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'acctables_tfoot'));
116  $headerPos = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'acctables_headerpos');
117  $noStyles = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'acctables_nostyles');
118  $tableClass = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'acctables_tableclass');
119  $delimiter = trim($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'tableparsing_delimiter', 's_parsing'));
120  if ($delimiter) {
121  $delimiter = chr((int)$delimiter);
122  } else {
123  $delimiter = '|';
124  }
125  $quotedInput = trim($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'tableparsing_quote', 's_parsing'));
126  if ($quotedInput) {
127  $quotedInput = chr((int)$quotedInput);
128  } else {
129  $quotedInput = '';
130  }
131  // Generate id prefix for accessible header
132  $headerScope = $headerPos == 'top' ? 'col' : 'row';
133  $headerIdPrefix = $headerScope . $this->cObj->data['uid'] . '-';
134  // Split into single lines (will become table-rows):
135  $rows = GeneralUtility::trimExplode(LF, $content);
136  reset($rows);
137  // Find number of columns to render:
139  $this->cObj->data['cols'] ? $this->cObj->data['cols'] : count(str_getcsv(current($rows), $delimiter, $quotedInput)),
140  0,
141  100
142  );
143  // Traverse rows (rendering the table here)
144  $rCount = count($rows);
145  foreach ($rows as $k => $v) {
146  $cells = str_getcsv($v, $delimiter, $quotedInput);
147  $newCells = array();
148  for ($a = 0; $a < $cols; $a++) {
149  if (trim($cells[$a]) === '') {
150  $cells[$a] = ' ';
151  $cells[$a] = preg_replace('|<br */?>|i', LF, $cells[$a]);
152  }
153  $cellAttribs = $noStyles ? '' : ($a > 0 && $cols - 1 == $a ? ' class="td-last td-' . $a . '"' : ' class="td-' . $a . '"');
154  if ($headerPos == 'top' && !$k || $headerPos == 'left' && !$a) {
155  $scope = ' scope="' . $headerScope . '"';
156  $scope .= ' id="' . $headerIdPrefix . ($headerScope == 'col' ? $a : $k) . '"';
157  $newCells[$a] = '
158  <th' . $cellAttribs . $scope . '>' . $this->cObj->stdWrap($cells[$a], $conf['innerStdWrap.']) . '</th>';
159  } else {
160  if (empty($headerPos)) {
161  $accessibleHeader = '';
162  } else {
163  $accessibleHeader = ' headers="' . $headerIdPrefix . ($headerScope == 'col' ? $a : $k) . '"';
164  }
165  $newCells[$a] = '
166  <td' . $cellAttribs . $accessibleHeader . '>' . $this->cObj->stdWrap($cells[$a], $conf['innerStdWrap.']) . '</td>';
167  }
168  }
169  if (!$noStyles) {
170  $oddEven = $k % 2 ? 'tr-odd' : 'tr-even';
171  $rowAttribs = $k > 0 && $rCount - 1 == $k ? ' class="' . $oddEven . ' tr-last"' : ' class="' . $oddEven . ' tr-' . $k . '"';
172  }
173  $rows[$k] = '
174  <tr' . $rowAttribs . '>' . implode('', $newCells) . '
175  </tr>';
176  }
177  $addTbody = 0;
178  $tableContents = '';
179  if ($caption) {
180  $tableContents .= '
181  <caption>' . $caption . '</caption>';
182  }
183  if ($headerPos == 'top' && $rows[0]) {
184  $tableContents .= '<thead>' . $rows[0] . '
185  </thead>';
186  unset($rows[0]);
187  $addTbody = 1;
188  }
189  if ($useTfoot) {
190  $tableContents .= '
191  <tfoot>' . $rows[($rCount - 1)] . '</tfoot>';
192  unset($rows[$rCount - 1]);
193  $addTbody = 1;
194  }
195  $tmpTable = implode('', $rows);
196  if ($addTbody) {
197  $tmpTable = '<tbody>' . $tmpTable . '</tbody>';
198  }
199  $tableContents .= $tmpTable;
200  // Set header type:
201  $type = (int)$this->cObj->data['layout'];
202  // Table tag params.
203  $tableTagParams = $this->getTableAttributes($conf, $type);
204  if (!$noStyles) {
205  $tableTagParams['class'] = 'contenttable contenttable-' . $type . ($tableClass ? ' ' . $tableClass : '') . $tableTagParams['class'];
206  } elseif ($tableClass) {
207  $tableTagParams['class'] = $tableClass;
208  }
209  // Compile table output:
210  $out = '
211  <table ' . GeneralUtility::implodeAttributes($tableTagParams) . '>' . $tableContents . '
212  </table>';
213  // Return value
214  return $out;
215  }
216  }
217 
225  public function render_uploads($content, $conf) {
226  // Look for hook before running default code for function
227  if ($hookObj = $this->hookRequest('render_uploads')) {
228  return $hookObj->render_uploads($content, $conf);
229  } else {
230  // Loading language-labels
231  $this->pi_loadLL();
232  $out = '';
233  // Set layout type:
234  $type = (int)$this->cObj->data['layout'];
235  // See if the file path variable is set, this takes precedence
236  $filePathConf = $this->cObj->stdWrap($conf['filePath'], $conf['filePath.']);
237  if ($filePathConf) {
238  $fileList = $this->cObj->filelist($filePathConf);
239  list($path) = explode('|', $filePathConf);
240  } else {
241  // Get the list of files from the field
242  $field = trim($conf['field']) ?: 'media';
243  $fileList = $this->cObj->data[$field];
244  $path = 'uploads/media/';
245  if (
246  is_array($GLOBALS['TCA']['tt_content']['columns'][$field]) &&
247  !empty($GLOBALS['TCA']['tt_content']['columns'][$field]['config']['uploadfolder'])
248  ) {
249  // In TCA-Array folders are saved without trailing slash, so $path.$fileName won't work
250  $path = $GLOBALS['TCA']['tt_content']['columns'][$field]['config']['uploadfolder'] . '/';
251  }
252  }
253  $path = trim($path);
254  // Explode into an array:
255  $fileArray = GeneralUtility::trimExplode(',', $fileList, TRUE);
256  // If there were files to list...:
257  if (count($fileArray)) {
258  // Get the descriptions for the files (if any):
259  $descriptions = GeneralUtility::trimExplode(LF, $this->cObj->data['imagecaption']);
260  // Get the titles for the files (if any)
261  $titles = GeneralUtility::trimExplode(LF, $this->cObj->data['titleText']);
262  // Get the alternative text for icons/thumbnails
263  $altTexts = GeneralUtility::trimExplode(LF, $this->cObj->data['altText']);
264  // Add the target to linkProc when explicitly set
265  if ($this->cObj->data['target']) {
266  $conf['linkProc.']['target'] = $this->cObj->data['target'];
267  unset($conf['linkProc.']['target.']);
268  }
269  // Adding hardcoded TS to linkProc configuration:
270  $conf['linkProc.']['path.']['current'] = 1;
271  if ($conf['linkProc.']['combinedLink']) {
272  $conf['linkProc.']['icon'] = $type > 0 ? 1 : 0;
273  } else {
274  // Always render icon - is inserted by PHP if needed.
275  $conf['linkProc.']['icon'] = 1;
276  // Temporary, internal split-token!
277  $conf['linkProc.']['icon.']['wrap'] = ' | //**//';
278  // ALways link the icon
279  $conf['linkProc.']['icon_link'] = 1;
280  }
281  $conf['linkProc.']['icon_image_ext_list'] = $type == 2 || $type == 3 ? $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'] : '';
282  // If the layout is type 2 or 3 we will render an image based icon if possible.
283  if ($conf['labelStdWrap.']) {
284  $conf['linkProc.']['labelStdWrap.'] = $conf['labelStdWrap.'];
285  }
286  if ($conf['useSpacesInLinkText'] || $conf['stripFileExtensionFromLinkText']) {
287  $conf['linkProc.']['removePrependedNumbers'] = 0;
288  }
289  // Traverse the files found:
290  $filesData = array();
291  foreach ($fileArray as $key => $fileName) {
293  if (@is_file($absPath)) {
294  $fI = pathinfo($fileName);
295  $filesData[$key] = array();
296  $currentPath = $path;
297  if (GeneralUtility::isFirstPartOfStr($fileName, '../../')) {
298  $currentPath = '';
299  $fileName = substr($fileName, 6);
300  }
301  $filesData[$key]['filename'] = $fileName;
302  $filesData[$key]['path'] = $currentPath;
303  $filesData[$key]['filesize'] = filesize($absPath);
304  $filesData[$key]['fileextension'] = strtolower($fI['extension']);
305  $filesData[$key]['description'] = trim($descriptions[$key]);
306  $filesData[$key]['titletext'] = trim($titles[$key]);
307  $filesData[$key]['alttext'] = trim($altTexts[$key]);
308  $conf['linkProc.']['title'] = trim($titles[$key]);
309  if (isset($altTexts[$key]) && !empty($altTexts[$key])) {
310  $altText = trim($altTexts[$key]);
311  } else {
312  $altText = sprintf($this->pi_getLL('uploads.icon'), $fileName);
313  }
314  $conf['linkProc.']['altText'] = ($conf['linkProc.']['iconCObject.']['altText'] = $altText);
315  $this->cObj->setCurrentVal($currentPath);
316  $GLOBALS['TSFE']->register['ICON_REL_PATH'] = $currentPath . $fileName;
317  $GLOBALS['TSFE']->register['filename'] = $filesData[$key]['filename'];
318  $GLOBALS['TSFE']->register['path'] = $filesData[$key]['path'];
319  $GLOBALS['TSFE']->register['fileSize'] = $filesData[$key]['filesize'];
320  $GLOBALS['TSFE']->register['fileExtension'] = $filesData[$key]['fileextension'];
321  $GLOBALS['TSFE']->register['description'] = $filesData[$key]['description'];
322  $GLOBALS['TSFE']->register['titleText'] = $filesData[$key]['titletext'];
323  $GLOBALS['TSFE']->register['altText'] = $filesData[$key]['alttext'];
324 
325  $filesData[$key]['linkedFilenameParts'] = $this->beautifyFileLink(
326  explode('//**//', $this->cObj->filelink($fileName, $conf['linkProc.'])),
327  $fileName,
328  $conf['useSpacesInLinkText'],
329  $conf['stripFileExtensionFromLinkText']
330  );
331  }
332  }
333  // optionSplit applied to conf to allow differnt settings per file
334  $splitConf = $GLOBALS['TSFE']->tmpl->splitConfArray($conf, count($filesData));
335  // Now, lets render the list!
336  $outputEntries = array();
337  foreach ($filesData as $key => $fileData) {
338  $GLOBALS['TSFE']->register['linkedIcon'] = $fileData['linkedFilenameParts'][0];
339  $GLOBALS['TSFE']->register['linkedLabel'] = $fileData['linkedFilenameParts'][1];
340  $GLOBALS['TSFE']->register['filename'] = $fileData['filename'];
341  $GLOBALS['TSFE']->register['path'] = $fileData['path'];
342  $GLOBALS['TSFE']->register['description'] = $fileData['description'];
343  $GLOBALS['TSFE']->register['fileSize'] = $fileData['filesize'];
344  $GLOBALS['TSFE']->register['fileExtension'] = $fileData['fileextension'];
345  $GLOBALS['TSFE']->register['titleText'] = $fileData['titletext'];
346  $GLOBALS['TSFE']->register['altText'] = $fileData['alttext'];
347  $outputEntries[] = $this->cObj->cObjGetSingle($splitConf[$key]['itemRendering'], $splitConf[$key]['itemRendering.']);
348  }
349  if (isset($conf['outerWrap'])) {
350  // Wrap around the whole content
351  $outerWrap = $this->cObj->stdWrap($conf['outerWrap'], $conf['outerWrap.']);
352  } else {
353  // Table tag params
354  $tableTagParams = $this->getTableAttributes($conf, $type);
355  $tableTagParams['class'] = 'csc-uploads csc-uploads-' . $type;
356  $outerWrap = '<table ' . GeneralUtility::implodeAttributes($tableTagParams) . '>|</table>';
357  }
358  // Compile it all into table tags:
359  $out = $this->cObj->wrap(implode('', $outputEntries), $outerWrap);
360  }
361  // Return value
362  return $out;
363  }
364  }
365 
376  protected function getImgColumnRelations($conf, $colCount) {
377  $relations = array();
378  $equalRelations = array_fill(0, $colCount, 1);
379  $colRelationsTypoScript = trim($this->cObj->stdWrap($conf['colRelations'], $conf['colRelations.']));
380  if ($colRelationsTypoScript) {
381  // Try to use column width relations given by TS
382  $relationParts = explode(':', $colRelationsTypoScript);
383  // Enough columns defined?
384  if (count($relationParts) >= $colCount) {
385  $out = array();
386  for ($a = 0; $a < $colCount; $a++) {
387  $currentRelationValue = (int)$relationParts[$a];
388  if ($currentRelationValue >= 1) {
389  $out[$a] = $currentRelationValue;
390  } else {
391  GeneralUtility::devLog('colRelations used with a value smaller than 1 therefore colRelations setting is ignored.', $this->extKey, 2);
392  unset($out);
393  break;
394  }
395  }
396  if (max($out) / min($out) <= 10) {
397  $relations = $out;
398  } else {
400  'The difference in size between the largest and smallest colRelation was not within' .
401  ' a factor of ten therefore colRelations setting is ignored..',
402  $this->extKey,
403  2
404  );
405  }
406  }
407  }
408  return $relations ?: $equalRelations;
409  }
410 
419  protected function getImgColumnWidths($conf, $colCount, $netW) {
420  $columnWidths = array();
421  $colRelations = $this->getImgColumnRelations($conf, $colCount);
422  $accumWidth = 0;
423  $accumDesiredWidth = 0;
424  $relUnitCount = array_sum($colRelations);
425  for ($a = 0; $a < $colCount; $a++) {
426  // This much width is available for the remaining images in this row (int)
427  $availableWidth = $netW - $accumWidth;
428  // Theoretical width of resized image. (float)
429  $desiredWidth = $netW / $relUnitCount * $colRelations[$a];
430  // Add this width. $accumDesiredWidth becomes the desired horizontal position
431  $accumDesiredWidth += $desiredWidth;
432  // Calculate width by comparing actual and desired horizontal position.
433  // this evenly distributes rounding errors across all images in this row.
434  $suggestedWidth = round($accumDesiredWidth - $accumWidth);
435  // finalImgWidth may not exceed $availableWidth
436  $finalImgWidth = (int)min($availableWidth, $suggestedWidth);
437  $accumWidth += $finalImgWidth;
438  $columnWidths[$a] = $finalImgWidth;
439  }
440  return $columnWidths;
441  }
442 
452  public function render_textpic($content, $conf) {
453  // Look for hook before running default code for function
454  if (method_exists($this, 'hookRequest') && ($hookObj = $this->hookRequest('render_textpic'))) {
455  return $hookObj->render_textpic($content, $conf);
456  }
457  $renderMethod = $this->cObj->stdWrap($conf['renderMethod'], $conf['renderMethod.']);
458  // Render using the default IMGTEXT code (table-based)
459  if (!$renderMethod || $renderMethod == 'table') {
460  return $this->cObj->IMGTEXT($conf);
461  }
462  $restoreRegisters = FALSE;
463  if (isset($conf['preRenderRegisters.'])) {
464  $restoreRegisters = TRUE;
465  $this->cObj->LOAD_REGISTER($conf['preRenderRegisters.'], 'LOAD_REGISTER');
466  }
467  // Specific configuration for the chosen rendering method
468  if (is_array($conf['rendering.'][$renderMethod . '.'])) {
469  $conf = array_replace_recursive($conf, $conf['rendering.'][$renderMethod . '.']);
470  }
471  // Image or Text with Image?
472  if (is_array($conf['text.'])) {
473  $content = $this->cObj->stdWrap($this->cObj->cObjGet($conf['text.'], 'text.'), $conf['text.']);
474  }
475  $imgList = trim($this->cObj->stdWrap($conf['imgList'], $conf['imgList.']));
476  if (!$imgList) {
477  // No images, that's easy
478  if ($restoreRegisters) {
479  $this->cObj->LOAD_REGISTER(array(), 'RESTORE_REGISTER');
480  }
481  return $content;
482  }
483  $imgs = GeneralUtility::trimExplode(',', $imgList, TRUE);
484  if (count($imgs) === 0) {
485  // The imgList was not empty but did only contain empty values
486  if ($restoreRegisters) {
487  $this->cObj->LOAD_REGISTER(array(), 'RESTORE_REGISTER');
488  }
489  return $content;
490  }
491  $imgStart = (int)$this->cObj->stdWrap($conf['imgStart'], $conf['imgStart.']);
492  $imgCount = count($imgs) - $imgStart;
493  $imgMax = (int)$this->cObj->stdWrap($conf['imgMax'], $conf['imgMax.']);
494  if ($imgMax) {
495  $imgCount = MathUtility::forceIntegerInRange($imgCount, 0, $imgMax);
496  }
497  $imgPath = $this->cObj->stdWrap($conf['imgPath'], $conf['imgPath.']);
498  // Does we need to render a "global caption" (below the whole image block)?
499  $renderGlobalCaption = !$conf['captionSplit'] && !$conf['imageTextSplit'] && is_array($conf['caption.']);
500  if ($imgCount == 1) {
501  // If we just have one image, the caption relates to the image, so it is not "global"
502  $renderGlobalCaption = FALSE;
503  }
504  $imgListContainsReferenceUids = (bool)(isset($conf['imgListContainsReferenceUids.'])
505  ? $this->cObj->stdWrap($conf['imgListContainsReferenceUids'], $conf['imgListContainsReferenceUids.'])
506  : $conf['imgListContainsReferenceUids']);
507  // Use the calculated information (amount of images, if global caption is wanted) to choose a different rendering method for the images-block
508  $GLOBALS['TSFE']->register['imageCount'] = $imgCount;
509  $GLOBALS['TSFE']->register['renderGlobalCaption'] = $renderGlobalCaption;
510  $fallbackRenderMethod = '';
511  if ($conf['fallbackRendering']) {
512  $fallbackRenderMethod = $this->cObj->cObjGetSingle($conf['fallbackRendering'], $conf['fallbackRendering.']);
513  }
514  if ($fallbackRenderMethod && is_array($conf['rendering.'][$fallbackRenderMethod . '.'])) {
515  $conf = array_replace_recursive($conf, $conf['rendering.'][$fallbackRenderMethod . '.']);
516  }
517  // Set the accessibility mode which uses a different type of markup, used 4.7+
518  $accessibilityMode = FALSE;
519  if (strpos(strtolower($renderMethod), 'caption') || strpos(strtolower($fallbackRenderMethod), 'caption')) {
520  $accessibilityMode = TRUE;
521  }
522  // Global caption
523  $globalCaption = '';
524  if ($renderGlobalCaption) {
525  $globalCaption = $this->cObj->stdWrap($this->cObj->cObjGet($conf['caption.'], 'caption.'), $conf['caption.']);
526  }
527  // Positioning
528  $position = $this->cObj->stdWrap($conf['textPos'], $conf['textPos.']);
529  // 0,1,2 = center,right,left
530  $imagePosition = $position & 7;
531  // 0,8,16,24 (above,below,intext,intext-wrap)
532  $contentPosition = $position & 24;
533  $textMargin = (int)$this->cObj->stdWrap($conf['textMargin'], $conf['textMargin.']);
534  if (!$conf['textMargin_outOfText'] && $contentPosition < 16) {
535  $textMargin = 0;
536  }
537  $colspacing = (int)$this->cObj->stdWrap($conf['colSpace'], $conf['colSpace.']);
538  $border = (int)$this->cObj->stdWrap($conf['border'], $conf['border.']) ? 1 : 0;
539  $borderThickness = (int)$this->cObj->stdWrap($conf['borderThick'], $conf['borderThick.']);
540  $borderThickness = $borderThickness ?: 1;
541  $borderSpace = $conf['borderSpace'] && $border ? (int)$conf['borderSpace'] : 0;
542  // Generate cols
543  $cols = (int)$this->cObj->stdWrap($conf['cols'], $conf['cols.']);
544  $colCount = $cols > 1 ? $cols : 1;
545  if ($colCount > $imgCount) {
546  $colCount = $imgCount;
547  }
548  $rowCount = ceil($imgCount / $colCount);
549  // Generate rows
550  $rows = (int)$this->cObj->stdWrap($conf['rows'], $conf['rows.']);
551  if ($rows > 1) {
552  $rowCount = $rows;
553  if ($rowCount > $imgCount) {
554  $rowCount = $imgCount;
555  }
556  $colCount = $rowCount > 1 ? ceil($imgCount / $rowCount) : $imgCount;
557  }
558  // Max Width
559  $maxW = (int)$this->cObj->stdWrap($conf['maxW'], $conf['maxW.']);
560  $maxWInText = (int)$this->cObj->stdWrap($conf['maxWInText'], $conf['maxWInText.']);
561  $fiftyPercentWidthInText = round($maxW / 100 * 50);
562  // in Text
563  if ($contentPosition >= 16) {
564  if (!$maxWInText) {
565  // If maxWInText is not set, it's calculated to the 50% of the max
566  $maxW = $fiftyPercentWidthInText;
567  } else {
568  $maxW = $maxWInText;
569  }
570  }
571  // max usuable width for images (without spacers and borders)
572  $netW = $maxW - $colspacing * ($colCount - 1) - $colCount * $border * ($borderThickness + $borderSpace) * 2;
573  // Specify the maximum width for each column
574  $columnWidths = $this->getImgColumnWidths($conf, $colCount, $netW);
575  $image_compression = (int)$this->cObj->stdWrap($conf['image_compression'], $conf['image_compression.']);
576  $image_effects = (int)$this->cObj->stdWrap($conf['image_effects'], $conf['image_effects.']);
577  $image_frames = (int)$this->cObj->stdWrap($conf['image_frames.']['key'], $conf['image_frames.']['key.']);
578  // EqualHeight
579  $equalHeight = (int)$this->cObj->stdWrap($conf['equalH'], $conf['equalH.']);
580  if ($equalHeight) {
581  $relations_cols = array();
582  // contains the individual width of all images after scaling to $equalHeight
583  $imgWidths = array();
584  for ($a = 0; $a < $imgCount; $a++) {
585  $imgKey = $a + $imgStart;
586 
588  if (MathUtility::canBeInterpretedAsInteger($imgs[$imgKey])) {
589  if ($imgListContainsReferenceUids) {
590  $file = $this->getResourceFactory()->getFileReferenceObject((int)$imgs[$imgKey])->getOriginalFile();
591  } else {
592  $file = $this->getResourceFactory()->getFileObject((int)$imgs[$imgKey]);
593  }
594 
595  } else {
596  $file = $this->getResourceFactory()->getFileObjectFromCombinedIdentifier($imgPath . $imgs[$imgKey]);
597  }
598 
599  // relationship between the original height and the wished height
600  $rel = $file->getProperty('height') / $equalHeight;
601  // if relations is zero, then the addition of this value is omitted as the image is not expected to display because of some error.
602  if ($rel) {
603  $imgWidths[$a] = $file->getProperty('width') / $rel;
604  // counts the total width of the row with the new height taken into consideration.
605  $relations_cols[(int)floor($a / $colCount)] += $imgWidths[$a];
606  }
607  }
608  }
609  // Fetches pictures
610  $splitArr = array();
611  $splitArr['imgObjNum'] = $conf['imgObjNum'];
612  $splitArr = $GLOBALS['TSFE']->tmpl->splitConfArray($splitArr, $imgCount);
613  // Contains the width of every image row
614  $imageRowsFinalWidths = array();
615  // Array index of $imgsTag will be the same as in $imgs, but $imgsTag only contains the images that are actually shown
616  $imgsTag = array();
617  $origImages = array();
618  $rowIdx = 0;
619  for ($a = 0; $a < $imgCount; $a++) {
620  $imgKey = $a + $imgStart;
621  // If the image cannot be interpreted as integer (therefore filename and no FAL id), add the image path
622  if (MathUtility::canBeInterpretedAsInteger($imgs[$imgKey])) {
623  $totalImagePath = (int)$imgs[$imgKey];
624  $this->initializeCurrentFileInContentObjectRenderer($totalImagePath, $imgListContainsReferenceUids);
625  } else {
626  $totalImagePath = $imgPath . $imgs[$imgKey];
627  }
628  // register IMG_NUM is kept for backwards compatibility
629  $GLOBALS['TSFE']->register['IMAGE_NUM'] = $imgKey;
630  $GLOBALS['TSFE']->register['IMAGE_NUM_CURRENT'] = $imgKey;
631  $GLOBALS['TSFE']->register['ORIG_FILENAME'] = $totalImagePath;
632  $this->cObj->data[$this->cObj->currentValKey] = $totalImagePath;
633  $imgObjNum = (int)$splitArr[$a]['imgObjNum'];
634  $imgConf = $conf[$imgObjNum . '.'];
635  if ($equalHeight) {
636  if ($a % $colCount == 0) {
637  // A new row starts
638  // Reset accumulated net width
639  $accumWidth = 0;
640  // Reset accumulated desired width
641  $accumDesiredWidth = 0;
642  $rowTotalMaxW = $relations_cols[$rowIdx];
643  if ($rowTotalMaxW > $netW && $netW > 0) {
644  $scale = $rowTotalMaxW / $netW;
645  } else {
646  $scale = 1;
647  }
648  $desiredHeight = $equalHeight / $scale;
649  $rowIdx++;
650  }
651  // This much width is available for the remaining images in this row (int)
652  $availableWidth = $netW - $accumWidth;
653  // Theoretical width of resized image. (float)
654  $desiredWidth = $imgWidths[$a] / $scale;
655  // Add this width. $accumDesiredWidth becomes the desired horizontal position
656  $accumDesiredWidth += $desiredWidth;
657  // Calculate width by comparing actual and desired horizontal position.
658  // this evenly distributes rounding errors across all images in this row.
659  $suggestedWidth = round($accumDesiredWidth - $accumWidth);
660  // finalImgWidth may not exceed $availableWidth
661  $finalImgWidth = (int)min($availableWidth, $suggestedWidth);
662  $accumWidth += $finalImgWidth;
663  $imgConf['file.']['width'] = $finalImgWidth;
664  $imgConf['file.']['height'] = round($desiredHeight);
665  // other stuff will be calculated accordingly:
666  unset($imgConf['file.']['maxW']);
667  unset($imgConf['file.']['maxH']);
668  unset($imgConf['file.']['minW']);
669  unset($imgConf['file.']['minH']);
670  unset($imgConf['file.']['width.']);
671  unset($imgConf['file.']['maxW.']);
672  unset($imgConf['file.']['maxH.']);
673  unset($imgConf['file.']['minW.']);
674  unset($imgConf['file.']['minH.']);
675  } else {
676  $imgConf['file.']['maxW'] = $columnWidths[$a % $colCount];
677  }
678  $titleInLink = $this->cObj->stdWrap($imgConf['titleInLink'], $imgConf['titleInLink.']);
679  $titleInLinkAndImg = $this->cObj->stdWrap($imgConf['titleInLinkAndImg'], $imgConf['titleInLinkAndImg.']);
680  $oldATagParms = $GLOBALS['TSFE']->ATagParams;
681  if ($titleInLink) {
682  // Title in A-tag instead of IMG-tag
683  $titleText = trim($this->cObj->stdWrap($imgConf['titleText'], $imgConf['titleText.']));
684  if ($titleText) {
685  // This will be used by the IMAGE call later:
686  $GLOBALS['TSFE']->ATagParams .= ' title="' . htmlspecialchars($titleText) . '"';
687  }
688  }
689 
690  // hook to allow custom rendering of a single element
691  // This hook is needed to render alternative content which is not just a plain image,
692  // like showing other FAL content, like videos, things which need to be embedded as JS, ...
693  $customRendering = '';
694  if (isset($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['css_styled_content']['pi1_hooks']['render_singleMediaElement'])
695  && is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['css_styled_content']['pi1_hooks']['render_singleMediaElement'])) {
696  $hookParameters = array(
697  'file' => $totalImagePath,
698  'imageConfiguration' => $imgConf
699  );
700 
701  foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['css_styled_content']['pi1_hooks']['render_singleMediaElement'] as $reference) {
702  $customRendering = \TYPO3\CMS\Core\Utility\GeneralUtility::callUserFunction($reference, $hookParameters, $this);
703  // if there is a renderer found, don't run through the other renderers
704  if (!empty($customRendering)) {
705  break;
706  }
707  }
708  }
709 
710  if (!empty($customRendering)) {
711  $imgsTag[$imgKey] = $customRendering;
712  } elseif ($imgConf || $imgConf['file']) {
713  if ($this->cObj->image_effects[$image_effects]) {
714  $imgConf['file.']['params'] .= ' ' . $this->cObj->image_effects[$image_effects];
715  }
716  if ($image_frames) {
717  if (is_array($conf['image_frames.'][$image_frames . '.'])) {
718  $imgConf['file.']['m.'] = $conf['image_frames.'][$image_frames . '.'];
719  }
720  }
721  if ($image_compression && $imgConf['file'] != 'GIFBUILDER') {
722  if ($image_compression == 1) {
723  $tempImport = $imgConf['file.']['import'];
724  $tempImport_dot = $imgConf['file.']['import.'];
725  $tempTreatIdAsReference = $imgConf['file.']['treatIdAsReference'];
726  unset($imgConf['file.']);
727  $imgConf['file.']['import'] = $tempImport;
728  $imgConf['file.']['import.'] = $tempImport_dot;
729  $imgConf['file.']['treatIdAsReference'] = $tempTreatIdAsReference;
730  } elseif (isset($this->cObj->image_compression[$image_compression])) {
731  $imgConf['file.']['params'] .= ' ' . $this->cObj->image_compression[$image_compression]['params'];
732  $imgConf['file.']['ext'] = $this->cObj->image_compression[$image_compression]['ext'];
733  unset($imgConf['file.']['ext.']);
734  }
735  }
736  if ($titleInLink && !$titleInLinkAndImg) {
737  // Check if the image will be linked
738  $link = $this->cObj->imageLinkWrap('', $this->cObj->getCurrentFile() ?: $totalImagePath, $imgConf['imageLinkWrap.']);
739  if ($link) {
740  // Title in A-tag only (set above: ATagParams), not in IMG-tag
741  unset($imgConf['titleText']);
742  unset($imgConf['titleText.']);
743  $imgConf['emptyTitleHandling'] = 'removeAttr';
744  }
745  }
746  $imgsTag[$imgKey] = $this->cObj->IMAGE($imgConf);
747  } else {
748  // currentValKey !!!
749  $imgsTag[$imgKey] = $this->cObj->IMAGE(array('file' => $totalImagePath));
750  }
751  // Restore our ATagParams
752  $GLOBALS['TSFE']->ATagParams = $oldATagParms;
753  // Store the original filepath
754  $origImages[$imgKey] = $GLOBALS['TSFE']->lastImageInfo;
755  if ($GLOBALS['TSFE']->lastImageInfo[0] == 0) {
756  $imageRowsFinalWidths[(int)floor($a / $colCount)] += $this->cObj->data['imagewidth'];
757  } else {
758  $imageRowsFinalWidths[(int)floor($a / $colCount)] += $GLOBALS['TSFE']->lastImageInfo[0];
759  }
760  }
761  // How much space will the image-block occupy?
762  $imageBlockWidth = max($imageRowsFinalWidths) + $colspacing * ($colCount - 1) + $colCount * $border * ($borderSpace + $borderThickness) * 2;
763  $GLOBALS['TSFE']->register['rowwidth'] = $imageBlockWidth;
764  $GLOBALS['TSFE']->register['rowWidthPlusTextMargin'] = $imageBlockWidth + $textMargin;
765  // noRows is in fact just one ROW, with the amount of columns specified, where the images are placed in.
766  // noCols is just one COLUMN, each images placed side by side on each row
767  $noRows = $this->cObj->stdWrap($conf['noRows'], $conf['noRows.']);
768  $noCols = $this->cObj->stdWrap($conf['noCols'], $conf['noCols.']);
769  // noRows overrides noCols. They cannot exist at the same time.
770  if ($noRows) {
771  $noCols = 0;
772  $rowCount = 1;
773  }
774  if ($noCols) {
775  $colCount = 1;
776  }
777  // Edit icons:
778  if (!is_array($conf['editIcons.'])) {
779  $conf['editIcons.'] = array();
780  }
781  $editIconsHTML = $conf['editIcons'] && $GLOBALS['TSFE']->beUserLogin ? $this->cObj->editIcons('', $conf['editIcons'], $conf['editIcons.']) : '';
782  // If noRows, we need multiple imagecolumn wraps
783  $imageWrapCols = 1;
784  if ($noRows) {
785  $imageWrapCols = $colCount;
786  }
787  // User wants to separate the rows, but only do that if we do have rows
788  $separateRows = $this->cObj->stdWrap($conf['separateRows'], $conf['separateRows.']);
789  if ($noRows) {
790  $separateRows = 0;
791  }
792  if ($rowCount == 1) {
793  $separateRows = 0;
794  }
795  if ($accessibilityMode) {
796  $imagesInColumns = round($imgCount / ($rowCount * $colCount), 0, PHP_ROUND_HALF_UP);
797  // Apply optionSplit to the list of classes that we want to add to each column
798  $addClassesCol = $conf['addClassesCol'];
799  if (isset($conf['addClassesCol.'])) {
800  $addClassesCol = $this->cObj->stdWrap($addClassesCol, $conf['addClassesCol.']);
801  }
802  $addClassesColConf = $GLOBALS['TSFE']->tmpl->splitConfArray(array('addClassesCol' => $addClassesCol), $colCount);
803  // Apply optionSplit to the list of classes that we want to add to each image
804  $addClassesImage = $conf['addClassesImage'];
805  if (isset($conf['addClassesImage.'])) {
806  $addClassesImage = $this->cObj->stdWrap($addClassesImage, $conf['addClassesImage.']);
807  }
808  $addClassesImageConf = $GLOBALS['TSFE']->tmpl->splitConfArray(array('addClassesImage' => $addClassesImage), $imagesInColumns);
809  $rows = array();
810  $currentImage = 0;
811  // Set the class for the caption (split or global)
812  $classCaptionAlign = array(
813  'center' => 'csc-textpic-caption-c',
814  'right' => 'csc-textpic-caption-r',
815  'left' => 'csc-textpic-caption-l'
816  );
817  $captionAlign = $this->cObj->stdWrap($conf['captionAlign'], $conf['captionAlign.']);
818  // Iterate over the rows
819  for ($rowCounter = 1; $rowCounter <= $rowCount; $rowCounter++) {
820  $rowColumns = array();
821  // Iterate over the columns
822  for ($columnCounter = 1; $columnCounter <= $colCount; $columnCounter++) {
823  $columnImages = array();
824  // Iterate over the amount of images allowed in a column
825  for ($imagesCounter = 1; $imagesCounter <= $imagesInColumns; $imagesCounter++) {
826  $image = NULL;
827  $splitCaption = NULL;
828  $imageMarkers = ($captionMarkers = array());
829  $single = '&nbsp;';
830  // Set the key of the current image
831  $imageKey = $currentImage + $imgStart;
832  // Register IMAGE_NUM_CURRENT for the caption
833  $GLOBALS['TSFE']->register['IMAGE_NUM_CURRENT'] = $imageKey;
834  $this->cObj->data[$this->cObj->currentValKey] = $origImages[$imageKey]['origFile'];
835  if (MathUtility::canBeInterpretedAsInteger($imgs[$imageKey])) {
836  $this->initializeCurrentFileInContentObjectRenderer((int)$imgs[$imageKey], $imgListContainsReferenceUids);
837  } elseif (!isset($imgs[$imageKey])) {
838  // If not all columns in the last row are filled $imageKey gets larger than
839  // the array. In that case we clear the current file.
840  $this->cObj->setCurrentFile(NULL);
841  }
842  // Get the image if not an empty cell
843  if (isset($imgsTag[$imageKey])) {
844  $image = $this->cObj->stdWrap($imgsTag[$imageKey], $conf['imgTagStdWrap.']);
845  // Add the edit icons
846  if ($editIconsHTML) {
847  $image .= $this->cObj->stdWrap($editIconsHTML, $conf['editIconsStdWrap.']);
848  }
849  // Wrap the single image
850  $single = $this->cObj->stdWrap($image, $conf['singleStdWrap.']);
851  // Get the caption
852  if (!$renderGlobalCaption) {
853  $imageMarkers['caption'] = $this->cObj->stdWrap($this->cObj->cObjGet($conf['caption.'], 'caption.'), $conf['caption.']);
854  if ($captionAlign) {
855  $captionMarkers['classes'] = ' ' . $classCaptionAlign[$captionAlign];
856  }
857  $imageMarkers['caption'] = $this->cObj->substituteMarkerArray($imageMarkers['caption'], $captionMarkers, '###|###', 1, 1);
858  }
859  if ($addClassesImageConf[$imagesCounter - 1]['addClassesImage']) {
860  $imageMarkers['classes'] = ' ' . $addClassesImageConf[($imagesCounter - 1)]['addClassesImage'];
861  }
862  }
863  $columnImages[] = $this->cObj->substituteMarkerArray($single, $imageMarkers, '###|###', 1, 1);
864  $currentImage++;
865  }
866  $rowColumn = $this->cObj->stdWrap(implode(LF, $columnImages), $conf['columnStdWrap.']);
867  // Start filling the markers for columnStdWrap
868  $columnMarkers = array();
869  if ($addClassesColConf[$columnCounter - 1]['addClassesCol']) {
870  $columnMarkers['classes'] = ' ' . $addClassesColConf[($columnCounter - 1)]['addClassesCol'];
871  }
872  $rowColumns[] = $this->cObj->substituteMarkerArray($rowColumn, $columnMarkers, '###|###', 1, 1);
873  }
874  if ($noRows) {
875  $rowConfiguration = $conf['noRowsStdWrap.'];
876  } elseif ($rowCounter == $rowCount) {
877  $rowConfiguration = $conf['lastRowStdWrap.'];
878  } else {
879  $rowConfiguration = $conf['rowStdWrap.'];
880  }
881  $row = $this->cObj->stdWrap(implode(LF, $rowColumns), $rowConfiguration);
882  // Start filling the markers for columnStdWrap
883  $rowMarkers = array();
884  $rows[] = $this->cObj->substituteMarkerArray($row, $rowMarkers, '###|###', 1, 1);
885  }
886  $images = $this->cObj->stdWrap(implode(LF, $rows), $conf['allStdWrap.']);
887  // Start filling the markers for allStdWrap
888  $allMarkers = array();
889  $classes = array();
890  // Add the global caption to the allStdWrap marker array if set
891  if ($globalCaption) {
892  $allMarkers['caption'] = $globalCaption;
893  if ($captionAlign) {
894  $classes[] = $classCaptionAlign[$captionAlign];
895  }
896  }
897  // Set the margin for image + text, no wrap always to avoid multiple stylesheets
898  $noWrapMargin = (int)(($maxWInText ? $maxWInText : $fiftyPercentWidthInText) + (int)$this->cObj->stdWrap($conf['textMargin'], $conf['textMargin.']));
899  $this->addPageStyle('.csc-textpic-intext-right-nowrap .csc-textpic-text', 'margin-right: ' . $noWrapMargin . 'px;');
900  $this->addPageStyle('.csc-textpic-intext-left-nowrap .csc-textpic-text', 'margin-left: ' . $noWrapMargin . 'px;');
901  // Beside Text where the image block width is not equal to maxW
902  if ($contentPosition == 24 && $maxW != $imageBlockWidth) {
903  $noWrapMargin = $imageBlockWidth + $textMargin;
904  // Beside Text, Right
905  if ($imagePosition == 1) {
906  $this->addPageStyle('.csc-textpic-intext-right-nowrap-' . $noWrapMargin . ' .csc-textpic-text', 'margin-right: ' . $noWrapMargin . 'px;');
907  $classes[] = 'csc-textpic-intext-right-nowrap-' . $noWrapMargin;
908  } elseif ($imagePosition == 2) {
909  $this->addPageStyle('.csc-textpic-intext-left-nowrap-' . $noWrapMargin . ' .csc-textpic-text', 'margin-left: ' . $noWrapMargin . 'px;');
910  $classes[] = 'csc-textpic-intext-left-nowrap-' . $noWrapMargin;
911  }
912  }
913  // Add the border class if needed
914  if ($border) {
915  $classes[] = $conf['borderClass'] ?: 'csc-textpic-border';
916  }
917  // Add the class for equal height if needed
918  if ($equalHeight) {
919  $classes[] = 'csc-textpic-equalheight';
920  }
921  $addClasses = $this->cObj->stdWrap($conf['addClasses'], $conf['addClasses.']);
922  if ($addClasses) {
923  $classes[] = $addClasses;
924  }
925  if ($classes) {
926  $class = ' ' . implode(' ', $classes);
927  }
928  // Fill the markers for the allStdWrap
929  $images = $this->cObj->substituteMarkerArray($images, $allMarkers, '###|###', 1, 1);
930  } else {
931  // Apply optionSplit to the list of classes that we want to add to each image
932  $addClassesImage = $conf['addClassesImage'];
933  if (isset($conf['addClassesImage.'])) {
934  $addClassesImage = $this->cObj->stdWrap($addClassesImage, $conf['addClassesImage.']);
935  }
936  $addClassesImageConf = $GLOBALS['TSFE']->tmpl->splitConfArray(array('addClassesImage' => $addClassesImage), $colCount);
937  // Render the images
938  $images = '';
939  for ($c = 0; $c < $imageWrapCols; $c++) {
940  $tmpColspacing = $colspacing;
941  if ($c == $imageWrapCols - 1 && $imagePosition == 2 || $c == 0 && ($imagePosition == 1 || $imagePosition == 0)) {
942  // Do not add spacing after column if we are first column (left) or last column (center/right)
943  $tmpColspacing = 0;
944  }
945  $thisImages = '';
946  $allRows = '';
947  $maxImageSpace = 0;
948  $imgsTagCount = count($imgsTag);
949  for ($i = $c; $i < $imgsTagCount; $i = $i + $imageWrapCols) {
950  $imgKey = $i + $imgStart;
951  $colPos = $i % $colCount;
952  if ($separateRows && $colPos == 0) {
953  $thisRow = '';
954  }
955  // Render one image
956  if ($origImages[$imgKey][0] == 0) {
957  $imageSpace = $this->cObj->data['imagewidth'] + $border * ($borderSpace + $borderThickness) * 2;
958  } else {
959  $imageSpace = $origImages[$imgKey][0] + $border * ($borderSpace + $borderThickness) * 2;
960  }
961  $GLOBALS['TSFE']->register['IMAGE_NUM'] = $imgKey;
962  $GLOBALS['TSFE']->register['IMAGE_NUM_CURRENT'] = $imgKey;
963  $GLOBALS['TSFE']->register['ORIG_FILENAME'] = $origImages[$imgKey]['origFile'];
964  $GLOBALS['TSFE']->register['imagewidth'] = $origImages[$imgKey][0];
965  $GLOBALS['TSFE']->register['imagespace'] = $imageSpace;
966  $GLOBALS['TSFE']->register['imageheight'] = $origImages[$imgKey][1];
967  if (MathUtility::canBeInterpretedAsInteger($imgs[$imgKey])) {
968  $this->initializeCurrentFileInContentObjectRenderer(intval($imgs[$imgKey]), $imgListContainsReferenceUids);
969  }
970  if ($imageSpace > $maxImageSpace) {
971  $maxImageSpace = $imageSpace;
972  }
973  $thisImage = '';
974  $thisImage .= $this->cObj->stdWrap($imgsTag[$imgKey], $conf['imgTagStdWrap.']);
975  if (!$renderGlobalCaption) {
976  $thisImage .= $this->cObj->stdWrap($this->cObj->cObjGet($conf['caption.'], 'caption.'), $conf['caption.']);
977  }
978  if ($editIconsHTML) {
979  $thisImage .= $this->cObj->stdWrap($editIconsHTML, $conf['editIconsStdWrap.']);
980  }
981  $thisImage = $this->cObj->stdWrap($thisImage, $conf['oneImageStdWrap.']);
982  $classes = '';
983  if ($addClassesImageConf[$colPos]['addClassesImage']) {
984  $classes = ' ' . $addClassesImageConf[$colPos]['addClassesImage'];
985  }
986  $thisImage = str_replace('###CLASSES###', $classes, $thisImage);
987  if ($separateRows) {
988  $thisRow .= $thisImage;
989  } else {
990  $allRows .= $thisImage;
991  }
992  $GLOBALS['TSFE']->register['columnwidth'] = $maxImageSpace + $tmpColspacing;
993  // Close this row at the end (colCount), or the last row at the final end
994  if ($separateRows && $i + 1 == count($imgsTag)) {
995  // Close the very last row with either normal configuration or lastRow stdWrap
996  $allRows .= $this->cObj->stdWrap(
997  $thisRow,
998  is_array($conf['imageLastRowStdWrap.']) ? $conf['imageLastRowStdWrap.'] : $conf['imageRowStdWrap.']
999  );
1000  } elseif ($separateRows && $colPos == $colCount - 1) {
1001  $allRows .= $this->cObj->stdWrap($thisRow, $conf['imageRowStdWrap.']);
1002  }
1003  }
1004  if ($separateRows) {
1005  $thisImages .= $allRows;
1006  } else {
1007  $thisImages .= $this->cObj->stdWrap($allRows, $conf['noRowsStdWrap.']);
1008  }
1009  if ($noRows) {
1010  // Only needed to make columns, rather than rows:
1011  $images .= $this->cObj->stdWrap($thisImages, $conf['imageColumnStdWrap.']);
1012  } else {
1013  $images .= $thisImages;
1014  }
1015  }
1016  // Add the global caption, if not split
1017  if ($globalCaption) {
1018  $images .= $globalCaption;
1019  }
1020  // CSS-classes
1021  $captionClass = '';
1022  $classCaptionAlign = array(
1023  'center' => 'csc-textpic-caption-c',
1024  'right' => 'csc-textpic-caption-r',
1025  'left' => 'csc-textpic-caption-l'
1026  );
1027  $captionAlign = $this->cObj->stdWrap($conf['captionAlign'], $conf['captionAlign.']);
1028  if ($captionAlign) {
1029  $captionClass = $classCaptionAlign[$captionAlign];
1030  }
1031  $borderClass = '';
1032  if ($border) {
1033  $borderClass = $conf['borderClass'] ?: 'csc-textpic-border';
1034  }
1035  // Multiple classes with all properties, to be styled in CSS
1036  $class = '';
1037  $class .= $borderClass ? ' ' . $borderClass : '';
1038  $class .= $captionClass ? ' ' . $captionClass : '';
1039  $class .= $equalHeight ? ' csc-textpic-equalheight' : '';
1040  $addClasses = $this->cObj->stdWrap($conf['addClasses'], $conf['addClasses.']);
1041  $class .= $addClasses ? ' ' . $addClasses : '';
1042  // Do we need a width in our wrap around images?
1043  $imgWrapWidth = '';
1044  if ($position == 0 || $position == 8) {
1045  // For 'center' we always need a width: without one, the margin:auto trick won't work
1046  $imgWrapWidth = $imageBlockWidth;
1047  }
1048  if ($rowCount > 1) {
1049  // For multiple rows we also need a width, so that the images will wrap
1050  $imgWrapWidth = $imageBlockWidth;
1051  }
1052  if ($globalCaption) {
1053  // If we have a global caption, we need the width so that the caption will wrap
1054  $imgWrapWidth = $imageBlockWidth;
1055  }
1056  // Wrap around the whole image block
1057  $GLOBALS['TSFE']->register['totalwidth'] = $imgWrapWidth;
1058  if ($imgWrapWidth) {
1059  $images = $this->cObj->stdWrap($images, $conf['imageStdWrap.']);
1060  } else {
1061  $images = $this->cObj->stdWrap($images, $conf['imageStdWrapNoWidth.']);
1062  }
1063  }
1064 
1065  $output = str_replace(
1066  array(
1067  '###TEXT###',
1068  '###IMAGES###',
1069  '###CLASSES###'
1070  ),
1071  array(
1072  $content,
1073  $images,
1074  $class
1075  ),
1076  $this->cObj->cObjGetSingle($conf['layout'], $conf['layout.'])
1077  );
1078 
1079  if ($restoreRegisters) {
1080  $this->cObj->LOAD_REGISTER(array(), 'RESTORE_REGISTER');
1081  }
1082 
1083  return $output;
1084  }
1085 
1096  protected function initializeCurrentFileInContentObjectRenderer($fileUid, $treatAsReference) {
1098  if ($treatAsReference) {
1099  $imageFile = $resourceFactory->getFileReferenceObject($fileUid);
1100  } else {
1101  $imageFile = $resourceFactory->getFileObject($fileUid);
1102  }
1103  $this->cObj->setCurrentFile($imageFile);
1104  }
1105 
1106  /***********************************
1107  * Rendering of Content Element properties
1108  ***********************************/
1109 
1120  public function renderSpace($content, array $configuration) {
1121  // Look for hook before running default code for function
1122  if (method_exists($this, 'hookRequest') && ($hookObject = $this->hookRequest('renderSpace'))) {
1123  return $hookObject->renderSpace($content, $configuration);
1124  }
1125  if (isset($configuration['space']) && in_array($configuration['space'], array('before', 'after'))) {
1126  $constant = (int)$configuration['constant'];
1127  if ($configuration['space'] === 'before') {
1128  $value = $constant + $this->cObj->data['spaceBefore'];
1129  $declaration = 'margin-top: ' . $value . 'px !important;';
1130  } else {
1131  $value = $constant + $this->cObj->data['spaceAfter'];
1132  $declaration = 'margin-bottom: ' . $value . 'px !important;';
1133  }
1134  if (!empty($value)) {
1135  if ($configuration['classStdWrap.']) {
1136  $className = $this->cObj->stdWrap($value, $configuration['classStdWrap.']);
1137  } else {
1138  $className = $value;
1139  }
1140  $selector = '.' . trim($className);
1141  $this->addPageStyle($selector, $declaration);
1142  return $className;
1143  }
1144  }
1145  }
1146 
1147  /************************************
1148  * Helper functions
1149  ************************************/
1150 
1163  protected function beautifyFileLink(array $links, $fileName, $useSpaces = FALSE, $cutFileExtension = FALSE) {
1164  $linkText = $fileName;
1165  if ($useSpaces) {
1166  $linkText = str_replace('_', ' ', $linkText);
1167  }
1168  if ($cutFileExtension) {
1169  $pos = strrpos($linkText, '.');
1170  $linkText = substr($linkText, 0, $pos);
1171  }
1172  $links[1] = str_replace('>' . $fileName . '<', '>' . htmlspecialchars($linkText) . '<', $links[1]);
1173  return $links;
1174  }
1175 
1184  public function getTableAttributes($conf, $type) {
1185  // Initializing:
1186  $tableTagParams_conf = $conf['tableParams_' . $type . '.'];
1187  $border = $this->cObj->data['table_border'] ? (int)$this->cObj->data['table_border'] : $tableTagParams_conf['border'];
1188  $cellSpacing = $this->cObj->data['table_cellspacing'] ? (int)$this->cObj->data['table_cellspacing'] : $tableTagParams_conf['cellspacing'];
1189  $cellPadding = $this->cObj->data['table_cellpadding'] ? (int)$this->cObj->data['table_cellpadding'] : $tableTagParams_conf['cellpadding'];
1190  $summary = trim(htmlspecialchars($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'acctables_summary')));
1191  // Create table attributes and classes array:
1192  $tableTagParams = ($classes = array());
1193  // Table attributes for all doctypes except HTML5
1194  if ($GLOBALS['TSFE']->config['config']['doctype'] !== 'html5') {
1195  $tableTagParams['border'] = $border;
1196  $tableTagParams['cellspacing'] = $cellSpacing;
1197  $tableTagParams['cellpadding'] = $cellPadding;
1198  if ($summary) {
1199  $tableTagParams['summary'] = $summary;
1200  }
1201  } else {
1202  if ($border) {
1203  // Border property has changed, now with class
1204  $borderClass = 'contenttable-border-' . $border;
1205  $borderDeclaration = 'border-width: ' . $border . 'px; border-style: solid;';
1206  $this->addPageStyle('.' . $borderClass, $borderDeclaration);
1207  $classes[] = $borderClass;
1208  }
1209  if ($cellSpacing) {
1210  // Border attribute for HTML5 is 1 when there is cell spacing
1211  $tableTagParams['border'] = 1;
1212  // Use CSS3 border-spacing in class to have cell spacing
1213  $cellSpacingClass = 'contenttable-cellspacing-' . $cellSpacing;
1214  $cellSpacingDeclaration = 'border-spacing: ' . $cellSpacing . 'px;';
1215  $this->addPageStyle('.' . $cellSpacingClass, $cellSpacingDeclaration);
1216  $classes[] = $cellSpacingClass;
1217  }
1218  if ($cellPadding) {
1219  // Cell padding property has changed, now with class
1220  $cellPaddingClass = 'contenttable-cellpadding-' . $cellPadding;
1221  $cellSpacingSelector = '.' . $cellPaddingClass . ' td, .' . $cellPaddingClass . ' th';
1222  $cellPaddingDeclaration = 'padding: ' . $cellPadding . 'px;';
1223  $this->addPageStyle($cellSpacingSelector, $cellPaddingDeclaration);
1224  $classes[] = $cellPaddingClass;
1225  }
1226  }
1227  // Background color is class
1228  if (isset($conf['color.'][$this->cObj->data['table_bgColor']]) && !empty($conf['color.'][$this->cObj->data['table_bgColor']])) {
1229  $classes[] = 'contenttable-color-' . $this->cObj->data['table_bgColor'];
1230  }
1231  if (!empty($classes)) {
1232  $tableTagParams['class'] = ' ' . implode(' ', $classes);
1233  }
1234  // Return result:
1235  return $tableTagParams;
1236  }
1237 
1249  protected function addPageStyle($selector, $declaration) {
1250  if (!isset($GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_cssstyledcontent.']['_CSS_PAGE_STYLE'])) {
1251  $GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_cssstyledcontent.']['_CSS_PAGE_STYLE'] = array();
1252  }
1253  if (!isset($GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_cssstyledcontent.']['_CSS_PAGE_STYLE'][$selector])) {
1254  $GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_cssstyledcontent.']['_CSS_PAGE_STYLE'][$selector] = TAB . $selector . ' { ' . $declaration . ' }';
1255  }
1256  }
1257 
1265  public function hookRequest($functionName) {
1266  global $TYPO3_CONF_VARS;
1267  // Hook: menuConfig_preProcessModMenu
1268  if ($TYPO3_CONF_VARS['EXTCONF']['css_styled_content']['pi1_hooks'][$functionName]) {
1269  $hookObj = GeneralUtility::getUserObj($TYPO3_CONF_VARS['EXTCONF']['css_styled_content']['pi1_hooks'][$functionName]);
1270  if (method_exists($hookObj, $functionName)) {
1271  $hookObj->pObj = $this;
1272  return $hookObj;
1273  }
1274  }
1275  }
1276 
1282  protected function getResourceFactory() {
1283  return \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance();
1284  }
1285 }
static implodeAttributes(array $arr, $xhtmlSafe=FALSE, $dontOmitBlankAttribs=FALSE)
$TYPO3_CONF_VARS['SYS']['contentTable']
pi_getFFvalue($T3FlexForm_array, $fieldName, $sheet='sDEF', $lang='lDEF', $value='vDEF')
static devLog($msg, $extKey, $severity=0, $dataVar=FALSE)
static isFirstPartOfStr($str, $partStr)
static forceIntegerInRange($theInt, $min, $max=2000000000, $defaultValue=0)
Definition: MathUtility.php:32
static getUserObj($classRef, $checkPrefix='', $silent=FALSE)
beautifyFileLink(array $links, $fileName, $useSpaces=FALSE, $cutFileExtension=FALSE)
static trimExplode($delim, $string, $removeEmptyValues=FALSE, $limit=0)
static callUserFunction($funcName, &$params, &$ref, $checkPrefix='', $errorMode=0)
pi_getLL($key, $alternativeLabel='', $hsc=FALSE)
if(!defined('TYPO3_MODE')) $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_pre_processing'][]
static getFileAbsFileName($filename, $onlyRelative=TRUE, $relToTYPO3_mainDir=FALSE)