1 |
efrain |
1 |
<?php
|
|
|
2 |
|
|
|
3 |
declare(strict_types=1);
|
|
|
4 |
|
|
|
5 |
namespace OpenSpout\Writer\ODS\Manager\Style;
|
|
|
6 |
|
|
|
7 |
use OpenSpout\Common\Entity\Style\Border;
|
|
|
8 |
use OpenSpout\Common\Entity\Style\BorderPart;
|
|
|
9 |
use OpenSpout\Common\Entity\Style\CellAlignment;
|
|
|
10 |
use OpenSpout\Common\Entity\Style\CellVerticalAlignment;
|
|
|
11 |
use OpenSpout\Common\Entity\Style\Style;
|
|
|
12 |
use OpenSpout\Writer\Common\AbstractOptions;
|
|
|
13 |
use OpenSpout\Writer\Common\ColumnWidth;
|
|
|
14 |
use OpenSpout\Writer\Common\Entity\Worksheet;
|
|
|
15 |
use OpenSpout\Writer\Common\Manager\Style\AbstractStyleManager as CommonStyleManager;
|
|
|
16 |
use OpenSpout\Writer\ODS\Helper\BorderHelper;
|
|
|
17 |
|
|
|
18 |
/**
|
|
|
19 |
* @internal
|
|
|
20 |
*
|
|
|
21 |
* @property StyleRegistry $styleRegistry
|
|
|
22 |
*/
|
|
|
23 |
final class StyleManager extends CommonStyleManager
|
|
|
24 |
{
|
|
|
25 |
private readonly AbstractOptions $options;
|
|
|
26 |
|
|
|
27 |
public function __construct(StyleRegistry $styleRegistry, AbstractOptions $options)
|
|
|
28 |
{
|
|
|
29 |
parent::__construct($styleRegistry);
|
|
|
30 |
$this->options = $options;
|
|
|
31 |
}
|
|
|
32 |
|
|
|
33 |
/**
|
|
|
34 |
* Returns the content of the "styles.xml" file, given a list of styles.
|
|
|
35 |
*
|
|
|
36 |
* @param int $numWorksheets Number of worksheets created
|
|
|
37 |
*/
|
|
|
38 |
public function getStylesXMLFileContent(int $numWorksheets): string
|
|
|
39 |
{
|
|
|
40 |
$content = <<<'EOD'
|
|
|
41 |
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
|
42 |
<office:document-styles office:version="1.2" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:msoxl="http://schemas.microsoft.com/office/excel/formula" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
|
43 |
EOD;
|
|
|
44 |
|
|
|
45 |
$content .= $this->getFontFaceSectionContent();
|
|
|
46 |
$content .= $this->getStylesSectionContent();
|
|
|
47 |
$content .= $this->getAutomaticStylesSectionContent($numWorksheets);
|
|
|
48 |
$content .= $this->getMasterStylesSectionContent($numWorksheets);
|
|
|
49 |
|
|
|
50 |
$content .= <<<'EOD'
|
|
|
51 |
</office:document-styles>
|
|
|
52 |
EOD;
|
|
|
53 |
|
|
|
54 |
return $content;
|
|
|
55 |
}
|
|
|
56 |
|
|
|
57 |
/**
|
|
|
58 |
* Returns the contents of the "<office:font-face-decls>" section, inside "content.xml" file.
|
|
|
59 |
*/
|
|
|
60 |
public function getContentXmlFontFaceSectionContent(): string
|
|
|
61 |
{
|
|
|
62 |
$content = '<office:font-face-decls>';
|
|
|
63 |
foreach ($this->styleRegistry->getUsedFonts() as $fontName) {
|
|
|
64 |
$content .= '<style:font-face style:name="'.$fontName.'" svg:font-family="'.$fontName.'"/>';
|
|
|
65 |
}
|
|
|
66 |
$content .= '</office:font-face-decls>';
|
|
|
67 |
|
|
|
68 |
return $content;
|
|
|
69 |
}
|
|
|
70 |
|
|
|
71 |
/**
|
|
|
72 |
* Returns the contents of the "<office:automatic-styles>" section, inside "content.xml" file.
|
|
|
73 |
*
|
|
|
74 |
* @param Worksheet[] $worksheets
|
|
|
75 |
*/
|
|
|
76 |
public function getContentXmlAutomaticStylesSectionContent(array $worksheets): string
|
|
|
77 |
{
|
|
|
78 |
$content = '<office:automatic-styles>';
|
|
|
79 |
|
|
|
80 |
foreach ($this->styleRegistry->getRegisteredStyles() as $style) {
|
|
|
81 |
$content .= $this->getStyleSectionContent($style);
|
|
|
82 |
}
|
|
|
83 |
|
|
|
84 |
$useOptimalRowHeight = null === $this->options->DEFAULT_ROW_HEIGHT ? 'true' : 'false';
|
|
|
85 |
$defaultRowHeight = null === $this->options->DEFAULT_ROW_HEIGHT ? '15pt' : "{$this->options->DEFAULT_ROW_HEIGHT}pt";
|
|
|
86 |
$defaultColumnWidth = null === $this->options->DEFAULT_COLUMN_WIDTH ? '' : "style:column-width=\"{$this->options->DEFAULT_COLUMN_WIDTH}pt\"";
|
|
|
87 |
|
|
|
88 |
$content .= <<<EOD
|
|
|
89 |
<style:style style:family="table-column" style:name="default-column-style">
|
|
|
90 |
<style:table-column-properties fo:break-before="auto" {$defaultColumnWidth}/>
|
|
|
91 |
</style:style>
|
|
|
92 |
<style:style style:family="table-row" style:name="ro1">
|
|
|
93 |
<style:table-row-properties fo:break-before="auto" style:row-height="{$defaultRowHeight}" style:use-optimal-row-height="{$useOptimalRowHeight}"/>
|
|
|
94 |
</style:style>
|
|
|
95 |
EOD;
|
|
|
96 |
|
|
|
97 |
foreach ($worksheets as $worksheet) {
|
|
|
98 |
$worksheetId = $worksheet->getId();
|
|
|
99 |
$isSheetVisible = $worksheet->getExternalSheet()->isVisible() ? 'true' : 'false';
|
|
|
100 |
|
|
|
101 |
$content .= <<<EOD
|
|
|
102 |
<style:style style:family="table" style:master-page-name="mp{$worksheetId}" style:name="ta{$worksheetId}">
|
|
|
103 |
<style:table-properties style:writing-mode="lr-tb" table:display="{$isSheetVisible}"/>
|
|
|
104 |
</style:style>
|
|
|
105 |
EOD;
|
|
|
106 |
}
|
|
|
107 |
|
|
|
108 |
// Sort column widths since ODS cares about order
|
|
|
109 |
$columnWidths = $this->options->getColumnWidths();
|
|
|
110 |
usort($columnWidths, static function (ColumnWidth $a, ColumnWidth $b): int {
|
|
|
111 |
return $a->start <=> $b->start;
|
|
|
112 |
});
|
|
|
113 |
$content .= $this->getTableColumnStylesXMLContent();
|
|
|
114 |
|
|
|
115 |
$content .= '</office:automatic-styles>';
|
|
|
116 |
|
|
|
117 |
return $content;
|
|
|
118 |
}
|
|
|
119 |
|
|
|
120 |
public function getTableColumnStylesXMLContent(): string
|
|
|
121 |
{
|
|
|
122 |
if ([] === $this->options->getColumnWidths()) {
|
|
|
123 |
return '';
|
|
|
124 |
}
|
|
|
125 |
|
|
|
126 |
$content = '';
|
|
|
127 |
foreach ($this->options->getColumnWidths() as $styleIndex => $columnWidth) {
|
|
|
128 |
$content .= <<<EOD
|
|
|
129 |
<style:style style:family="table-column" style:name="co{$styleIndex}">
|
|
|
130 |
<style:table-column-properties fo:break-before="auto" style:use-optimal-column-width="false" style:column-width="{$columnWidth->width}pt"/>
|
|
|
131 |
</style:style>
|
|
|
132 |
EOD;
|
|
|
133 |
}
|
|
|
134 |
|
|
|
135 |
return $content;
|
|
|
136 |
}
|
|
|
137 |
|
|
|
138 |
public function getStyledTableColumnXMLContent(int $maxNumColumns): string
|
|
|
139 |
{
|
|
|
140 |
if ([] === $this->options->getColumnWidths()) {
|
|
|
141 |
return '';
|
|
|
142 |
}
|
|
|
143 |
|
|
|
144 |
$content = '';
|
|
|
145 |
foreach ($this->options->getColumnWidths() as $styleIndex => $columnWidth) {
|
|
|
146 |
$numCols = $columnWidth->end - $columnWidth->start + 1;
|
|
|
147 |
$content .= <<<EOD
|
|
|
148 |
<table:table-column table:default-cell-style-name='Default' table:style-name="co{$styleIndex}" table:number-columns-repeated="{$numCols}"/>
|
|
|
149 |
EOD;
|
|
|
150 |
}
|
|
|
151 |
\assert(isset($columnWidth));
|
|
|
152 |
// Note: This assumes the column widths are contiguous and default width is
|
|
|
153 |
// only applied to columns after the last custom column with a custom width
|
|
|
154 |
$content .= '<table:table-column table:default-cell-style-name="ce1" table:style-name="default-column-style" table:number-columns-repeated="'.($maxNumColumns - $columnWidth->end).'"/>';
|
|
|
155 |
|
|
|
156 |
return $content;
|
|
|
157 |
}
|
|
|
158 |
|
|
|
159 |
/**
|
|
|
160 |
* Returns the content of the "<office:styles>" section, inside "styles.xml" file.
|
|
|
161 |
*/
|
|
|
162 |
private function getStylesSectionContent(): string
|
|
|
163 |
{
|
|
|
164 |
$defaultStyle = $this->getDefaultStyle();
|
|
|
165 |
|
|
|
166 |
return <<<EOD
|
|
|
167 |
<office:styles>
|
|
|
168 |
<number:number-style style:name="N0">
|
|
|
169 |
<number:number number:min-integer-digits="1"/>
|
|
|
170 |
</number:number-style>
|
|
|
171 |
<style:style style:data-style-name="N0" style:family="table-cell" style:name="Default">
|
|
|
172 |
<style:table-cell-properties fo:background-color="transparent" style:vertical-align="automatic"/>
|
|
|
173 |
<style:text-properties fo:color="#{$defaultStyle->getFontColor()}"
|
|
|
174 |
fo:font-size="{$defaultStyle->getFontSize()}pt" style:font-size-asian="{$defaultStyle->getFontSize()}pt" style:font-size-complex="{$defaultStyle->getFontSize()}pt"
|
|
|
175 |
style:font-name="{$defaultStyle->getFontName()}" style:font-name-asian="{$defaultStyle->getFontName()}" style:font-name-complex="{$defaultStyle->getFontName()}"/>
|
|
|
176 |
</style:style>
|
|
|
177 |
</office:styles>
|
|
|
178 |
EOD;
|
|
|
179 |
}
|
|
|
180 |
|
|
|
181 |
/**
|
|
|
182 |
* Returns the content of the "<office:master-styles>" section, inside "styles.xml" file.
|
|
|
183 |
*
|
|
|
184 |
* @param int $numWorksheets Number of worksheets created
|
|
|
185 |
*/
|
|
|
186 |
private function getMasterStylesSectionContent(int $numWorksheets): string
|
|
|
187 |
{
|
|
|
188 |
$content = '<office:master-styles>';
|
|
|
189 |
|
|
|
190 |
for ($i = 1; $i <= $numWorksheets; ++$i) {
|
|
|
191 |
$content .= <<<EOD
|
|
|
192 |
<style:master-page style:name="mp{$i}" style:page-layout-name="pm{$i}">
|
|
|
193 |
<style:header/>
|
|
|
194 |
<style:header-left style:display="false"/>
|
|
|
195 |
<style:footer/>
|
|
|
196 |
<style:footer-left style:display="false"/>
|
|
|
197 |
</style:master-page>
|
|
|
198 |
EOD;
|
|
|
199 |
}
|
|
|
200 |
|
|
|
201 |
$content .= '</office:master-styles>';
|
|
|
202 |
|
|
|
203 |
return $content;
|
|
|
204 |
}
|
|
|
205 |
|
|
|
206 |
/**
|
|
|
207 |
* Returns the content of the "<office:font-face-decls>" section, inside "styles.xml" file.
|
|
|
208 |
*/
|
|
|
209 |
private function getFontFaceSectionContent(): string
|
|
|
210 |
{
|
|
|
211 |
$content = '<office:font-face-decls>';
|
|
|
212 |
foreach ($this->styleRegistry->getUsedFonts() as $fontName) {
|
|
|
213 |
$content .= '<style:font-face style:name="'.$fontName.'" svg:font-family="'.$fontName.'"/>';
|
|
|
214 |
}
|
|
|
215 |
$content .= '</office:font-face-decls>';
|
|
|
216 |
|
|
|
217 |
return $content;
|
|
|
218 |
}
|
|
|
219 |
|
|
|
220 |
/**
|
|
|
221 |
* Returns the content of the "<office:automatic-styles>" section, inside "styles.xml" file.
|
|
|
222 |
*
|
|
|
223 |
* @param int $numWorksheets Number of worksheets created
|
|
|
224 |
*/
|
|
|
225 |
private function getAutomaticStylesSectionContent(int $numWorksheets): string
|
|
|
226 |
{
|
|
|
227 |
$content = '<office:automatic-styles>';
|
|
|
228 |
|
|
|
229 |
for ($i = 1; $i <= $numWorksheets; ++$i) {
|
|
|
230 |
$content .= <<<EOD
|
|
|
231 |
<style:page-layout style:name="pm{$i}">
|
|
|
232 |
<style:page-layout-properties style:first-page-number="continue" style:print="objects charts drawings" style:table-centering="none"/>
|
|
|
233 |
<style:header-style/>
|
|
|
234 |
<style:footer-style/>
|
|
|
235 |
</style:page-layout>
|
|
|
236 |
EOD;
|
|
|
237 |
}
|
|
|
238 |
|
|
|
239 |
$content .= '</office:automatic-styles>';
|
|
|
240 |
|
|
|
241 |
return $content;
|
|
|
242 |
}
|
|
|
243 |
|
|
|
244 |
/**
|
|
|
245 |
* Returns the contents of the "<style:style>" section, inside "<office:automatic-styles>" section.
|
|
|
246 |
*/
|
|
|
247 |
private function getStyleSectionContent(Style $style): string
|
|
|
248 |
{
|
|
|
249 |
$styleIndex = $style->getId() + 1; // 1-based
|
|
|
250 |
|
|
|
251 |
$content = '<style:style style:data-style-name="N0" style:family="table-cell" style:name="ce'.$styleIndex.'" style:parent-style-name="Default">';
|
|
|
252 |
|
|
|
253 |
$content .= $this->getTextPropertiesSectionContent($style);
|
|
|
254 |
$content .= $this->getParagraphPropertiesSectionContent($style);
|
|
|
255 |
$content .= $this->getTableCellPropertiesSectionContent($style);
|
|
|
256 |
|
|
|
257 |
$content .= '</style:style>';
|
|
|
258 |
|
|
|
259 |
return $content;
|
|
|
260 |
}
|
|
|
261 |
|
|
|
262 |
/**
|
|
|
263 |
* Returns the contents of the "<style:text-properties>" section, inside "<style:style>" section.
|
|
|
264 |
*/
|
|
|
265 |
private function getTextPropertiesSectionContent(Style $style): string
|
|
|
266 |
{
|
|
|
267 |
if (!$style->shouldApplyFont()) {
|
|
|
268 |
return '';
|
|
|
269 |
}
|
|
|
270 |
|
|
|
271 |
return '<style:text-properties '
|
|
|
272 |
.$this->getFontSectionContent($style)
|
|
|
273 |
.'/>';
|
|
|
274 |
}
|
|
|
275 |
|
|
|
276 |
/**
|
|
|
277 |
* Returns the contents of the fonts definition section, inside "<style:text-properties>" section.
|
|
|
278 |
*/
|
|
|
279 |
private function getFontSectionContent(Style $style): string
|
|
|
280 |
{
|
|
|
281 |
$defaultStyle = $this->getDefaultStyle();
|
|
|
282 |
$content = '';
|
|
|
283 |
|
|
|
284 |
$fontColor = $style->getFontColor();
|
|
|
285 |
if ($fontColor !== $defaultStyle->getFontColor()) {
|
|
|
286 |
$content .= ' fo:color="#'.$fontColor.'"';
|
|
|
287 |
}
|
|
|
288 |
|
|
|
289 |
$fontName = $style->getFontName();
|
|
|
290 |
if ($fontName !== $defaultStyle->getFontName()) {
|
|
|
291 |
$content .= ' style:font-name="'.$fontName.'" style:font-name-asian="'.$fontName.'" style:font-name-complex="'.$fontName.'"';
|
|
|
292 |
}
|
|
|
293 |
|
|
|
294 |
$fontSize = $style->getFontSize();
|
|
|
295 |
if ($fontSize !== $defaultStyle->getFontSize()) {
|
|
|
296 |
$content .= ' fo:font-size="'.$fontSize.'pt" style:font-size-asian="'.$fontSize.'pt" style:font-size-complex="'.$fontSize.'pt"';
|
|
|
297 |
}
|
|
|
298 |
|
|
|
299 |
if ($style->isFontBold()) {
|
|
|
300 |
$content .= ' fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"';
|
|
|
301 |
}
|
|
|
302 |
if ($style->isFontItalic()) {
|
|
|
303 |
$content .= ' fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic"';
|
|
|
304 |
}
|
|
|
305 |
if ($style->isFontUnderline()) {
|
|
|
306 |
$content .= ' style:text-underline-style="solid" style:text-underline-type="single"';
|
|
|
307 |
}
|
|
|
308 |
if ($style->isFontStrikethrough()) {
|
|
|
309 |
$content .= ' style:text-line-through-style="solid"';
|
|
|
310 |
}
|
|
|
311 |
|
|
|
312 |
return $content;
|
|
|
313 |
}
|
|
|
314 |
|
|
|
315 |
/**
|
|
|
316 |
* Returns the contents of the "<style:paragraph-properties>" section, inside "<style:style>" section.
|
|
|
317 |
*/
|
|
|
318 |
private function getParagraphPropertiesSectionContent(Style $style): string
|
|
|
319 |
{
|
|
|
320 |
if (!$style->shouldApplyCellAlignment() && !$style->shouldApplyCellVerticalAlignment()) {
|
|
|
321 |
return '';
|
|
|
322 |
}
|
|
|
323 |
|
|
|
324 |
return '<style:paragraph-properties '
|
|
|
325 |
.$this->getCellAlignmentSectionContent($style)
|
|
|
326 |
.$this->getCellVerticalAlignmentSectionContent($style)
|
|
|
327 |
.'/>';
|
|
|
328 |
}
|
|
|
329 |
|
|
|
330 |
/**
|
|
|
331 |
* Returns the contents of the cell alignment definition for the "<style:paragraph-properties>" section.
|
|
|
332 |
*/
|
|
|
333 |
private function getCellAlignmentSectionContent(Style $style): string
|
|
|
334 |
{
|
|
|
335 |
if (!$style->hasSetCellAlignment()) {
|
|
|
336 |
return '';
|
|
|
337 |
}
|
|
|
338 |
|
|
|
339 |
return sprintf(
|
|
|
340 |
' fo:text-align="%s" ',
|
|
|
341 |
$this->transformCellAlignment($style->getCellAlignment())
|
|
|
342 |
);
|
|
|
343 |
}
|
|
|
344 |
|
|
|
345 |
/**
|
|
|
346 |
* Returns the contents of the cell vertical alignment definition for the "<style:paragraph-properties>" section.
|
|
|
347 |
*/
|
|
|
348 |
private function getCellVerticalAlignmentSectionContent(Style $style): string
|
|
|
349 |
{
|
|
|
350 |
if (!$style->hasSetCellVerticalAlignment()) {
|
|
|
351 |
return '';
|
|
|
352 |
}
|
|
|
353 |
|
|
|
354 |
return sprintf(
|
|
|
355 |
' fo:vertical-align="%s" ',
|
|
|
356 |
$this->transformCellVerticalAlignment($style->getCellVerticalAlignment())
|
|
|
357 |
);
|
|
|
358 |
}
|
|
|
359 |
|
|
|
360 |
/**
|
|
|
361 |
* Even though "left" and "right" alignments are part of the spec, and interpreted
|
|
|
362 |
* respectively as "start" and "end", using the recommended values increase compatibility
|
|
|
363 |
* with software that will read the created ODS file.
|
|
|
364 |
*/
|
|
|
365 |
private function transformCellAlignment(string $cellAlignment): string
|
|
|
366 |
{
|
|
|
367 |
return match ($cellAlignment) {
|
|
|
368 |
CellAlignment::LEFT => 'start',
|
|
|
369 |
CellAlignment::RIGHT => 'end',
|
|
|
370 |
default => $cellAlignment,
|
|
|
371 |
};
|
|
|
372 |
}
|
|
|
373 |
|
|
|
374 |
/**
|
|
|
375 |
* Spec uses 'middle' rather than 'center'
|
|
|
376 |
* http://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part1.html#__RefHeading__1420236_253892949.
|
|
|
377 |
*/
|
|
|
378 |
private function transformCellVerticalAlignment(string $cellVerticalAlignment): string
|
|
|
379 |
{
|
|
|
380 |
return (CellVerticalAlignment::CENTER === $cellVerticalAlignment)
|
|
|
381 |
? 'middle'
|
|
|
382 |
: $cellVerticalAlignment;
|
|
|
383 |
}
|
|
|
384 |
|
|
|
385 |
/**
|
|
|
386 |
* Returns the contents of the "<style:table-cell-properties>" section, inside "<style:style>" section.
|
|
|
387 |
*/
|
|
|
388 |
private function getTableCellPropertiesSectionContent(Style $style): string
|
|
|
389 |
{
|
|
|
390 |
$content = '<style:table-cell-properties ';
|
|
|
391 |
|
|
|
392 |
if ($style->hasSetWrapText()) {
|
|
|
393 |
$content .= $this->getWrapTextXMLContent($style->shouldWrapText());
|
|
|
394 |
}
|
|
|
395 |
|
|
|
396 |
if (null !== ($border = $style->getBorder())) {
|
|
|
397 |
$content .= $this->getBorderXMLContent($border);
|
|
|
398 |
}
|
|
|
399 |
|
|
|
400 |
if (null !== ($bgColor = $style->getBackgroundColor())) {
|
|
|
401 |
$content .= $this->getBackgroundColorXMLContent($bgColor);
|
|
|
402 |
}
|
|
|
403 |
|
|
|
404 |
$content .= '/>';
|
|
|
405 |
|
|
|
406 |
return $content;
|
|
|
407 |
}
|
|
|
408 |
|
|
|
409 |
/**
|
|
|
410 |
* Returns the contents of the wrap text definition for the "<style:table-cell-properties>" section.
|
|
|
411 |
*/
|
|
|
412 |
private function getWrapTextXMLContent(bool $shouldWrapText): string
|
|
|
413 |
{
|
|
|
414 |
return ' fo:wrap-option="'.($shouldWrapText ? '' : 'no-').'wrap" style:vertical-align="automatic" ';
|
|
|
415 |
}
|
|
|
416 |
|
|
|
417 |
/**
|
|
|
418 |
* Returns the contents of the borders definition for the "<style:table-cell-properties>" section.
|
|
|
419 |
*/
|
|
|
420 |
private function getBorderXMLContent(Border $border): string
|
|
|
421 |
{
|
|
|
422 |
$borders = array_map(static function (BorderPart $borderPart) {
|
|
|
423 |
return BorderHelper::serializeBorderPart($borderPart);
|
|
|
424 |
}, $border->getParts());
|
|
|
425 |
|
|
|
426 |
return sprintf(' %s ', implode(' ', $borders));
|
|
|
427 |
}
|
|
|
428 |
|
|
|
429 |
/**
|
|
|
430 |
* Returns the contents of the background color definition for the "<style:table-cell-properties>" section.
|
|
|
431 |
*/
|
|
|
432 |
private function getBackgroundColorXMLContent(string $bgColor): string
|
|
|
433 |
{
|
|
|
434 |
return sprintf(' fo:background-color="#%s" ', $bgColor);
|
|
|
435 |
}
|
|
|
436 |
}
|