Skip to content

Commit

Permalink
Refactoring xlsx reader (#1033)
Browse files Browse the repository at this point in the history
Start work on breaking up monolithic Reader and Writer classes into dedicated subclasses to make maintenance work easier
  • Loading branch information
Mark Baker authored Jun 30, 2019
1 parent e884271 commit 1e71154
Show file tree
Hide file tree
Showing 25 changed files with 1,596 additions and 683 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
]
},
"require": {
"php": "5.6|^7.0",
"php": "^5.6|^7.0",
"ext-ctype": "*",
"ext-dom": "*",
"ext-gd": "*",
Expand Down
2 changes: 1 addition & 1 deletion src/PhpSpreadsheet/Document/Properties.php
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ public function isCustomPropertySet($propertyName)
*
* @param string $propertyName
*
* @return string
* @return mixed
*/
public function getCustomPropertyValue($propertyName)
{
Expand Down
98 changes: 7 additions & 91 deletions src/PhpSpreadsheet/Reader/Ods.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\Cell\DataType;
use PhpOffice\PhpSpreadsheet\Document\Properties;
use PhpOffice\PhpSpreadsheet\Reader\Ods\Properties as DocumentProperties;
use PhpOffice\PhpSpreadsheet\Reader\Security\XmlScanner;
use PhpOffice\PhpSpreadsheet\RichText\RichText;
use PhpOffice\PhpSpreadsheet\Settings;
Expand Down Expand Up @@ -265,7 +265,7 @@ public function loadIntoExisting($pFilename, Spreadsheet $spreadsheet)

$zip = new ZipArchive();
if (!$zip->open($pFilename)) {
throw new Exception('Could not open ' . $pFilename . ' for reading! Error opening file.');
throw new Exception("Could not open {$pFilename} for reading! Error opening file.");
}

// Meta
Expand All @@ -275,97 +275,13 @@ public function loadIntoExisting($pFilename, Spreadsheet $spreadsheet)
'SimpleXMLElement',
Settings::getLibXmlLoaderOptions()
);
$namespacesMeta = $xml->getNamespaces(true);
if ($xml === false) {
throw new Exception('Unable to read data from {$pFilename}');
}

$docProps = $spreadsheet->getProperties();
$officeProperty = $xml->children($namespacesMeta['office']);
foreach ($officeProperty as $officePropertyData) {
$officePropertyDC = [];
if (isset($namespacesMeta['dc'])) {
$officePropertyDC = $officePropertyData->children($namespacesMeta['dc']);
}
foreach ($officePropertyDC as $propertyName => $propertyValue) {
$propertyValue = (string) $propertyValue;
switch ($propertyName) {
case 'title':
$docProps->setTitle($propertyValue);

break;
case 'subject':
$docProps->setSubject($propertyValue);

break;
case 'creator':
$docProps->setCreator($propertyValue);
$docProps->setLastModifiedBy($propertyValue);

break;
case 'date':
$creationDate = strtotime($propertyValue);
$docProps->setCreated($creationDate);
$docProps->setModified($creationDate);

break;
case 'description':
$docProps->setDescription($propertyValue);

break;
}
}
$officePropertyMeta = [];
if (isset($namespacesMeta['dc'])) {
$officePropertyMeta = $officePropertyData->children($namespacesMeta['meta']);
}
foreach ($officePropertyMeta as $propertyName => $propertyValue) {
$propertyValueAttributes = $propertyValue->attributes($namespacesMeta['meta']);
$propertyValue = (string) $propertyValue;
switch ($propertyName) {
case 'initial-creator':
$docProps->setCreator($propertyValue);

break;
case 'keyword':
$docProps->setKeywords($propertyValue);

break;
case 'creation-date':
$creationDate = strtotime($propertyValue);
$docProps->setCreated($creationDate);

break;
case 'user-defined':
$propertyValueType = Properties::PROPERTY_TYPE_STRING;
foreach ($propertyValueAttributes as $key => $value) {
if ($key == 'name') {
$propertyValueName = (string) $value;
} elseif ($key == 'value-type') {
switch ($value) {
case 'date':
$propertyValue = Properties::convertProperty($propertyValue, 'date');
$propertyValueType = Properties::PROPERTY_TYPE_DATE;

break;
case 'boolean':
$propertyValue = Properties::convertProperty($propertyValue, 'bool');
$propertyValueType = Properties::PROPERTY_TYPE_BOOLEAN;

break;
case 'float':
$propertyValue = Properties::convertProperty($propertyValue, 'r4');
$propertyValueType = Properties::PROPERTY_TYPE_FLOAT;

break;
default:
$propertyValueType = Properties::PROPERTY_TYPE_STRING;
}
}
}
$docProps->setCustomProperty($propertyValueName, $propertyValue, $propertyValueType);
$namespacesMeta = $xml->getNamespaces(true);

break;
}
}
}
(new DocumentProperties($spreadsheet))->load($xml, $namespacesMeta);

// Content

Expand Down
136 changes: 136 additions & 0 deletions src/PhpSpreadsheet/Reader/Ods/Properties.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
<?php

namespace PhpOffice\PhpSpreadsheet\Reader\Ods;

use PhpOffice\PhpSpreadsheet\Document\Properties as DocumentProperties;
use PhpOffice\PhpSpreadsheet\Spreadsheet;

class Properties
{
private $spreadsheet;

public function __construct(Spreadsheet $spreadsheet)
{
$this->spreadsheet = $spreadsheet;
}

public function load(\SimpleXMLElement $xml, $namespacesMeta)
{
$docProps = $this->spreadsheet->getProperties();
$officeProperty = $xml->children($namespacesMeta['office']);
foreach ($officeProperty as $officePropertyData) {
/** @var \SimpleXMLElement $officePropertyData */
$officePropertiesDC = [];
if (isset($namespacesMeta['dc'])) {
$officePropertiesDC = $officePropertyData->children($namespacesMeta['dc']);
}
$this->setCoreProperties($docProps, $officePropertiesDC);

$officePropertyMeta = [];
if (isset($namespacesMeta['dc'])) {
$officePropertyMeta = $officePropertyData->children($namespacesMeta['meta']);
}
foreach ($officePropertyMeta as $propertyName => $propertyValue) {
$this->setMetaProperties($namespacesMeta, $propertyValue, $propertyName, $docProps);
}
}
}

private function setCoreProperties(DocumentProperties $docProps, \SimpleXMLElement $officePropertyDC)
{
foreach ($officePropertyDC as $propertyName => $propertyValue) {
$propertyValue = (string) $propertyValue;
switch ($propertyName) {
case 'title':
$docProps->setTitle($propertyValue);

break;
case 'subject':
$docProps->setSubject($propertyValue);

break;
case 'creator':
$docProps->setCreator($propertyValue);
$docProps->setLastModifiedBy($propertyValue);

break;
case 'creation-date':
$creationDate = strtotime($propertyValue);
$docProps->setCreated($creationDate);
$docProps->setModified($creationDate);

break;
case 'keyword':
$docProps->setKeywords($propertyValue);

break;
case 'description':
$docProps->setDescription($propertyValue);

break;
}
}
}

private function setMetaProperties(
$namespacesMeta,
\SimpleXMLElement $propertyValue,
$propertyName,
DocumentProperties $docProps
) {
$propertyValueAttributes = $propertyValue->attributes($namespacesMeta['meta']);
$propertyValue = (string) $propertyValue;
switch ($propertyName) {
case 'initial-creator':
$docProps->setCreator($propertyValue);

break;
case 'keyword':
$docProps->setKeywords($propertyValue);

break;
case 'creation-date':
$creationDate = strtotime($propertyValue);
$docProps->setCreated($creationDate);

break;
case 'user-defined':
$this->setUserDefinedProperty($propertyValueAttributes, $propertyValue, $docProps);

break;
}
}

private function setUserDefinedProperty($propertyValueAttributes, $propertyValue, DocumentProperties $docProps)
{
$propertyValueName = '';
$propertyValueType = DocumentProperties::PROPERTY_TYPE_STRING;
foreach ($propertyValueAttributes as $key => $value) {
if ($key == 'name') {
$propertyValueName = (string) $value;
} elseif ($key == 'value-type') {
switch ($value) {
case 'date':
$propertyValue = DocumentProperties::convertProperty($propertyValue, 'date');
$propertyValueType = DocumentProperties::PROPERTY_TYPE_DATE;

break;
case 'boolean':
$propertyValue = DocumentProperties::convertProperty($propertyValue, 'bool');
$propertyValueType = DocumentProperties::PROPERTY_TYPE_BOOLEAN;

break;
case 'float':
$propertyValue = DocumentProperties::convertProperty($propertyValue, 'r4');
$propertyValueType = DocumentProperties::PROPERTY_TYPE_FLOAT;

break;
default:
$propertyValueType = DocumentProperties::PROPERTY_TYPE_STRING;
}
}
}

$docProps->setCustomProperty($propertyValueName, $propertyValue, $propertyValueType);
}
}
Loading

0 comments on commit 1e71154

Please sign in to comment.