hasCellCoords) { return ''; } $styleValues = [ 'paddingTop' => $context->paddingTop, 'paddingRight' => $context->paddingRight, 'paddingBottom' => $context->paddingBottom, 'paddingLeft' => $context->paddingLeft, 'orientation' => $context->orientation, 'elementGap' => $context->elementGap, 'wrap' => $context->wrap, 'verticalAlign' => $context->verticalAlign, 'backgroundColor' => $context->backgroundColor, 'borderTop' => $context->borderTop, 'borderRight' => $context->borderRight, 'borderBottom' => $context->borderBottom, 'borderLeft' => $context->borderLeft, 'borderTopLeftRadius' => $context->borderTopLeftRadius, 'borderTopRightRadius' => $context->borderTopRightRadius, 'borderBottomRightRadius' => $context->borderBottomRightRadius, 'borderBottomLeftRadius' => $context->borderBottomLeftRadius, ]; $styleValues = $this->overrideStyles( $context->cellStyleOverride, $styleValues ); $isStickyHeaderCell = $context->stickyHeader && $context->row === 0 && $context->tag === 'th'; $isStickyFirstColCell = $context->stickyFirstCol && $context->col === 0; $styleParts = ['position:relative']; if ($styleValues['paddingTop'] !== '') { $styleParts[] = 'padding-top:' . $styleValues['paddingTop']; } if ($styleValues['paddingRight'] !== '') { $styleParts[] = 'padding-right:' . $styleValues['paddingRight']; } if ($styleValues['paddingBottom'] !== '') { $styleParts[] = 'padding-bottom:' . $styleValues['paddingBottom']; } if ($styleValues['paddingLeft'] !== '') { $styleParts[] = 'padding-left:' . $styleValues['paddingLeft']; } if ($styleValues['verticalAlign'] !== '') { $styleParts[] = 'vertical-align:' . $styleValues['verticalAlign']; } if ($styleValues['backgroundColor'] !== '') { $styleParts[] = 'background-color:' . $styleValues['backgroundColor']; } if ($styleValues['borderTop'] !== '') { $styleParts[] = 'border-top:' . $styleValues['borderTop']; } if ($styleValues['borderRight'] !== '') { $styleParts[] = 'border-right:' . $styleValues['borderRight']; } if ($styleValues['borderBottom'] !== '') { $styleParts[] = 'border-bottom:' . $styleValues['borderBottom']; } if ($styleValues['borderLeft'] !== '') { $styleParts[] = 'border-left:' . $styleValues['borderLeft']; } if ($styleValues['borderTopLeftRadius'] !== '') { $styleParts[] = 'border-top-left-radius:' . $styleValues['borderTopLeftRadius']; } if ($styleValues['borderTopRightRadius'] !== '') { $styleParts[] = 'border-top-right-radius:' . $styleValues['borderTopRightRadius']; } if ($styleValues['borderBottomRightRadius'] !== '') { $styleParts[] = 'border-bottom-right-radius:' . $styleValues['borderBottomRightRadius']; } if ($styleValues['borderBottomLeftRadius'] !== '') { $styleParts[] = 'border-bottom-left-radius:' . $styleValues['borderBottomLeftRadius']; } if ($context->colSpan === 1 && $context->width !== null && $context->width !== '') { $styleParts[] = 'width:' . $context->width; $styleParts[] = 'min-width:' . $context->width; } if ($context->rowSpan === 1 && $context->height !== null && $context->height !== '') { $styleParts[] = 'height:' . $context->height; $styleParts[] = 'min-height:' . $context->height; } if ($isStickyHeaderCell) { $styleParts[] = 'position:sticky'; $styleParts[] = 'top:0'; $styleParts[] = $isStickyFirstColCell ? 'z-index:3' : 'z-index:2'; if ($styleValues['backgroundColor'] === '') { $styleParts[] = 'background-color:#fff'; } } if ($isStickyFirstColCell) { if (!$isStickyHeaderCell) { $styleParts[] = 'position:sticky'; $styleParts[] = 'z-index:1'; } $styleParts[] = 'left:0'; if ( !$isStickyHeaderCell && $styleValues['backgroundColor'] === '' ) { $styleParts[] = 'background-color:#fff'; } } $tag = $context->tag === 'th' ? 'th' : 'td'; $sortableType = getStringOrNull($context->sortableType); $buttonRenderer = new ButtonRenderer(); $imageRenderer = new ImageRenderer(); $listRenderer = new ListRenderer(); $textRenderer = new TextRenderer(); $elementsHtml = ''; $isHorizontal = $styleValues['orientation'] === 'horizontal'; $implicitAlignment = $this->getUniformElementsAlignment($context->elements); foreach ($context->elements as $element) { if (!is_object($element)) { continue; } $name = getStringOrNull($element->name->asText()) ?? 'unknown'; $attributes = is_array($element->attributes) ? $element->attributes : []; $elementHtml = ''; if ($name === 'text') { $elementHtml = $textRenderer->render($attributes); } if ($name === 'button') { $elementHtml = $buttonRenderer->render($attributes); } if ($name === 'image') { $elementHtml = $imageRenderer->render($attributes); } if ($name === 'list') { $elementHtml = $listRenderer->render($attributes); } if ($elementHtml === '') { $elementHtml = apply_filters( 'tableberg/render_cell_element_html', '', $name, $attributes, $context ); if (!is_string($elementHtml)) { $elementHtml = ''; } } if ($elementHtml === '') { $elementHtml = "
$name
"; } $elementAlign = $this->getElementAlignment( $name, $attributes ); $elementWrapperStyles = [ 'display:flex', 'justify-content:' . $this->alignmentToJustifyContent($elementAlign), ]; if (!$isHorizontal) { $elementWrapperStyles[] = 'width:100%'; } $elementsHtml .= "
{$elementHtml}
"; } $elementsWrapperClasses = ['tableberg-cell-elements']; $elementsWrapperStyleParts = ['display:flex']; if ($isHorizontal) { $elementsWrapperClasses[] = 'tableberg-cell-elements-horizontal'; } $elementsWrapperStyleParts[] = 'flex-direction:' . ($isHorizontal ? 'row' : 'column'); $verticalAlignFlex = 'center'; if ($styleValues['verticalAlign'] === 'top') { $verticalAlignFlex = 'flex-start'; } elseif ($styleValues['verticalAlign'] === 'bottom') { $verticalAlignFlex = 'flex-end'; } if ($isHorizontal) { $elementsWrapperStyleParts[] = 'justify-content:' . $this->alignmentToJustifyContent($implicitAlignment); $elementsWrapperStyleParts[] = 'align-items:' . $verticalAlignFlex; } else { $elementsWrapperStyleParts[] = 'justify-content:' . $verticalAlignFlex; $elementsWrapperStyleParts[] = 'align-items:stretch'; } $elementsWrapperStyleParts[] = 'flex-wrap:' . ($styleValues['wrap'] === 'nowrap' ? 'nowrap' : 'wrap'); if ($styleValues['elementGap'] !== '') { $elementsWrapperStyleParts[] = 'gap:' . $styleValues['elementGap']; } $elementsWrapperClassAttr = implode(' ', $elementsWrapperClasses); $elementsWrapperStyleAttr = ''; $elementsWrapperStyleAttr = "style='" . implode(';', $elementsWrapperStyleParts) . "'"; $elementsWrapperHtml = "
{$elementsHtml}
"; $ribbonHtml = apply_filters( 'tableberg/render_cell_ribbon_html', '', $context->ribbon, $context ); if (!is_string($ribbonHtml)) { $ribbonHtml = ''; } $cellIsSortableHeader = $tag === 'th' && $sortableType !== null; $sortIndicatorHtml = $cellIsSortableHeader ? "" : ''; $stylesStr = implode(';', $styleParts); $attrsStr = ($tag === 'th' && $sortableType !== null) ? "data-sortable='{$sortableType}' role='button' tabindex='0' aria-sort='none'" : ''; $classAttr = $context->className !== '' ? " class='" . \esc_attr($context->className) . "'" : ''; $html = "<$tag rowspan='{$context->rowSpan}' colspan='{$context->colSpan}' {$classAttr} style='$stylesStr' data-cell-row='{$context->row}' data-cell-col='{$context->col}' {$attrsStr} > $elementsWrapperHtml $sortIndicatorHtml $ribbonHtml "; return $html; } /** * @param string $elementName * @param array $attributes * @return string */ private function getElementAlignment($elementName, $attributes) { if ($elementName === 'icon') { $styles = getArrayOrNull($attributes['styles']) ?? []; $styleAlign = getStringOrNull($styles['align']); if (in_array($styleAlign, ['left', 'center', 'right'], true)) { return $styleAlign; } return 'left'; } $topLevelAlign = getStringOrNull($attributes['align']); if (in_array($topLevelAlign, ['left', 'center', 'right'], true)) { return $topLevelAlign; } return 'left'; } /** * @param string $alignment * @return string */ private function alignmentToJustifyContent($alignment) { if ($alignment === 'center') { return 'center'; } if ($alignment === 'right') { return 'flex-end'; } return 'flex-start'; } /** * @param array $elements * @return string */ private function getUniformElementsAlignment($elements) { $resolvedAlignment = null; $hasElements = false; foreach ($elements as $element) { if (!is_object($element)) { continue; } $name = getStringOrNull($element->name->asText()) ?? 'unknown'; $attributes = is_array($element->attributes) ? $element->attributes : []; $currentAlignment = $this->getElementAlignment($name, $attributes); if (!$hasElements) { $resolvedAlignment = $currentAlignment; $hasElements = true; continue; } if ($resolvedAlignment !== $currentAlignment) { return 'left'; } } return $hasElements ? $resolvedAlignment : 'left'; } /** * @param array|null $cellStyleOverride * @param array $styleValues * @return array */ private function overrideStyles($cellStyleOverride, $styleValues) { if (!is_array($cellStyleOverride)) { return $styleValues; } $overridePadding = getArrayOrNull($cellStyleOverride['padding']); if (is_array($overridePadding)) { if (isset($overridePadding['top']) && $overridePadding['top'] instanceof StringAttr) { $styleValues['paddingTop'] = $overridePadding['top']->asAttr(); } if (isset($overridePadding['right']) && $overridePadding['right'] instanceof StringAttr) { $styleValues['paddingRight'] = $overridePadding['right']->asAttr(); } if (isset($overridePadding['bottom']) && $overridePadding['bottom'] instanceof StringAttr) { $styleValues['paddingBottom'] = $overridePadding['bottom']->asAttr(); } if (isset($overridePadding['left']) && $overridePadding['left'] instanceof StringAttr) { $styleValues['paddingLeft'] = $overridePadding['left']->asAttr(); } } if (isset($cellStyleOverride['backgroundColor']) && $cellStyleOverride['backgroundColor'] instanceof StringAttr) { $styleValues['backgroundColor'] = $cellStyleOverride['backgroundColor']->asAttr(); } if (isset($cellStyleOverride['orientation']) && $cellStyleOverride['orientation'] instanceof StringAttr) { $orientation = $cellStyleOverride['orientation']->asAttr(); $styleValues['orientation'] = $orientation; } if (isset($cellStyleOverride['wrap']) && $cellStyleOverride['wrap'] instanceof StringAttr) { $wrap = $cellStyleOverride['wrap']->asAttr(); $styleValues['wrap'] = $wrap; } if (isset($cellStyleOverride['elementGap']) && $cellStyleOverride['elementGap'] instanceof StringAttr) { $styleValues['elementGap'] = $cellStyleOverride['elementGap']->asAttr(); } if (isset($cellStyleOverride['verticalAlign']) && $cellStyleOverride['verticalAlign'] instanceof StringAttr) { $verticalAlign = $cellStyleOverride['verticalAlign']->asAttr(); $styleValues['verticalAlign'] = $verticalAlign; } $overrideBorder = getArrayOrNull($cellStyleOverride['border']); if (is_array($overrideBorder)) { if (isset($overrideBorder['top']) && $overrideBorder['top'] instanceof StringAttr) { $styleValues['borderTop'] = $overrideBorder['top']->asAttr(); } if (isset($overrideBorder['right']) && $overrideBorder['right'] instanceof StringAttr) { $styleValues['borderRight'] = $overrideBorder['right']->asAttr(); } if (isset($overrideBorder['bottom']) && $overrideBorder['bottom'] instanceof StringAttr) { $styleValues['borderBottom'] = $overrideBorder['bottom']->asAttr(); } if (isset($overrideBorder['left']) && $overrideBorder['left'] instanceof StringAttr) { $styleValues['borderLeft'] = $overrideBorder['left']->asAttr(); } } $overrideBorderRadius = getArrayOrNull($cellStyleOverride['borderRadius']); if (is_array($overrideBorderRadius)) { if (isset($overrideBorderRadius['topLeft']) && $overrideBorderRadius['topLeft'] instanceof StringAttr) { $styleValues['borderTopLeftRadius'] = $overrideBorderRadius['topLeft']->asAttr(); } if (isset($overrideBorderRadius['topRight']) && $overrideBorderRadius['topRight'] instanceof StringAttr) { $styleValues['borderTopRightRadius'] = $overrideBorderRadius['topRight']->asAttr(); } if (isset($overrideBorderRadius['bottomRight']) && $overrideBorderRadius['bottomRight'] instanceof StringAttr) { $styleValues['borderBottomRightRadius'] = $overrideBorderRadius['bottomRight']->asAttr(); } if (isset($overrideBorderRadius['bottomLeft']) && $overrideBorderRadius['bottomLeft'] instanceof StringAttr) { $styleValues['borderBottomLeftRadius'] = $overrideBorderRadius['bottomLeft']->asAttr(); } } return $styleValues; } }