Gnumeric Better Namespace Handling (#2022)
* Gnumeric Better Namespace Handling There have been a number of issues concerning the handling of legitimate but unexpected namespace prefixes in Xlsx spreadsheets created by software other than Excel and PhpSpreadsheet/PhpExcel.I have studied them, but, till now, have not had a good idea on how to act on them. A recent comment https://github.com/PHPOffice/PhpSpreadsheet/issues/860#issuecomment-824926224 in issue #860 by @IMSoP has triggered an idea about how to proceed. Although the issues exclusively concern Xlsx format, I am starting out by dealing with Gnumeric. It is simpler and smaller than Xlsx, and, more important, already has a test for an unexpected prefix, since, at some point, it changed its generic prefix from gmr to gnm. I added support and a test for that some time ago, but almost certainly not in the best possible manner. The code as changed for this PR seems simpler and less kludgey, both for that exceptional case as well as for normal handling. My hope is that this change can be a template for similar Reader changes for Xml, Ods, and, especially, Xlsx. All grandfathered Phpstan issues with Gnumeric are fixed and eliminated from baseline as part of this change. * Namespace Handling using XMLReader Adopt a suggestion from @IMSoP affecting listWorkSheetInfo, which uses XMLReader rather than SimpleXML for its processing. * Update GnumericLoadTest.php PR #2024 was pushed last night, causing a Phpstan problem with this member. * Update Gnumeric.php Suggestions from Mark Baker - strict equality test, more descriptive variable names.
This commit is contained in:
parent
5873116488
commit
4be9366722
|
|
@ -2545,71 +2545,6 @@ parameters:
|
|||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Csv/Delimiter.php
|
||||
|
||||
-
|
||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Gnumeric\\:\\:\\$referenceHelper has no typehint specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Gnumeric.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$fp of function fread expects resource, resource\\|false given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Gnumeric.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$fp of function fclose expects resource, resource\\|false given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Gnumeric.php
|
||||
|
||||
-
|
||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Gnumeric\\:\\:\\$mappings has no typehint specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Gnumeric.php
|
||||
|
||||
-
|
||||
message: "#^Offset 'No' does not exist on SimpleXMLElement\\|null\\.$#"
|
||||
count: 2
|
||||
path: src/PhpSpreadsheet/Reader/Gnumeric.php
|
||||
|
||||
-
|
||||
message: "#^Offset 'Unit' does not exist on SimpleXMLElement\\|null\\.$#"
|
||||
count: 2
|
||||
path: src/PhpSpreadsheet/Reader/Gnumeric.php
|
||||
|
||||
-
|
||||
message: "#^Offset 'DefaultSizePts' does not exist on SimpleXMLElement\\|null\\.$#"
|
||||
count: 2
|
||||
path: src/PhpSpreadsheet/Reader/Gnumeric.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Gnumeric\\:\\:parseBorderAttributes\\(\\) has no return typehint specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Gnumeric.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Gnumeric\\:\\:parseBorderAttributes\\(\\) has parameter \\$borderAttributes with no typehint specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Gnumeric.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Gnumeric\\:\\:parseRichText\\(\\) has no return typehint specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Gnumeric.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Gnumeric\\:\\:parseRichText\\(\\) has parameter \\$is with no typehint specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Gnumeric.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Gnumeric\\:\\:parseGnumericColour\\(\\) has no return typehint specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Gnumeric.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Gnumeric\\:\\:parseGnumericColour\\(\\) has parameter \\$gnmColour with no typehint specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Gnumeric.php
|
||||
|
||||
-
|
||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Html\\:\\:\\$rowspan has no typehint specified\\.$#"
|
||||
count: 1
|
||||
|
|
|
|||
|
|
@ -25,7 +25,19 @@ use XMLReader;
|
|||
|
||||
class Gnumeric extends BaseReader
|
||||
{
|
||||
private const UOM_CONVERSION_POINTS_TO_CENTIMETERS = 0.03527777778;
|
||||
const NAMESPACE_GNM = 'http://www.gnumeric.org/v10.dtd'; // gmr in old sheets
|
||||
|
||||
const NAMESPACE_XSI = 'http://www.w3.org/2001/XMLSchema-instance';
|
||||
|
||||
const NAMESPACE_OFFICE = 'urn:oasis:names:tc:opendocument:xmlns:office:1.0';
|
||||
|
||||
const NAMESPACE_XLINK = 'http://www.w3.org/1999/xlink';
|
||||
|
||||
const NAMESPACE_DC = 'http://purl.org/dc/elements/1.1/';
|
||||
|
||||
const NAMESPACE_META = 'urn:oasis:names:tc:opendocument:xmlns:meta:1.0';
|
||||
|
||||
const NAMESPACE_OOO = 'http://openoffice.org/2004/office';
|
||||
|
||||
/**
|
||||
* Shared Expressions.
|
||||
|
|
@ -41,16 +53,9 @@ class Gnumeric extends BaseReader
|
|||
*/
|
||||
private $spreadsheet;
|
||||
|
||||
/** @var ReferenceHelper */
|
||||
private $referenceHelper;
|
||||
|
||||
/**
|
||||
* Namespace shared across all functions.
|
||||
* It is 'gnm', except for really old sheets which use 'gmr'.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $gnm = 'gnm';
|
||||
|
||||
/**
|
||||
* Create a new Gnumeric.
|
||||
*/
|
||||
|
|
@ -77,16 +82,20 @@ class Gnumeric extends BaseReader
|
|||
if (function_exists('gzread')) {
|
||||
// Read signature data (first 3 bytes)
|
||||
$fh = fopen($pFilename, 'rb');
|
||||
if ($fh !== false) {
|
||||
$data = fread($fh, 2);
|
||||
fclose($fh);
|
||||
}
|
||||
|
||||
return $data == chr(0x1F) . chr(0x8B);
|
||||
}
|
||||
|
||||
private static function matchXml(string $name, string $field): bool
|
||||
return $data === chr(0x1F) . chr(0x8B);
|
||||
}
|
||||
|
||||
private static function matchXml(XMLReader $xml, string $expectedLocalName): bool
|
||||
{
|
||||
return 1 === preg_match("/^(gnm|gmr):$field$/", $name);
|
||||
return $xml->namespaceURI === self::NAMESPACE_GNM
|
||||
&& $xml->localName === $expectedLocalName
|
||||
&& $xml->nodeType === XMLReader::ELEMENT;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -106,10 +115,10 @@ class Gnumeric extends BaseReader
|
|||
|
||||
$worksheetNames = [];
|
||||
while ($xml->read()) {
|
||||
if (self::matchXml($xml->name, 'SheetName') && $xml->nodeType == XMLReader::ELEMENT) {
|
||||
if (self::matchXml($xml, 'SheetName')) {
|
||||
$xml->read(); // Move onto the value node
|
||||
$worksheetNames[] = (string) $xml->value;
|
||||
} elseif (self::matchXml($xml->name, 'Sheets')) {
|
||||
} elseif (self::matchXml($xml, 'Sheets')) {
|
||||
// break out of the loop once we've got our sheet names rather than parse the entire file
|
||||
break;
|
||||
}
|
||||
|
|
@ -135,7 +144,7 @@ class Gnumeric extends BaseReader
|
|||
|
||||
$worksheetInfo = [];
|
||||
while ($xml->read()) {
|
||||
if (self::matchXml($xml->name, 'Sheet') && $xml->nodeType == XMLReader::ELEMENT) {
|
||||
if (self::matchXml($xml, 'Sheet')) {
|
||||
$tmpInfo = [
|
||||
'worksheetName' => '',
|
||||
'lastColumnLetter' => 'A',
|
||||
|
|
@ -145,22 +154,20 @@ class Gnumeric extends BaseReader
|
|||
];
|
||||
|
||||
while ($xml->read()) {
|
||||
if ($xml->nodeType == XMLReader::ELEMENT) {
|
||||
if (self::matchXml($xml->name, 'Name')) {
|
||||
if (self::matchXml($xml, 'Name')) {
|
||||
$xml->read(); // Move onto the value node
|
||||
$tmpInfo['worksheetName'] = (string) $xml->value;
|
||||
} elseif (self::matchXml($xml->name, 'MaxCol')) {
|
||||
} elseif (self::matchXml($xml, 'MaxCol')) {
|
||||
$xml->read(); // Move onto the value node
|
||||
$tmpInfo['lastColumnIndex'] = (int) $xml->value;
|
||||
$tmpInfo['totalColumns'] = (int) $xml->value + 1;
|
||||
} elseif (self::matchXml($xml->name, 'MaxRow')) {
|
||||
} elseif (self::matchXml($xml, 'MaxRow')) {
|
||||
$xml->read(); // Move onto the value node
|
||||
$tmpInfo['totalRows'] = (int) $xml->value + 1;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
$tmpInfo['lastColumnLetter'] = Coordinate::stringFromColumnIndex($tmpInfo['lastColumnIndex'] + 1);
|
||||
$worksheetInfo[] = $tmpInfo;
|
||||
}
|
||||
|
|
@ -188,6 +195,7 @@ class Gnumeric extends BaseReader
|
|||
return $data;
|
||||
}
|
||||
|
||||
/** @var array */
|
||||
private static $mappings = [
|
||||
'borderStyle' => [
|
||||
'0' => Border::BORDER_NONE,
|
||||
|
|
@ -266,7 +274,7 @@ class Gnumeric extends BaseReader
|
|||
private function processComments(SimpleXMLElement $sheet): void
|
||||
{
|
||||
if ((!$this->readDataOnly) && (isset($sheet->Objects))) {
|
||||
foreach ($sheet->Objects->children($this->gnm, true) as $key => $comment) {
|
||||
foreach ($sheet->Objects->children(self::NAMESPACE_GNM) as $key => $comment) {
|
||||
$commentAttributes = $comment->attributes();
|
||||
// Only comment objects are handled at the moment
|
||||
if ($commentAttributes->Text) {
|
||||
|
|
@ -278,6 +286,14 @@ class Gnumeric extends BaseReader
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
*/
|
||||
private static function testSimpleXml($value): SimpleXMLElement
|
||||
{
|
||||
return ($value instanceof SimpleXMLElement) ? $value : new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><root></root>');
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads Spreadsheet from file.
|
||||
*
|
||||
|
|
@ -306,12 +322,10 @@ class Gnumeric extends BaseReader
|
|||
$gFileData = $this->gzfileGetContents($pFilename);
|
||||
|
||||
$xml2 = simplexml_load_string($this->securityScanner->scan($gFileData), 'SimpleXMLElement', Settings::getLibXmlLoaderOptions());
|
||||
$xml = ($xml2 !== false) ? $xml2 : new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><root></root>');
|
||||
$namespacesMeta = $xml->getNamespaces(true);
|
||||
$this->gnm = array_key_exists('gmr', $namespacesMeta) ? 'gmr' : 'gnm';
|
||||
$xml = self::testSimpleXml($xml2);
|
||||
|
||||
$gnmXML = $xml->children($namespacesMeta[$this->gnm]);
|
||||
(new Properties($this->spreadsheet))->readProperties($xml, $gnmXML, $namespacesMeta);
|
||||
$gnmXML = $xml->children(self::NAMESPACE_GNM);
|
||||
(new Properties($this->spreadsheet))->readProperties($xml, $gnmXML);
|
||||
|
||||
$worksheetID = 0;
|
||||
foreach ($gnmXML->Sheets->Sheet as $sheet) {
|
||||
|
|
@ -331,7 +345,7 @@ class Gnumeric extends BaseReader
|
|||
$this->spreadsheet->getActiveSheet()->setTitle($worksheetName, false, false);
|
||||
|
||||
if (!$this->readDataOnly) {
|
||||
(new PageSetup($this->spreadsheet, $this->gnm))
|
||||
(new PageSetup($this->spreadsheet))
|
||||
->printInformation($sheet)
|
||||
->sheetMargins($sheet);
|
||||
}
|
||||
|
|
@ -384,7 +398,7 @@ class Gnumeric extends BaseReader
|
|||
if (array_key_exists($vtype, self::$mappings['dataType'])) {
|
||||
$type = self::$mappings['dataType'][$vtype];
|
||||
}
|
||||
if ($vtype == '20') { // Boolean
|
||||
if ($vtype === '20') { // Boolean
|
||||
$cell = $cell == 'TRUE';
|
||||
}
|
||||
}
|
||||
|
|
@ -512,84 +526,122 @@ class Gnumeric extends BaseReader
|
|||
}
|
||||
}
|
||||
|
||||
private function processColumnLoop(int $c, int $maxCol, SimpleXMLElement $columnOverride, float $defaultWidth): int
|
||||
private function setColumnWidth(int $whichColumn, float $defaultWidth): void
|
||||
{
|
||||
$columnAttributes = $columnOverride->attributes();
|
||||
$columnDimension = $this->spreadsheet->getActiveSheet()->getColumnDimension(Coordinate::stringFromColumnIndex($whichColumn + 1));
|
||||
if ($columnDimension !== null) {
|
||||
$columnDimension->setWidth($defaultWidth);
|
||||
}
|
||||
}
|
||||
|
||||
private function setColumnInvisible(int $whichColumn): void
|
||||
{
|
||||
$columnDimension = $this->spreadsheet->getActiveSheet()->getColumnDimension(Coordinate::stringFromColumnIndex($whichColumn + 1));
|
||||
if ($columnDimension !== null) {
|
||||
$columnDimension->setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
private function processColumnLoop(int $whichColumn, int $maxCol, SimpleXMLElement $columnOverride, float $defaultWidth): int
|
||||
{
|
||||
$columnAttributes = self::testSimpleXml($columnOverride->attributes());
|
||||
$column = $columnAttributes['No'];
|
||||
$columnWidth = ((float) $columnAttributes['Unit']) / 5.4;
|
||||
$hidden = (isset($columnAttributes['Hidden'])) && ((string) $columnAttributes['Hidden'] == '1');
|
||||
$columnCount = (int) ($columnAttributes['Count'] ?? 1);
|
||||
while ($c < $column) {
|
||||
$this->spreadsheet->getActiveSheet()->getColumnDimension(Coordinate::stringFromColumnIndex($c + 1))->setWidth($defaultWidth);
|
||||
++$c;
|
||||
while ($whichColumn < $column) {
|
||||
$this->setColumnWidth($whichColumn, $defaultWidth);
|
||||
++$whichColumn;
|
||||
}
|
||||
while (($c < ($column + $columnCount)) && ($c <= $maxCol)) {
|
||||
$this->spreadsheet->getActiveSheet()->getColumnDimension(Coordinate::stringFromColumnIndex($c + 1))->setWidth($columnWidth);
|
||||
while (($whichColumn < ($column + $columnCount)) && ($whichColumn <= $maxCol)) {
|
||||
$this->setColumnWidth($whichColumn, $columnWidth);
|
||||
if ($hidden) {
|
||||
$this->spreadsheet->getActiveSheet()->getColumnDimension(Coordinate::stringFromColumnIndex($c + 1))->setVisible(false);
|
||||
$this->setColumnInvisible($whichColumn);
|
||||
}
|
||||
++$c;
|
||||
++$whichColumn;
|
||||
}
|
||||
|
||||
return $c;
|
||||
return $whichColumn;
|
||||
}
|
||||
|
||||
private function processColumnWidths(SimpleXMLElement $sheet, int $maxCol): void
|
||||
{
|
||||
if ((!$this->readDataOnly) && (isset($sheet->Cols))) {
|
||||
// Column Widths
|
||||
$defaultWidth = 0;
|
||||
$columnAttributes = $sheet->Cols->attributes();
|
||||
if ($columnAttributes !== null) {
|
||||
$defaultWidth = $columnAttributes['DefaultSizePts'] / 5.4;
|
||||
$c = 0;
|
||||
foreach ($sheet->Cols->ColInfo as $columnOverride) {
|
||||
$c = $this->processColumnLoop($c, $maxCol, $columnOverride, $defaultWidth);
|
||||
}
|
||||
while ($c <= $maxCol) {
|
||||
$this->spreadsheet->getActiveSheet()->getColumnDimension(Coordinate::stringFromColumnIndex($c + 1))->setWidth($defaultWidth);
|
||||
++$c;
|
||||
$whichColumn = 0;
|
||||
foreach ($sheet->Cols->ColInfo as $columnOverride) {
|
||||
$whichColumn = $this->processColumnLoop($whichColumn, $maxCol, $columnOverride, $defaultWidth);
|
||||
}
|
||||
while ($whichColumn <= $maxCol) {
|
||||
$this->setColumnWidth($whichColumn, $defaultWidth);
|
||||
++$whichColumn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function processRowLoop(int $r, int $maxRow, SimpleXMLElement $rowOverride, float $defaultHeight): int
|
||||
private function setRowHeight(int $whichRow, float $defaultHeight): void
|
||||
{
|
||||
$rowAttributes = $rowOverride->attributes();
|
||||
$rowDimension = $this->spreadsheet->getActiveSheet()->getRowDimension($whichRow);
|
||||
if ($rowDimension !== null) {
|
||||
$rowDimension->setRowHeight($defaultHeight);
|
||||
}
|
||||
}
|
||||
|
||||
private function setRowInvisible(int $whichRow): void
|
||||
{
|
||||
$rowDimension = $this->spreadsheet->getActiveSheet()->getRowDimension($whichRow);
|
||||
if ($rowDimension !== null) {
|
||||
$rowDimension->setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
private function processRowLoop(int $whichRow, int $maxRow, SimpleXMLElement $rowOverride, float $defaultHeight): int
|
||||
{
|
||||
$rowAttributes = self::testSimpleXml($rowOverride->attributes());
|
||||
$row = $rowAttributes['No'];
|
||||
$rowHeight = (float) $rowAttributes['Unit'];
|
||||
$hidden = (isset($rowAttributes['Hidden'])) && ((string) $rowAttributes['Hidden'] == '1');
|
||||
$rowCount = (int) ($rowAttributes['Count'] ?? 1);
|
||||
while ($r < $row) {
|
||||
++$r;
|
||||
$this->spreadsheet->getActiveSheet()->getRowDimension($r)->setRowHeight($defaultHeight);
|
||||
while ($whichRow < $row) {
|
||||
++$whichRow;
|
||||
$this->setRowHeight($whichRow, $defaultHeight);
|
||||
}
|
||||
while (($r < ($row + $rowCount)) && ($r < $maxRow)) {
|
||||
++$r;
|
||||
$this->spreadsheet->getActiveSheet()->getRowDimension($r)->setRowHeight($rowHeight);
|
||||
while (($whichRow < ($row + $rowCount)) && ($whichRow < $maxRow)) {
|
||||
++$whichRow;
|
||||
$this->setRowHeight($whichRow, $rowHeight);
|
||||
if ($hidden) {
|
||||
$this->spreadsheet->getActiveSheet()->getRowDimension($r)->setVisible(false);
|
||||
$this->setRowInvisible($whichRow);
|
||||
}
|
||||
}
|
||||
|
||||
return $r;
|
||||
return $whichRow;
|
||||
}
|
||||
|
||||
private function processRowHeights(SimpleXMLElement $sheet, int $maxRow): void
|
||||
{
|
||||
if ((!$this->readDataOnly) && (isset($sheet->Rows))) {
|
||||
// Row Heights
|
||||
$defaultHeight = 0;
|
||||
$rowAttributes = $sheet->Rows->attributes();
|
||||
if ($rowAttributes !== null) {
|
||||
$defaultHeight = (float) $rowAttributes['DefaultSizePts'];
|
||||
$r = 0;
|
||||
}
|
||||
$whichRow = 0;
|
||||
|
||||
foreach ($sheet->Rows->RowInfo as $rowOverride) {
|
||||
$r = $this->processRowLoop($r, $maxRow, $rowOverride, $defaultHeight);
|
||||
$whichRow = $this->processRowLoop($whichRow, $maxRow, $rowOverride, $defaultHeight);
|
||||
}
|
||||
// never executed, I can't figure out any circumstances
|
||||
// under which it would be executed, and, even if
|
||||
// such exist, I'm not convinced this is needed.
|
||||
//while ($r < $maxRow) {
|
||||
// ++$r;
|
||||
// $this->spreadsheet->getActiveSheet()->getRowDimension($r)->setRowHeight($defaultHeight);
|
||||
//while ($whichRow < $maxRow) {
|
||||
// ++$whichRow;
|
||||
// $this->spreadsheet->getActiveSheet()->getRowDimension($whichRow)->setRowHeight($defaultHeight);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
|
@ -641,19 +693,21 @@ class Gnumeric extends BaseReader
|
|||
}
|
||||
}
|
||||
|
||||
private static function parseBorderAttributes($borderAttributes)
|
||||
private static function parseBorderAttributes(?SimpleXMLElement $borderAttributes): array
|
||||
{
|
||||
$styleArray = [];
|
||||
if ($borderAttributes !== null) {
|
||||
if (isset($borderAttributes['Color'])) {
|
||||
$styleArray['color']['rgb'] = self::parseGnumericColour($borderAttributes['Color']);
|
||||
}
|
||||
|
||||
self::addStyle($styleArray, 'borderStyle', $borderAttributes['Style']);
|
||||
}
|
||||
|
||||
return $styleArray;
|
||||
}
|
||||
|
||||
private function parseRichText($is)
|
||||
private function parseRichText(string $is): RichText
|
||||
{
|
||||
$value = new RichText();
|
||||
$value->createText($is);
|
||||
|
|
@ -661,7 +715,7 @@ class Gnumeric extends BaseReader
|
|||
return $value;
|
||||
}
|
||||
|
||||
private static function parseGnumericColour($gnmColour)
|
||||
private static function parseGnumericColour(string $gnmColour): string
|
||||
{
|
||||
[$gnmR, $gnmG, $gnmB] = explode(':', $gnmColour);
|
||||
$gnmR = substr(str_pad($gnmR, 4, '0', STR_PAD_RIGHT), 0, 2);
|
||||
|
|
@ -679,7 +733,7 @@ class Gnumeric extends BaseReader
|
|||
$shade = (string) $styleAttributes['Shade'];
|
||||
if (($RGB != '000000') || ($shade != '0')) {
|
||||
$RGB2 = self::parseGnumericColour($styleAttributes['PatternColor']);
|
||||
if ($shade == '1') {
|
||||
if ($shade === '1') {
|
||||
$styleArray['fill']['startColor']['rgb'] = $RGB;
|
||||
$styleArray['fill']['endColor']['rgb'] = $RGB2;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheet\Reader\Gnumeric;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Gnumeric;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\PageMargins;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\PageSetup as WorksheetPageSetup;
|
||||
|
|
@ -14,15 +15,9 @@ class PageSetup
|
|||
*/
|
||||
private $spreadsheet;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $gnm;
|
||||
|
||||
public function __construct(Spreadsheet $spreadsheet, string $gnm)
|
||||
public function __construct(Spreadsheet $spreadsheet)
|
||||
{
|
||||
$this->spreadsheet = $spreadsheet;
|
||||
$this->gnm = $gnm;
|
||||
}
|
||||
|
||||
public function printInformation(SimpleXMLElement $sheet): self
|
||||
|
|
@ -68,7 +63,7 @@ class PageSetup
|
|||
|
||||
private function buildMarginSet(SimpleXMLElement $sheet, array $marginSet): array
|
||||
{
|
||||
foreach ($sheet->PrintInformation->Margins->children($this->gnm, true) as $key => $margin) {
|
||||
foreach ($sheet->PrintInformation->Margins->children(Gnumeric::NAMESPACE_GNM) as $key => $margin) {
|
||||
$marginAttributes = $margin->attributes();
|
||||
$marginSize = ($marginAttributes['Points']) ?? 72; // Default is 72pt
|
||||
// Convert value in points to inches
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheet\Reader\Gnumeric;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Gnumeric;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use SimpleXMLElement;
|
||||
|
||||
|
|
@ -91,15 +92,12 @@ class Properties
|
|||
}
|
||||
}
|
||||
|
||||
private function docPropertiesMeta(SimpleXMLElement $officePropertyMeta, array $namespacesMeta): void
|
||||
private function docPropertiesMeta(SimpleXMLElement $officePropertyMeta): void
|
||||
{
|
||||
$docProps = $this->spreadsheet->getProperties();
|
||||
foreach ($officePropertyMeta as $propertyName => $propertyValue) {
|
||||
if ($propertyValue === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$attributes = $propertyValue->attributes($namespacesMeta['meta']);
|
||||
if ($propertyValue !== null) {
|
||||
$attributes = $propertyValue->attributes(Gnumeric::NAMESPACE_META);
|
||||
$propertyValue = trim((string) $propertyValue);
|
||||
switch ($propertyName) {
|
||||
case 'keyword':
|
||||
|
|
@ -120,6 +118,17 @@ class Properties
|
|||
break;
|
||||
case 'user-defined':
|
||||
[, $attrName] = explode(':', $attributes['name']);
|
||||
$this->userDefinedProperties($attrName, $propertyValue);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function userDefinedProperties(string $attrName, string $propertyValue): void
|
||||
{
|
||||
$docProps = $this->spreadsheet->getProperties();
|
||||
switch ($attrName) {
|
||||
case 'publisher':
|
||||
$docProps->setCompany($propertyValue);
|
||||
|
|
@ -134,31 +143,21 @@ class Properties
|
|||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function readProperties(SimpleXMLElement $xml, SimpleXMLElement $gnmXML, array $namespacesMeta): void
|
||||
public function readProperties(SimpleXMLElement $xml, SimpleXMLElement $gnmXML): void
|
||||
{
|
||||
if (isset($namespacesMeta['office'])) {
|
||||
$officeXML = $xml->children($namespacesMeta['office']);
|
||||
$officeXML = $xml->children(Gnumeric::NAMESPACE_OFFICE);
|
||||
if (!empty($officeXML)) {
|
||||
$officeDocXML = $officeXML->{'document-meta'};
|
||||
$officeDocMetaXML = $officeDocXML->meta;
|
||||
|
||||
foreach ($officeDocMetaXML as $officePropertyData) {
|
||||
$officePropertyDC = [];
|
||||
if (isset($namespacesMeta['dc'])) {
|
||||
$officePropertyDC = $officePropertyData->children($namespacesMeta['dc']);
|
||||
}
|
||||
$officePropertyDC = $officePropertyData->children(Gnumeric::NAMESPACE_DC);
|
||||
$this->docPropertiesDC($officePropertyDC);
|
||||
|
||||
$officePropertyMeta = [];
|
||||
if (isset($namespacesMeta['meta'])) {
|
||||
$officePropertyMeta = $officePropertyData->children($namespacesMeta['meta']);
|
||||
}
|
||||
$this->docPropertiesMeta($officePropertyMeta, $namespacesMeta);
|
||||
$officePropertyMeta = $officePropertyData->children(Gnumeric::NAMESPACE_META);
|
||||
$this->docPropertiesMeta($officePropertyMeta);
|
||||
}
|
||||
} elseif (isset($gnmXML->Summary)) {
|
||||
$this->docPropertiesOld($gnmXML);
|
||||
|
|
|
|||
|
|
@ -115,7 +115,8 @@ class GnumericLoadTest extends TestCase
|
|||
self::assertEquals(Font::UNDERLINE_DOUBLE, $sheet->getCell('A24')->getStyle()->getFont()->getUnderline());
|
||||
self::assertTrue($sheet->getCell('B23')->getStyle()->getFont()->getSubScript());
|
||||
self::assertTrue($sheet->getCell('B24')->getStyle()->getFont()->getSuperScript());
|
||||
self::assertFalse($sheet->getRowDimension(30)->getVisible());
|
||||
$rowDimension = $sheet->getRowDimension(30);
|
||||
self::assertFalse($rowDimension->getVisible());
|
||||
}
|
||||
|
||||
public function testLoadFilter(): void
|
||||
|
|
|
|||
Loading…
Reference in New Issue