Fix XLSX Writer on Windows plaftorms

A bug was introduced, preventing Spout to create valid XLSX files on Windows.
This commits reverts the changes that introduced DIRECTORY_SEPARATOR everywhere
and fixes the original issue with the writer by normalizing paths when creating
the zipped file.
This commit is contained in:
Adrien Loison 2015-07-01 15:24:53 -07:00
parent c6ebf115fc
commit b3df57d2e5
9 changed files with 29 additions and 38 deletions

View File

@ -36,7 +36,7 @@ class FileSystemHelper
{
$this->throwIfOperationNotInBaseFolder($parentFolderPath);
$folderPath = $parentFolderPath . DIRECTORY_SEPARATOR . $folderName;
$folderPath = $parentFolderPath . '/' . $folderName;
$wasCreationSuccessful = mkdir($folderPath, 0777, true);
if (!$wasCreationSuccessful) {
@ -60,7 +60,7 @@ class FileSystemHelper
{
$this->throwIfOperationNotInBaseFolder($parentFolderPath);
$filePath = $parentFolderPath . DIRECTORY_SEPARATOR . $fileName;
$filePath = $parentFolderPath . '/' . $fileName;
$wasCreationSuccessful = file_put_contents($filePath, $fileContents);
if (!$wasCreationSuccessful) {

View File

@ -162,12 +162,11 @@ class SharedStringsHelper
}
/**
* @return string The path to the shared strings XML file, working cross-platforms
* @return string The path to the shared strings XML file
*/
protected function getSharedStringsFilePath()
{
$sharedStringsXmlFilePath = str_replace('/', DIRECTORY_SEPARATOR, self::SHARED_STRINGS_XML_FILE_PATH);
return 'zip://' . $this->filePath . '#' . $sharedStringsXmlFilePath;
return 'zip://' . $this->filePath . '#' . self::SHARED_STRINGS_XML_FILE_PATH;
}
/**
@ -250,7 +249,7 @@ class SharedStringsHelper
protected function getSharedStringTempFilePath($sharedStringIndex)
{
$numTempFile = intval($sharedStringIndex / self::MAX_NUM_STRINGS_PER_TEMP_FILE);
return $this->tempFolder . DIRECTORY_SEPARATOR . 'sharedstrings' . $numTempFile;
return $this->tempFolder . '/sharedstrings' . $numTempFile;
}
/**

View File

@ -186,8 +186,7 @@ class WorksheetHelper
*/
protected function getFileAsXMLElementWithNamespace($xmlFilePath, $mainNamespace)
{
$normalizedXmlFilePath = str_replace('/', DIRECTORY_SEPARATOR, $xmlFilePath);
$xmlContents = $this->globalFunctionsHelper->file_get_contents('zip://' . $this->filePath . '#' . $normalizedXmlFilePath);
$xmlContents = $this->globalFunctionsHelper->file_get_contents('zip://' . $this->filePath . '#' . $xmlFilePath);
$xmlElement = new \SimpleXMLElement($xmlContents);
$xmlElement->registerXPathNamespace('ns', $mainNamespace);

View File

@ -33,12 +33,11 @@ class Worksheet
/**
* @return string Path of the XML file containing the worksheet data,
* without the leading slash and working cross-platforms.
* without the leading slash.
*/
public function getDataXmlFilePath()
{
$dataXmlFilePath = ltrim($this->dataXmlFilePath, '/');
return str_replace('/', DIRECTORY_SEPARATOR, $dataXmlFilePath);
return ltrim($this->dataXmlFilePath, '/');
}
/**

View File

@ -36,7 +36,7 @@ EOD;
*/
public function __construct($xlFolder)
{
$sharedStringsFilePath = $xlFolder . DIRECTORY_SEPARATOR . self::SHARED_STRINGS_FILE_NAME;
$sharedStringsFilePath = $xlFolder . '/' . self::SHARED_STRINGS_FILE_NAME;
$this->sharedStringsFilePointer = fopen($sharedStringsFilePath, 'w');
$this->throwIfSharedStringsFilePointerIsNotAvailable();

View File

@ -33,18 +33,30 @@ class ZipHelper
*/
protected function addFolderToZip($zip, $folderPath)
{
$folderRealPath = realpath($folderPath) . DIRECTORY_SEPARATOR;
$folderRealPath = $this->getNormalizedRealPath($folderPath) . '/';
$itemIterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($folderPath, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST);
foreach ($itemIterator as $itemInfo) {
$itemRealPath = realpath($itemInfo->getPathname());
$itemRealPath = $this->getNormalizedRealPath($itemInfo->getPathname());
$itemLocalPath = str_replace($folderRealPath, '', $itemRealPath);
if ($itemInfo->isFile()) {
$zip->addFile($itemInfo->getPathname(), $itemLocalPath);
$zip->addFile($itemRealPath, $itemLocalPath);
} else if ($itemInfo->isDir()) {
$zip->addEmptyDir($itemLocalPath);
}
}
}
/**
* Returns canonicalized absolute pathname, containing only forward slashes.
*
* @param string $path Path to normalize
* @return string Normalized and canonicalized path
*/
protected function getNormalizedRealPath($path)
{
$realPath = realpath($path);
return str_replace(DIRECTORY_SEPARATOR, '/', $realPath);
}
}

View File

@ -56,7 +56,7 @@ EOD;
$this->stringsEscaper = new \Box\Spout\Common\Escaper\XLSX();
$this->worksheetFilePath = $worksheetFilesFolder . DIRECTORY_SEPARATOR . strtolower($this->externalSheet->getName()) . '.xml';
$this->worksheetFilePath = $worksheetFilesFolder . '/' . strtolower($this->externalSheet->getName()) . '.xml';
$this->startSheet();
}

View File

@ -90,18 +90,9 @@ class SheetTest extends \PHPUnit_Framework_TestCase
*/
private function assertSheetNameEquals($expectedName, $resourcePath, $message = '')
{
$pathToWorkbookFile = $resourcePath . $this->normalizePath('#xl/workbook.xml');
$pathToWorkbookFile = $resourcePath . '#xl/workbook.xml';
$xmlContents = file_get_contents('zip://' . $pathToWorkbookFile);
$this->assertContains('<sheet name="' . $expectedName . '"', $xmlContents, $message);
}
/**
* @param string $path
* @return string The path with the correct directory separators, as defined for the current platform
*/
private function normalizePath($path)
{
return str_replace('/', DIRECTORY_SEPARATOR, $path);
}
}

View File

@ -408,7 +408,7 @@ class XLSXTest extends \PHPUnit_Framework_TestCase
private function assertInlineDataWasWrittenToSheet($fileName, $sheetIndex, $inlineData, $message = '')
{
$resourcePath = $this->getGeneratedResourcePath($fileName);
$pathToSheetFile = $resourcePath . $this->normalizePath('#xl/worksheets/sheet' . $sheetIndex . '.xml');
$pathToSheetFile = $resourcePath . '#xl/worksheets/sheet' . $sheetIndex . '.xml';
$xmlContents = file_get_contents('zip://' . $pathToSheetFile);
$this->assertContains((string)$inlineData, $xmlContents, $message);
@ -424,7 +424,7 @@ class XLSXTest extends \PHPUnit_Framework_TestCase
private function assertInlineDataWasNotWrittenToSheet($fileName, $sheetIndex, $inlineData, $message = '')
{
$resourcePath = $this->getGeneratedResourcePath($fileName);
$pathToSheetFile = $resourcePath . $this->normalizePath('#xl/worksheets/sheet' . $sheetIndex . '.xml');
$pathToSheetFile = $resourcePath . '#xl/worksheets/sheet' . $sheetIndex . '.xml';
$xmlContents = file_get_contents('zip://' . $pathToSheetFile);
$this->assertNotContains((string)$inlineData, $xmlContents, $message);
@ -439,18 +439,9 @@ class XLSXTest extends \PHPUnit_Framework_TestCase
private function assertSharedStringWasWritten($fileName, $sharedString, $message = '')
{
$resourcePath = $this->getGeneratedResourcePath($fileName);
$pathToSharedStringsFile = $resourcePath . $this->normalizePath('#xl/sharedStrings.xml');
$pathToSharedStringsFile = $resourcePath . '#xl/sharedStrings.xml';
$xmlContents = file_get_contents('zip://' . $pathToSharedStringsFile);
$this->assertContains($sharedString, $xmlContents, $message);
}
/**
* @param string $path
* @return string The path with the correct directory separators, as defined for the current platform
*/
private function normalizePath($path)
{
return str_replace('/', DIRECTORY_SEPARATOR, $path);
}
}