ODS writer
Added ODS writer Refactored XLSX writer to abstract some pieces into an abstract multi-sheets writer Created an abstract style helper Moved shared components around
This commit is contained in:
1 parent
a8f1fba854
commit
5949cb2442
39 files changed
+2924
-533
No files matched your search
@@ -34,6 +34,7 @@ class XLSXTest extends \PHPUnit_Framework_TestCase
|
||||
*/
|
||||
public function testEscape($stringToEscape, $expectedEscapedString)
|
||||
{
|
||||
/** @noinspection PhpUnnecessaryFullyQualifiedNameInspection */
|
||||
$escaper = new \Box\Spout\Common\Escaper\XLSX();
|
||||
$escapedString = $escaper->escape($stringToEscape);
|
||||
|
||||
@@ -65,6 +66,7 @@ class XLSXTest extends \PHPUnit_Framework_TestCase
|
||||
*/
|
||||
public function testUnescape($stringToUnescape, $expectedUnescapedString)
|
||||
{
|
||||
/** @noinspection PhpUnnecessaryFullyQualifiedNameInspection */
|
||||
$escaper = new \Box\Spout\Common\Escaper\XLSX();
|
||||
$unescapedString = $escaper->unescape($stringToUnescape);
|
||||
|
||||
|
||||
+2
-2
@@ -1,11 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace Box\Spout\Writer\XLSX\Helper;
|
||||
namespace Box\Spout\Writer\Common\Helper;
|
||||
|
||||
/**
|
||||
* Class CellHelperTest
|
||||
*
|
||||
* @package Box\Spout\Writer\XLSX\Helper
|
||||
* @package Box\Spout\Writer\Common\Helper
|
||||
*/
|
||||
class CellHelperTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
namespace Box\Spout\Writer\Common;
|
||||
|
||||
/**
|
||||
* Class SheetTest
|
||||
*
|
||||
* @package Box\Spout\Writer\Common
|
||||
*/
|
||||
class SheetTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testGetSheetName()
|
||||
{
|
||||
$sheets = [new Sheet(0), new Sheet(1)];
|
||||
|
||||
$this->assertEquals('Sheet1', $sheets[0]->getName(), 'Invalid name for the first sheet');
|
||||
$this->assertEquals('Sheet2', $sheets[1]->getName(), 'Invalid name for the second sheet');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testSetSheetNameShouldCreateSheetWithCustomName()
|
||||
{
|
||||
$customSheetName = 'CustomName';
|
||||
$sheet = new Sheet(0);
|
||||
$sheet->setName($customSheetName);
|
||||
|
||||
$this->assertEquals($customSheetName, $sheet->getName(), "The sheet name should have been changed to '$customSheetName'");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function dataProviderForInvalidSheetNames()
|
||||
{
|
||||
return [
|
||||
[null],
|
||||
[21],
|
||||
[''],
|
||||
['this title exceeds the 31 characters limit'],
|
||||
['Illegal \\'],
|
||||
['Illegal /'],
|
||||
['Illegal ?'],
|
||||
['Illegal *'],
|
||||
['Illegal :'],
|
||||
['Illegal ['],
|
||||
['Illegal ]'],
|
||||
['\'Illegal start'],
|
||||
['Illegal end\''],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataProviderForInvalidSheetNames
|
||||
* @expectedException \Box\Spout\Writer\Exception\InvalidSheetNameException
|
||||
*
|
||||
* @param string $customSheetName
|
||||
* @return void
|
||||
*/
|
||||
public function testSetSheetNameShouldThrowOnInvalidName($customSheetName)
|
||||
{
|
||||
(new Sheet(0))->setName($customSheetName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testSetSheetNameShouldNotThrowWhenSettingSameNameAsCurrentOne()
|
||||
{
|
||||
$customSheetName = 'Sheet name';
|
||||
$sheet = new Sheet(0);
|
||||
$sheet->setName($customSheetName);
|
||||
$sheet->setName($customSheetName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Box\Spout\Writer\Exception\InvalidSheetNameException
|
||||
* @return void
|
||||
*/
|
||||
public function testSetSheetNameShouldThrowWhenNameIsAlreadyUsed()
|
||||
{
|
||||
$customSheetName = 'Sheet name';
|
||||
|
||||
$sheet = new Sheet(0);
|
||||
$sheet->setName($customSheetName);
|
||||
|
||||
$sheet = new Sheet(1);
|
||||
$sheet->setName($customSheetName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
namespace Box\Spout\Writer\ODS\Helper;
|
||||
|
||||
use Box\Spout\Writer\Style\StyleBuilder;
|
||||
|
||||
/**
|
||||
* Class StyleHelperTest
|
||||
*
|
||||
* @package Box\Spout\Writer\ODS\Helper
|
||||
*/
|
||||
class StyleHelperTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/** @var \Box\Spout\Writer\Style\Style */
|
||||
protected $defaultStyle;
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function setUp()
|
||||
{
|
||||
$this->defaultStyle = (new StyleBuilder())->build();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testRegisterStyleShouldUpdateId()
|
||||
{
|
||||
$style1 = (new StyleBuilder())->setFontBold()->build();
|
||||
$style2 = (new StyleBuilder())->setFontUnderline()->build();
|
||||
|
||||
$this->assertEquals(0, $this->defaultStyle->getId(), 'Default style ID should be 0');
|
||||
$this->assertNull($style1->getId());
|
||||
$this->assertNull($style2->getId());
|
||||
|
||||
$styleHelper = new StyleHelper($this->defaultStyle);
|
||||
$registeredStyle1 = $styleHelper->registerStyle($style1);
|
||||
$registeredStyle2 = $styleHelper->registerStyle($style2);
|
||||
|
||||
$this->assertEquals(1, $registeredStyle1->getId());
|
||||
$this->assertEquals(2, $registeredStyle2->getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testRegisterStyleShouldReuseAlreadyRegisteredStyles()
|
||||
{
|
||||
$style = (new StyleBuilder())->setFontBold()->build();
|
||||
|
||||
$styleHelper = new StyleHelper($this->defaultStyle);
|
||||
$registeredStyle1 = $styleHelper->registerStyle($style);
|
||||
$registeredStyle2 = $styleHelper->registerStyle($style);
|
||||
|
||||
$this->assertEquals(1, $registeredStyle1->getId());
|
||||
$this->assertEquals(1, $registeredStyle2->getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testApplyExtraStylesIfNeededShouldApplyWrapTextIfCellContainsNewLine()
|
||||
{
|
||||
$style = clone $this->defaultStyle;
|
||||
$styleHelper = new StyleHelper($this->defaultStyle);
|
||||
|
||||
$this->assertFalse($style->shouldWrapText());
|
||||
|
||||
$updatedStyle = $styleHelper->applyExtraStylesIfNeeded($style, [12, 'single line', "multi\nlines", null]);
|
||||
|
||||
$this->assertTrue($updatedStyle->shouldWrapText());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testApplyExtraStylesIfNeededShouldDoNothingIfWrapTextAlreadyApplied()
|
||||
{
|
||||
$style = (new StyleBuilder())->setShouldWrapText()->build();
|
||||
$styleHelper = new StyleHelper($this->defaultStyle);
|
||||
|
||||
$this->assertTrue($style->shouldWrapText());
|
||||
|
||||
$updatedStyle = $styleHelper->applyExtraStylesIfNeeded($style, ["multi\nlines"]);
|
||||
|
||||
$this->assertTrue($updatedStyle->shouldWrapText());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
namespace Box\Spout\Writer\ODS;
|
||||
|
||||
use Box\Spout\Common\Type;
|
||||
use Box\Spout\TestUsingResource;
|
||||
use Box\Spout\Writer\Common\Sheet;
|
||||
use Box\Spout\Writer\WriterFactory;
|
||||
|
||||
/**
|
||||
* Class SheetTest
|
||||
*
|
||||
* @package Box\Spout\Writer\ODS
|
||||
*/
|
||||
class SheetTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
use TestUsingResource;
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testGetSheetIndex()
|
||||
{
|
||||
$sheets = $this->writeDataToMulitpleSheetsAndReturnSheets('test_get_sheet_index.ods');
|
||||
|
||||
$this->assertEquals(2, count($sheets), '2 sheets should have been created');
|
||||
$this->assertEquals(0, $sheets[0]->getIndex(), 'The first sheet should be index 0');
|
||||
$this->assertEquals(1, $sheets[1]->getIndex(), 'The second sheet should be index 1');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testGetSheetName()
|
||||
{
|
||||
$sheets = $this->writeDataToMulitpleSheetsAndReturnSheets('test_get_sheet_name.ods');
|
||||
|
||||
$this->assertEquals(2, count($sheets), '2 sheets should have been created');
|
||||
$this->assertEquals('Sheet1', $sheets[0]->getName(), 'Invalid name for the first sheet');
|
||||
$this->assertEquals('Sheet2', $sheets[1]->getName(), 'Invalid name for the second sheet');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testSetSheetNameShouldCreateSheetWithCustomName()
|
||||
{
|
||||
$fileName = 'test_set_name_should_create_sheet_with_custom_name.ods';
|
||||
$customSheetName = 'CustomName';
|
||||
$this->writeDataAndReturnSheetWithCustomName($fileName, $customSheetName);
|
||||
|
||||
$this->assertSheetNameEquals($customSheetName, $fileName, "The sheet name should have been changed to '$customSheetName'");
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Box\Spout\Writer\Exception\InvalidSheetNameException
|
||||
* @return void
|
||||
*/
|
||||
public function testSetSheetNameShouldThrowWhenNameIsAlreadyUsed()
|
||||
{
|
||||
$fileName = 'test_set_name_with_non_unique_name.ods';
|
||||
$this->createGeneratedFolderIfNeeded($fileName);
|
||||
$resourcePath = $this->getGeneratedResourcePath($fileName);
|
||||
|
||||
$writer = WriterFactory::create(Type::ODS);
|
||||
$writer->openToFile($resourcePath);
|
||||
|
||||
$customSheetName = 'Sheet name';
|
||||
|
||||
$sheet = $writer->getCurrentSheet();
|
||||
$sheet->setName($customSheetName);
|
||||
|
||||
$writer->addNewSheetAndMakeItCurrent();
|
||||
$sheet = $writer->getCurrentSheet();
|
||||
$sheet->setName($customSheetName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $fileName
|
||||
* @param string $sheetName
|
||||
* @return Sheet
|
||||
*/
|
||||
private function writeDataAndReturnSheetWithCustomName($fileName, $sheetName)
|
||||
{
|
||||
$this->createGeneratedFolderIfNeeded($fileName);
|
||||
$resourcePath = $this->getGeneratedResourcePath($fileName);
|
||||
|
||||
$writer = WriterFactory::create(Type::ODS);
|
||||
$writer->openToFile($resourcePath);
|
||||
|
||||
$sheet = $writer->getCurrentSheet();
|
||||
$sheet->setName($sheetName);
|
||||
|
||||
$writer->addRow(['ods--11', 'ods--12']);
|
||||
$writer->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $fileName
|
||||
* @return Sheet[]
|
||||
*/
|
||||
private function writeDataToMulitpleSheetsAndReturnSheets($fileName)
|
||||
{
|
||||
$this->createGeneratedFolderIfNeeded($fileName);
|
||||
$resourcePath = $this->getGeneratedResourcePath($fileName);
|
||||
|
||||
/** @var \Box\Spout\Writer\ODS\Writer $writer */
|
||||
$writer = WriterFactory::create(Type::ODS);
|
||||
$writer->openToFile($resourcePath);
|
||||
|
||||
$writer->addRow(['ods--sheet1--11', 'ods--sheet1--12']);
|
||||
$writer->addNewSheetAndMakeItCurrent();
|
||||
$writer->addRow(['ods--sheet2--11', 'ods--sheet2--12', 'ods--sheet2--13']);
|
||||
|
||||
$writer->close();
|
||||
|
||||
return $writer->getSheets();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $expectedName
|
||||
* @param string $fileName
|
||||
* @param string $message
|
||||
* @return void
|
||||
*/
|
||||
private function assertSheetNameEquals($expectedName, $fileName, $message = '')
|
||||
{
|
||||
$resourcePath = $this->getGeneratedResourcePath($fileName);
|
||||
$pathToWorkbookFile = $resourcePath . '#content.xml';
|
||||
$xmlContents = file_get_contents('zip://' . $pathToWorkbookFile);
|
||||
|
||||
$this->assertContains("table:name=\"$expectedName\"", $xmlContents, $message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,446 @@
|
||||
<?php
|
||||
|
||||
namespace Box\Spout\Writer\ODS;
|
||||
|
||||
use Box\Spout\Common\Type;
|
||||
use Box\Spout\Reader\Wrapper\XMLReader;
|
||||
use Box\Spout\TestUsingResource;
|
||||
use Box\Spout\Writer\Style\StyleBuilder;
|
||||
use Box\Spout\Writer\WriterFactory;
|
||||
|
||||
/**
|
||||
* Class WriterTest
|
||||
*
|
||||
* @package Box\Spout\Writer\ODS
|
||||
*/
|
||||
class WriterTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
use TestUsingResource;
|
||||
|
||||
/**
|
||||
* @expectedException \Box\Spout\Common\Exception\IOException
|
||||
*/
|
||||
public function testAddRowShouldThrowExceptionIfCannotOpenAFileForWriting()
|
||||
{
|
||||
$fileName = 'file_that_wont_be_written.ods';
|
||||
$this->createUnwritableFolderIfNeeded($fileName);
|
||||
$filePath = $this->getGeneratedUnwritableResourcePath($fileName);
|
||||
|
||||
$writer = WriterFactory::create(Type::ODS);
|
||||
@$writer->openToFile($filePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Box\Spout\Writer\Exception\WriterNotOpenedException
|
||||
*/
|
||||
public function testAddRowShouldThrowExceptionIfCallAddRowBeforeOpeningWriter()
|
||||
{
|
||||
$writer = WriterFactory::create(Type::ODS);
|
||||
$writer->addRow(['ods--11', 'ods--12']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Box\Spout\Writer\Exception\WriterNotOpenedException
|
||||
*/
|
||||
public function testAddRowShouldThrowExceptionIfCalledBeforeOpeningWriter()
|
||||
{
|
||||
$writer = WriterFactory::create(Type::ODS);
|
||||
$writer->addRows([['ods--11', 'ods--12']]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Box\Spout\Writer\Exception\WriterAlreadyOpenedException
|
||||
*/
|
||||
public function testSetTempFolderShouldThrowExceptionIfCalledAfterOpeningWriter()
|
||||
{
|
||||
$fileName = 'file_that_wont_be_written.ods';
|
||||
$filePath = $this->getGeneratedResourcePath($fileName);
|
||||
|
||||
/** @var \Box\Spout\Writer\ODS\Writer $writer */
|
||||
$writer = WriterFactory::create(Type::ODS);
|
||||
$writer->openToFile($filePath);
|
||||
|
||||
$writer->setTempFolder('');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Box\Spout\Writer\Exception\WriterAlreadyOpenedException
|
||||
*/
|
||||
public function testsetShouldCreateNewSheetsAutomaticallyShouldThrowExceptionIfCalledAfterOpeningWriter()
|
||||
{
|
||||
$fileName = 'file_that_wont_be_written.ods';
|
||||
$filePath = $this->getGeneratedResourcePath($fileName);
|
||||
|
||||
/** @var \Box\Spout\Writer\ODS\Writer $writer */
|
||||
$writer = WriterFactory::create(Type::ODS);
|
||||
$writer->openToFile($filePath);
|
||||
|
||||
$writer->setShouldCreateNewSheetsAutomatically(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Box\Spout\Common\Exception\InvalidArgumentException
|
||||
*/
|
||||
public function testAddRowShouldThrowExceptionIfUnsupportedDataTypePassedIn()
|
||||
{
|
||||
$fileName = 'test_add_row_should_throw_exception_if_unsupported_data_type_passed_in.ods';
|
||||
$dataRows = [
|
||||
[new \stdClass()],
|
||||
];
|
||||
|
||||
$this->writeToODSFile($dataRows, $fileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testAddNewSheetAndMakeItCurrent()
|
||||
{
|
||||
$fileName = 'test_add_new_sheet_and_make_it_current.ods';
|
||||
$this->createGeneratedFolderIfNeeded($fileName);
|
||||
$resourcePath = $this->getGeneratedResourcePath($fileName);
|
||||
|
||||
/** @var Writer $writer */
|
||||
$writer = WriterFactory::create(Type::ODS);
|
||||
$writer->openToFile($resourcePath);
|
||||
$writer->addNewSheetAndMakeItCurrent();
|
||||
$writer->close();
|
||||
|
||||
$sheets = $writer->getSheets();
|
||||
$this->assertEquals(2, count($sheets), 'There should be 2 sheets');
|
||||
$this->assertEquals($sheets[1], $writer->getCurrentSheet(), 'The current sheet should be the second one.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testSetCurrentSheet()
|
||||
{
|
||||
$fileName = 'test_set_current_sheet.ods';
|
||||
$this->createGeneratedFolderIfNeeded($fileName);
|
||||
$resourcePath = $this->getGeneratedResourcePath($fileName);
|
||||
|
||||
$writer = WriterFactory::create(Type::ODS);
|
||||
$writer->openToFile($resourcePath);
|
||||
|
||||
$writer->addNewSheetAndMakeItCurrent();
|
||||
$writer->addNewSheetAndMakeItCurrent();
|
||||
|
||||
$firstSheet = $writer->getSheets()[0];
|
||||
$writer->setCurrentSheet($firstSheet);
|
||||
|
||||
$writer->close();
|
||||
|
||||
$this->assertEquals($firstSheet, $writer->getCurrentSheet(), 'The current sheet should be the first one.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testAddRowShouldWriteGivenDataToSheet()
|
||||
{
|
||||
$fileName = 'test_add_row_should_write_given_data_to_sheet.ods';
|
||||
$dataRows = [
|
||||
['ods--11', 'ods--12'],
|
||||
['ods--21', 'ods--22', 'ods--23'],
|
||||
];
|
||||
|
||||
$this->writeToODSFile($dataRows, $fileName);
|
||||
|
||||
foreach ($dataRows as $dataRow) {
|
||||
foreach ($dataRow as $cellValue) {
|
||||
$this->assertValueWasWritten($fileName, $cellValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testAddRowShouldWriteGivenDataToTwoSheets()
|
||||
{
|
||||
$fileName = 'test_add_row_should_write_given_data_to_two_sheets.ods';
|
||||
$dataRows = [
|
||||
['ods--11', 'ods--12'],
|
||||
['ods--21', 'ods--22', 'ods--23'],
|
||||
];
|
||||
|
||||
$numSheets = 2;
|
||||
$this->writeToMultipleSheetsInODSFile($dataRows, $numSheets, $fileName);
|
||||
|
||||
for ($i = 1; $i <= $numSheets; $i++) {
|
||||
foreach ($dataRows as $dataRow) {
|
||||
foreach ($dataRow as $cellValue) {
|
||||
$this->assertValueWasWritten($fileName, $cellValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testAddRowShouldSupportMultipleTypesOfData()
|
||||
{
|
||||
$fileName = 'test_add_row_should_support_multiple_types_of_data.ods';
|
||||
$dataRows = [
|
||||
['ods--11', true, '', 0, 10.2, null],
|
||||
];
|
||||
|
||||
$this->writeToODSFile($dataRows, $fileName);
|
||||
|
||||
$this->assertValueWasWritten($fileName, 'ods--11');
|
||||
$this->assertValueWasWrittenToSheet($fileName, 1, 1); // true is converted to 1
|
||||
$this->assertValueWasWrittenToSheet($fileName, 1, 0);
|
||||
$this->assertValueWasWrittenToSheet($fileName, 1, 10.2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testAddRowShouldWriteGivenDataToTheCorrectSheet()
|
||||
{
|
||||
$fileName = 'test_add_row_should_write_given_data_to_the_correct_sheet.ods';
|
||||
$dataRowsSheet1 = [
|
||||
['ods--sheet1--11', 'ods--sheet1--12'],
|
||||
['ods--sheet1--21', 'ods--sheet1--22', 'ods--sheet1--23'],
|
||||
];
|
||||
$dataRowsSheet2 = [
|
||||
['ods--sheet2--11', 'ods--sheet2--12'],
|
||||
['ods--sheet2--21', 'ods--sheet2--22', 'ods--sheet2--23'],
|
||||
];
|
||||
$dataRowsSheet1Again = [
|
||||
['ods--sheet1--31', 'ods--sheet1--32'],
|
||||
['ods--sheet1--41', 'ods--sheet1--42', 'ods--sheet1--43'],
|
||||
];
|
||||
|
||||
$this->createGeneratedFolderIfNeeded($fileName);
|
||||
$resourcePath = $this->getGeneratedResourcePath($fileName);
|
||||
|
||||
/** @var \Box\Spout\Writer\ODS\Writer $writer */
|
||||
$writer = WriterFactory::create(Type::ODS);
|
||||
$writer->openToFile($resourcePath);
|
||||
|
||||
$writer->addRows($dataRowsSheet1);
|
||||
|
||||
$writer->addNewSheetAndMakeItCurrent();
|
||||
$writer->addRows($dataRowsSheet2);
|
||||
|
||||
$firstSheet = $writer->getSheets()[0];
|
||||
$writer->setCurrentSheet($firstSheet);
|
||||
|
||||
$writer->addRows($dataRowsSheet1Again);
|
||||
|
||||
$writer->close();
|
||||
|
||||
foreach ($dataRowsSheet1 as $dataRow) {
|
||||
foreach ($dataRow as $cellValue) {
|
||||
$this->assertValueWasWrittenToSheet($fileName, 1, $cellValue, 'Data should have been written in Sheet 1');
|
||||
}
|
||||
}
|
||||
foreach ($dataRowsSheet2 as $dataRow) {
|
||||
foreach ($dataRow as $cellValue) {
|
||||
$this->assertValueWasWrittenToSheet($fileName, 2, $cellValue, 'Data should have been written in Sheet 2');
|
||||
}
|
||||
}
|
||||
foreach ($dataRowsSheet1Again as $dataRow) {
|
||||
foreach ($dataRow as $cellValue) {
|
||||
$this->assertValueWasWrittenToSheet($fileName, 1, $cellValue, 'Data should have been written in Sheet 1');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testAddRowShouldAutomaticallyCreateNewSheetsIfMaxRowsReachedAndOptionTurnedOn()
|
||||
{
|
||||
$fileName = 'test_add_row_should_automatically_create_new_sheets_if_max_rows_reached_and_option_turned_on.ods';
|
||||
$dataRows = [
|
||||
['ods--sheet1--11', 'ods--sheet1--12'],
|
||||
['ods--sheet1--21', 'ods--sheet1--22', 'ods--sheet1--23'],
|
||||
['ods--sheet2--11', 'ods--sheet2--12'], // this should be written in a new sheet
|
||||
];
|
||||
|
||||
// set the maxRowsPerSheet limit to 2
|
||||
\ReflectionHelper::setStaticValue('\Box\Spout\Writer\ODS\Internal\Workbook', 'maxRowsPerWorksheet', 2);
|
||||
|
||||
$writer = $this->writeToODSFile($dataRows, $fileName, $shouldCreateSheetsAutomatically = true);
|
||||
$this->assertEquals(2, count($writer->getSheets()), '2 sheets should have been created.');
|
||||
|
||||
$this->assertValueWasNotWrittenToSheet($fileName, 1, 'ods--sheet2--11');
|
||||
$this->assertValueWasWrittenToSheet($fileName, 2, 'ods--sheet2--11');
|
||||
|
||||
\ReflectionHelper::reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testAddRowShouldNotCreateNewSheetsIfMaxRowsReachedAndOptionTurnedOff()
|
||||
{
|
||||
$fileName = 'test_add_row_should_not_create_new_sheets_if_max_rows_reached_and_option_turned_off.ods';
|
||||
$dataRows = [
|
||||
['ods--sheet1--11', 'ods--sheet1--12'],
|
||||
['ods--sheet1--21', 'ods--sheet1--22', 'ods--sheet1--23'],
|
||||
['ods--sheet1--31', 'ods--sheet1--32'], // this should NOT be written in a new sheet
|
||||
];
|
||||
|
||||
// set the maxRowsPerSheet limit to 2
|
||||
\ReflectionHelper::setStaticValue('\Box\Spout\Writer\ODS\Internal\Workbook', 'maxRowsPerWorksheet', 2);
|
||||
|
||||
$writer = $this->writeToODSFile($dataRows, $fileName, $shouldCreateSheetsAutomatically = false);
|
||||
$this->assertEquals(1, count($writer->getSheets()), 'Only 1 sheet should have been created.');
|
||||
|
||||
$this->assertValueWasNotWrittenToSheet($fileName, 1, 'ods--sheet1--31');
|
||||
|
||||
\ReflectionHelper::reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testAddRowShouldEscapeHtmlSpecialCharacters()
|
||||
{
|
||||
$fileName = 'test_add_row_should_escape_html_special_characters.ods';
|
||||
$dataRows = [
|
||||
['I\'m in "great" mood', 'This <must> be escaped & tested'],
|
||||
];
|
||||
|
||||
$this->writeToODSFile($dataRows, $fileName);
|
||||
|
||||
$this->assertValueWasWritten($fileName, 'I'm in "great" mood', 'Quotes should be escaped');
|
||||
$this->assertValueWasWritten($fileName, 'This <must> be escaped & tested', '<, > and & should be escaped');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testAddRowShouldKeepNewLines()
|
||||
{
|
||||
$fileName = 'test_add_row_should_keep_new_lines.ods';
|
||||
$dataRow = ["I have\na dream"];
|
||||
|
||||
$this->writeToODSFile([$dataRow], $fileName);
|
||||
|
||||
$this->assertValueWasWrittenToSheet($fileName, 1, 'I have');
|
||||
$this->assertValueWasWrittenToSheet($fileName, 1, 'a dream');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $allRows
|
||||
* @param string $fileName
|
||||
* @param bool $shouldCreateSheetsAutomatically
|
||||
* @return Writer
|
||||
*/
|
||||
private function writeToODSFile($allRows, $fileName, $shouldCreateSheetsAutomatically = true)
|
||||
{
|
||||
$this->createGeneratedFolderIfNeeded($fileName);
|
||||
$resourcePath = $this->getGeneratedResourcePath($fileName);
|
||||
|
||||
/** @var \Box\Spout\Writer\ODS\Writer $writer */
|
||||
$writer = WriterFactory::create(Type::ODS);
|
||||
$writer->setShouldCreateNewSheetsAutomatically($shouldCreateSheetsAutomatically);
|
||||
|
||||
$writer->openToFile($resourcePath);
|
||||
$writer->addRows($allRows);
|
||||
$writer->close();
|
||||
|
||||
return $writer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $allRows
|
||||
* @param int $numSheets
|
||||
* @param string $fileName
|
||||
* @param bool $shouldCreateSheetsAutomatically
|
||||
* @return Writer
|
||||
*/
|
||||
private function writeToMultipleSheetsInODSFile($allRows, $numSheets, $fileName, $shouldCreateSheetsAutomatically = true)
|
||||
{
|
||||
$this->createGeneratedFolderIfNeeded($fileName);
|
||||
$resourcePath = $this->getGeneratedResourcePath($fileName);
|
||||
|
||||
/** @var \Box\Spout\Writer\ODS\Writer $writer */
|
||||
$writer = WriterFactory::create(Type::ODS);
|
||||
$writer->setShouldCreateNewSheetsAutomatically($shouldCreateSheetsAutomatically);
|
||||
|
||||
$writer->openToFile($resourcePath);
|
||||
$writer->addRows($allRows);
|
||||
|
||||
for ($i = 1; $i < $numSheets; $i++) {
|
||||
$writer->addNewSheetAndMakeItCurrent();
|
||||
$writer->addRows($allRows);
|
||||
}
|
||||
|
||||
$writer->close();
|
||||
|
||||
return $writer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $fileName
|
||||
* @param string $value
|
||||
* @param string $message
|
||||
* @return void
|
||||
*/
|
||||
private function assertValueWasWritten($fileName, $value, $message = '')
|
||||
{
|
||||
$resourcePath = $this->getGeneratedResourcePath($fileName);
|
||||
$pathToContentFile = $resourcePath . '#content.xml';
|
||||
$xmlContents = file_get_contents('zip://' . $pathToContentFile);
|
||||
|
||||
$this->assertContains($value, $xmlContents, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $fileName
|
||||
* @param int $sheetIndex
|
||||
* @param mixed $value
|
||||
* @param string $message
|
||||
* @return void
|
||||
*/
|
||||
private function assertValueWasWrittenToSheet($fileName, $sheetIndex, $value, $message = '')
|
||||
{
|
||||
$sheetXmlAsString = $this->getSheetXmlNodeAsString($fileName, $sheetIndex);
|
||||
$valueAsXmlString = "<text:p>$value</text:p>";
|
||||
|
||||
$this->assertContains($valueAsXmlString, $sheetXmlAsString, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $fileName
|
||||
* @param int $sheetIndex
|
||||
* @param mixed $value
|
||||
* @param string $message
|
||||
* @return void
|
||||
*/
|
||||
private function assertValueWasNotWrittenToSheet($fileName, $sheetIndex, $value, $message = '')
|
||||
{
|
||||
$sheetXmlAsString = $this->getSheetXmlNodeAsString($fileName, $sheetIndex);
|
||||
$valueAsXmlString = "<text:p>$value</text:p>";
|
||||
|
||||
$this->assertNotContains($valueAsXmlString, $sheetXmlAsString, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $fileName
|
||||
* @param int $sheetIndex
|
||||
* @return string
|
||||
*/
|
||||
private function getSheetXmlNodeAsString($fileName, $sheetIndex)
|
||||
{
|
||||
$resourcePath = $this->getGeneratedResourcePath($fileName);
|
||||
$pathToSheetFile = $resourcePath . '#content.xml';
|
||||
|
||||
$xmlReader = new XMLReader();
|
||||
$xmlReader->open('zip://' . $pathToSheetFile);
|
||||
$xmlReader->readUntilNodeFound('table:table');
|
||||
|
||||
for ($i = 1; $i < $sheetIndex; $i++) {
|
||||
$xmlReader->readUntilNodeFound('table:table');
|
||||
}
|
||||
|
||||
return $xmlReader->readOuterXml();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,364 @@
|
||||
<?php
|
||||
|
||||
namespace Box\Spout\Writer\ODS;
|
||||
|
||||
use Box\Spout\Common\Type;
|
||||
use Box\Spout\Reader\Wrapper\XMLReader;
|
||||
use Box\Spout\TestUsingResource;
|
||||
use Box\Spout\Writer\Style\Color;
|
||||
use Box\Spout\Writer\Style\Style;
|
||||
use Box\Spout\Writer\Style\StyleBuilder;
|
||||
use Box\Spout\Writer\WriterFactory;
|
||||
|
||||
/**
|
||||
* Class WriterWithStyleTest
|
||||
*
|
||||
* @package Box\Spout\Writer\ODS
|
||||
*/
|
||||
class WriterWithStyleTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
use TestUsingResource;
|
||||
|
||||
/** @var \Box\Spout\Writer\Style\Style */
|
||||
protected $defaultStyle;
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function setUp()
|
||||
{
|
||||
$this->defaultStyle = (new StyleBuilder())->build();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Box\Spout\Writer\Exception\WriterNotOpenedException
|
||||
*/
|
||||
public function testAddRowWithStyleShouldThrowExceptionIfCallAddRowBeforeOpeningWriter()
|
||||
{
|
||||
$writer = WriterFactory::create(Type::ODS);
|
||||
$writer->addRowWithStyle(['ods--11', 'ods--12'], $this->defaultStyle);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Box\Spout\Writer\Exception\WriterNotOpenedException
|
||||
*/
|
||||
public function testAddRowWithStyleShouldThrowExceptionIfCalledBeforeOpeningWriter()
|
||||
{
|
||||
$writer = WriterFactory::create(Type::ODS);
|
||||
$writer->addRowWithStyle(['ods--11', 'ods--12'], $this->defaultStyle);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function dataProviderForInvalidStyle()
|
||||
{
|
||||
return [
|
||||
['style'],
|
||||
[new \stdClass()],
|
||||
[null],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataProviderForInvalidStyle
|
||||
* @expectedException \Box\Spout\Common\Exception\InvalidArgumentException
|
||||
*
|
||||
* @param \Box\Spout\Writer\Style\Style $style
|
||||
*/
|
||||
public function testAddRowWithStyleShouldThrowExceptionIfInvalidStyleGiven($style)
|
||||
{
|
||||
$fileName = 'test_add_row_with_style_should_throw_exception.ods';
|
||||
$this->createGeneratedFolderIfNeeded($fileName);
|
||||
$resourcePath = $this->getGeneratedResourcePath($fileName);
|
||||
|
||||
$writer = WriterFactory::create(Type::ODS);
|
||||
$writer->openToFile($resourcePath);
|
||||
$writer->addRowWithStyle(['ods--11', 'ods--12'], $style);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataProviderForInvalidStyle
|
||||
* @expectedException \Box\Spout\Common\Exception\InvalidArgumentException
|
||||
*
|
||||
* @param \Box\Spout\Writer\Style\Style $style
|
||||
*/
|
||||
public function testAddRowsWithStyleShouldThrowExceptionIfInvalidStyleGiven($style)
|
||||
{
|
||||
$fileName = 'test_add_row_with_style_should_throw_exception.ods';
|
||||
$this->createGeneratedFolderIfNeeded($fileName);
|
||||
$resourcePath = $this->getGeneratedResourcePath($fileName);
|
||||
|
||||
$writer = WriterFactory::create(Type::ODS);
|
||||
$writer->openToFile($resourcePath);
|
||||
$writer->addRowsWithStyle([['ods--11', 'ods--12']], $style);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testAddRowWithStyleShouldListAllUsedStylesInCreatedContentXmlFile()
|
||||
{
|
||||
$fileName = 'test_add_row_with_style_should_list_all_used_fonts.ods';
|
||||
$dataRows = [
|
||||
['ods--11', 'ods--12'],
|
||||
['ods--21', 'ods--22'],
|
||||
];
|
||||
|
||||
$style = (new StyleBuilder())
|
||||
->setFontBold()
|
||||
->setFontItalic()
|
||||
->setFontUnderline()
|
||||
->setFontStrikethrough()
|
||||
->build();
|
||||
$style2 = (new StyleBuilder())
|
||||
->setFontSize(15)
|
||||
->setFontColor(Color::RED)
|
||||
->setFontName('Font')
|
||||
->build();
|
||||
|
||||
$this->writeToODSFileWithMultipleStyles($dataRows, $fileName, [$style, $style2]);
|
||||
|
||||
$cellStyleElements = $this->getCellStyleElementsFromContentXmlFile($fileName);
|
||||
$this->assertEquals(3, count($cellStyleElements), 'There should be 3 separate cell styles, including the default one.');
|
||||
|
||||
// Second font should contain data from the first created style
|
||||
$customFont1Element = $cellStyleElements[1];
|
||||
$this->assertFirstChildHasAttributeEquals('bold', $customFont1Element, 'text-properties', 'fo:font-weight');
|
||||
$this->assertFirstChildHasAttributeEquals('italic', $customFont1Element, 'text-properties', 'fo:font-style');
|
||||
$this->assertFirstChildHasAttributeEquals('solid', $customFont1Element, 'text-properties', 'style:text-underline-style');
|
||||
$this->assertFirstChildHasAttributeEquals('solid', $customFont1Element, 'text-properties', 'style:text-line-through-style');
|
||||
|
||||
// Third font should contain data from the second created style
|
||||
$customFont2Element = $cellStyleElements[2];
|
||||
$this->assertFirstChildHasAttributeEquals('15pt', $customFont2Element, 'text-properties', 'fo:font-size');
|
||||
$this->assertFirstChildHasAttributeEquals('#' . Color::RED, $customFont2Element, 'text-properties', 'fo:color');
|
||||
$this->assertFirstChildHasAttributeEquals('Font', $customFont2Element, 'text-properties', 'style:font-name');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testAddRowWithStyleShouldWriteDefaultStyleSettings()
|
||||
{
|
||||
$fileName = 'test_add_row_with_style_should_write_default_style_settings.ods';
|
||||
$dataRow = ['ods--11', 'ods--12'];
|
||||
|
||||
$this->writeToODSFile([$dataRow], $fileName, $this->defaultStyle);
|
||||
|
||||
$textPropertiesElement = $this->getXmlSectionFromStylesXmlFile($fileName, 'style:text-properties');
|
||||
$this->assertEquals(Style::DEFAULT_FONT_SIZE . 'pt', $textPropertiesElement->getAttribute('fo:font-size'));
|
||||
$this->assertEquals('#' . Style::DEFAULT_FONT_COLOR, $textPropertiesElement->getAttribute('fo:color'));
|
||||
$this->assertEquals(Style::DEFAULT_FONT_NAME, $textPropertiesElement->getAttribute('style:font-name'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testAddRowWithStyleShouldApplyStyleToCells()
|
||||
{
|
||||
$fileName = 'test_add_row_with_style_should_apply_style_to_cells.ods';
|
||||
$dataRows = [
|
||||
['ods--11'],
|
||||
['ods--21'],
|
||||
['ods--31'],
|
||||
];
|
||||
$style = (new StyleBuilder())->setFontBold()->build();
|
||||
$style2 = (new StyleBuilder())->setFontSize(15)->build();
|
||||
|
||||
$this->writeToODSFileWithMultipleStyles($dataRows, $fileName, [$style, $style2, null]);
|
||||
|
||||
$cellDomElements = $this->getCellElementsFromContentXmlFile($fileName);
|
||||
$this->assertEquals(3, count($cellDomElements), 'There should be 3 cells with content');
|
||||
|
||||
$this->assertEquals('ce2', $cellDomElements[0]->getAttribute('table:style-name'));
|
||||
$this->assertEquals('ce3', $cellDomElements[1]->getAttribute('table:style-name'));
|
||||
$this->assertEquals('ce1', $cellDomElements[2]->getAttribute('table:style-name'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testAddRowWithStyleShouldReuseDuplicateStyles()
|
||||
{
|
||||
$fileName = 'test_add_row_with_style_should_reuse_duplicate_styles.ods';
|
||||
$dataRows = [
|
||||
['ods--11'],
|
||||
['ods--21'],
|
||||
];
|
||||
$style = (new StyleBuilder())->setFontBold()->build();
|
||||
|
||||
$this->writeToODSFile($dataRows, $fileName, $style);
|
||||
|
||||
$cellDomElements = $this->getCellElementsFromContentXmlFile($fileName);
|
||||
$this->assertEquals(2, count($cellDomElements), 'There should be 2 cells with content');
|
||||
|
||||
$this->assertEquals('ce2', $cellDomElements[0]->getAttribute('table:style-name'));
|
||||
$this->assertEquals('ce2', $cellDomElements[1]->getAttribute('table:style-name'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testAddRowWithStyleShouldAddWrapTextAlignmentInfoInStylesXmlFileIfSpecified()
|
||||
{
|
||||
$fileName = 'test_add_row_with_style_should_add_wrap_text_alignment.ods';
|
||||
$dataRows = [
|
||||
['ods--11', 'ods--12'],
|
||||
];
|
||||
$style = (new StyleBuilder())->setShouldWrapText()->build();
|
||||
|
||||
$this->writeToODSFile($dataRows, $fileName,$style);
|
||||
|
||||
$styleElements = $this->getCellStyleElementsFromContentXmlFile($fileName);
|
||||
$this->assertEquals(2, count($styleElements), 'There should be 2 styles (default and custom)');
|
||||
|
||||
$customStyleElement = $styleElements[1];
|
||||
$this->assertFirstChildHasAttributeEquals('wrap', $customStyleElement, 'table-cell-properties', 'fo:wrap-option');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testAddRowWithStyleShouldApplyWrapTextIfCellContainsNewLine()
|
||||
{
|
||||
$fileName = 'test_add_row_with_style_should_apply_wrap_text_if_new_lines.ods';
|
||||
$dataRows = [
|
||||
["ods--11\nods--11"],
|
||||
];
|
||||
|
||||
$this->writeToODSFile($dataRows, $fileName, $this->defaultStyle);
|
||||
|
||||
$styleElements = $this->getCellStyleElementsFromContentXmlFile($fileName);
|
||||
$this->assertEquals(2, count($styleElements), 'There should be 2 styles (default and custom)');
|
||||
|
||||
$customStyleElement = $styleElements[1];
|
||||
$this->assertFirstChildHasAttributeEquals('wrap', $customStyleElement, 'table-cell-properties', 'fo:wrap-option');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $allRows
|
||||
* @param string $fileName
|
||||
* @param \Box\Spout\Writer\Style\Style $style
|
||||
* @return Writer
|
||||
*/
|
||||
private function writeToODSFile($allRows, $fileName, $style)
|
||||
{
|
||||
$this->createGeneratedFolderIfNeeded($fileName);
|
||||
$resourcePath = $this->getGeneratedResourcePath($fileName);
|
||||
|
||||
/** @var \Box\Spout\Writer\ODS\Writer $writer */
|
||||
$writer = WriterFactory::create(Type::ODS);
|
||||
|
||||
$writer->openToFile($resourcePath);
|
||||
$writer->addRowsWithStyle($allRows, $style);
|
||||
$writer->close();
|
||||
|
||||
return $writer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $allRows
|
||||
* @param string $fileName
|
||||
* @param \Box\Spout\Writer\Style\Style|null[] $styles
|
||||
* @return Writer
|
||||
*/
|
||||
private function writeToODSFileWithMultipleStyles($allRows, $fileName, $styles)
|
||||
{
|
||||
// there should be as many rows as there are styles passed in
|
||||
$this->assertEquals(count($allRows), count($styles));
|
||||
|
||||
$this->createGeneratedFolderIfNeeded($fileName);
|
||||
$resourcePath = $this->getGeneratedResourcePath($fileName);
|
||||
|
||||
/** @var \Box\Spout\Writer\ODS\Writer $writer */
|
||||
$writer = WriterFactory::create(Type::ODS);
|
||||
|
||||
$writer->openToFile($resourcePath);
|
||||
for ($i = 0; $i < count($allRows); $i++) {
|
||||
if ($styles[$i] === null) {
|
||||
$writer->addRow($allRows[$i]);
|
||||
} else {
|
||||
$writer->addRowWithStyle($allRows[$i], $styles[$i]);
|
||||
}
|
||||
}
|
||||
$writer->close();
|
||||
|
||||
return $writer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $fileName
|
||||
* @return \DOMNode[]
|
||||
*/
|
||||
private function getCellElementsFromContentXmlFile($fileName)
|
||||
{
|
||||
$cellElements = [];
|
||||
|
||||
$resourcePath = $this->getGeneratedResourcePath($fileName);
|
||||
$pathToStylesXmlFile = $resourcePath . '#content.xml';
|
||||
|
||||
$xmlReader = new \XMLReader();
|
||||
$xmlReader->open('zip://' . $pathToStylesXmlFile);
|
||||
|
||||
while ($xmlReader->read()) {
|
||||
if ($xmlReader->nodeType === \XMLReader::ELEMENT && $xmlReader->name === 'table:table-cell' && $xmlReader->getAttribute('office:value-type') !== null) {
|
||||
$cellElements[] = $xmlReader->expand();
|
||||
}
|
||||
}
|
||||
|
||||
return $cellElements;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $fileName
|
||||
* @return \DOMNode[]
|
||||
*/
|
||||
private function getCellStyleElementsFromContentXmlFile($fileName)
|
||||
{
|
||||
$cellStyleElements = [];
|
||||
|
||||
$resourcePath = $this->getGeneratedResourcePath($fileName);
|
||||
$pathToStylesXmlFile = $resourcePath . '#content.xml';
|
||||
|
||||
$xmlReader = new \XMLReader();
|
||||
$xmlReader->open('zip://' . $pathToStylesXmlFile);
|
||||
|
||||
while ($xmlReader->read()) {
|
||||
if ($xmlReader->nodeType === \XMLReader::ELEMENT && $xmlReader->name === 'style:style' && $xmlReader->getAttribute('style:family') === 'table-cell') {
|
||||
$cellStyleElements[] = $xmlReader->expand();
|
||||
}
|
||||
}
|
||||
|
||||
return $cellStyleElements;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $fileName
|
||||
* @param string $section
|
||||
* @return \DomElement
|
||||
*/
|
||||
private function getXmlSectionFromStylesXmlFile($fileName, $section)
|
||||
{
|
||||
$resourcePath = $this->getGeneratedResourcePath($fileName);
|
||||
$pathToStylesXmlFile = $resourcePath . '#styles.xml';
|
||||
|
||||
$xmlReader = new XMLReader();
|
||||
$xmlReader->open('zip://' . $pathToStylesXmlFile);
|
||||
$xmlReader->readUntilNodeFound($section);
|
||||
|
||||
return $xmlReader->expand();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $expectedValue
|
||||
* @param \DOMNode $parentElement
|
||||
* @param string $childTagName
|
||||
* @param string $attributeName
|
||||
* @return void
|
||||
*/
|
||||
private function assertFirstChildHasAttributeEquals($expectedValue, $parentElement, $childTagName, $attributeName)
|
||||
{
|
||||
$this->assertEquals($expectedValue, $parentElement->getElementsByTagName($childTagName)->item(0)->getAttribute($attributeName));
|
||||
}
|
||||
}
|
||||
@@ -28,13 +28,13 @@ class ColorTest extends \PHPUnit_Framework_TestCase
|
||||
[0, 112, 192, Color::BLUE],
|
||||
[0, 32, 96, Color::DARK_BLUE],
|
||||
[112, 48, 160, Color::PURPLE],
|
||||
[0, 0, 0, 'FF000000'],
|
||||
[255, 255, 255, 'FFFFFFFF'],
|
||||
[255, 0, 0, 'FFFF0000'],
|
||||
[0, 128, 0, 'FF008000'],
|
||||
[0, 255, 0, 'FF00FF00'],
|
||||
[0, 0, 255, 'FF0000FF'],
|
||||
[128, 22, 43, 'FF80162B'],
|
||||
[0, 0, 0, '000000'],
|
||||
[255, 255, 255, 'FFFFFF'],
|
||||
[255, 0, 0, 'FF0000'],
|
||||
[0, 128, 0, '008000'],
|
||||
[0, 255, 0, '00FF00'],
|
||||
[0, 0, 255, '0000FF'],
|
||||
[128, 22, 43, '80162B'],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace Box\Spout\Writer\XLSX;
|
||||
|
||||
use Box\Spout\Common\Type;
|
||||
use Box\Spout\TestUsingResource;
|
||||
use Box\Spout\Writer\Common\Sheet;
|
||||
use Box\Spout\Writer\WriterFactory;
|
||||
|
||||
/**
|
||||
@@ -51,64 +52,6 @@ class SheetTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertSheetNameEquals($customSheetName, $fileName, "The sheet name should have been changed to '$customSheetName'");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function dataProviderForInvalidSheetNames()
|
||||
{
|
||||
return [
|
||||
[null],
|
||||
[21],
|
||||
[''],
|
||||
['this title exceeds the 31 characters limit'],
|
||||
['Illegal \\'],
|
||||
['Illegal /'],
|
||||
['Illegal ?'],
|
||||
['Illegal *'],
|
||||
['Illegal :'],
|
||||
['Illegal ['],
|
||||
['Illegal ]'],
|
||||
['\'Illegal start'],
|
||||
['Illegal end\''],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataProviderForInvalidSheetNames
|
||||
* @expectedException \Box\Spout\Writer\Exception\InvalidSheetNameException
|
||||
*
|
||||
* @param string $customSheetName
|
||||
* @return void
|
||||
*/
|
||||
public function testSetSheetNameShouldThrowOnInvalidName($customSheetName)
|
||||
{
|
||||
$fileName = 'test_set_name_with_invalid_name_should_throw_exception.xlsx';
|
||||
$this->writeDataAndReturnSheetWithCustomName($fileName, $customSheetName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testSetSheetNameShouldNotThrowWhenSettingSameNameAsCurrentOne()
|
||||
{
|
||||
$fileName = 'test_set_name_with_same_as_current.xlsx';
|
||||
$this->createGeneratedFolderIfNeeded($fileName);
|
||||
$resourcePath = $this->getGeneratedResourcePath($fileName);
|
||||
|
||||
$writer = WriterFactory::create(Type::XLSX);
|
||||
$writer->openToFile($resourcePath);
|
||||
|
||||
$customSheetName = 'Sheet name';
|
||||
$sheet = $writer->getCurrentSheet();
|
||||
$sheet->setName($customSheetName);
|
||||
$sheet->setName($customSheetName);
|
||||
|
||||
$writer->addRow(['xlsx--11', 'xlsx--12']);
|
||||
$writer->close();
|
||||
|
||||
$this->assertSheetNameEquals($customSheetName, $fileName, "The sheet name should have been changed to '$customSheetName'");
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Box\Spout\Writer\Exception\InvalidSheetNameException
|
||||
* @return void
|
||||
@@ -186,6 +129,6 @@ class SheetTest extends \PHPUnit_Framework_TestCase
|
||||
$pathToWorkbookFile = $resourcePath . '#xl/workbook.xml';
|
||||
$xmlContents = file_get_contents('zip://' . $pathToWorkbookFile);
|
||||
|
||||
$this->assertContains('<sheet name="' . $expectedName . '"', $xmlContents, $message);
|
||||
$this->assertContains("<sheet name=\"$expectedName\"", $xmlContents, $message);
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ use Box\Spout\TestUsingResource;
|
||||
use Box\Spout\Writer\WriterFactory;
|
||||
|
||||
/**
|
||||
* Class XLSXTest
|
||||
* Class WriterTest
|
||||
*
|
||||
* @package Box\Spout\Writer\XLSX
|
||||
*/
|
||||
@@ -169,7 +169,7 @@ class WriterTest extends \PHPUnit_Framework_TestCase
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testAddRowShouldWriteGivenDataToTwoSheetUsingInlineStrings()
|
||||
public function testAddRowShouldWriteGivenDataToTwoSheetsUsingInlineStrings()
|
||||
{
|
||||
$fileName = 'test_add_row_should_write_given_data_to_two_sheets_using_inline_strings.xlsx';
|
||||
$dataRows = [
|
||||
@@ -212,7 +212,7 @@ class WriterTest extends \PHPUnit_Framework_TestCase
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testAddRowShouldWriteGivenDataToTwoSheetUsingSharedStrings()
|
||||
public function testAddRowShouldWriteGivenDataToTwoSheetsUsingSharedStrings()
|
||||
{
|
||||
$fileName = 'test_add_row_should_write_given_data_to_two_sheets_using_shared_strings.xlsx';
|
||||
$dataRows = [
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Box\Spout\Writer\XLSX;
|
||||
|
||||
use Box\Spout\Common\Type;
|
||||
use Box\Spout\Reader\Wrapper\XMLReader;
|
||||
use Box\Spout\TestUsingResource;
|
||||
use Box\Spout\Writer\Style\Color;
|
||||
use Box\Spout\Writer\Style\Style;
|
||||
@@ -96,7 +97,7 @@ class WriterWithStyleTest extends \PHPUnit_Framework_TestCase
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testAddRowWithStyleShouldListAllUsedFontsInCreateStylesXmlFile()
|
||||
public function testAddRowWithStyleShouldListAllUsedFontsInCreatedStylesXmlFile()
|
||||
{
|
||||
$fileName = 'test_add_row_with_style_should_list_all_used_fonts.xlsx';
|
||||
$dataRows = [
|
||||
@@ -113,7 +114,7 @@ class WriterWithStyleTest extends \PHPUnit_Framework_TestCase
|
||||
$style2 = (new StyleBuilder())
|
||||
->setFontSize(15)
|
||||
->setFontColor(Color::RED)
|
||||
->setFontName('Arial')
|
||||
->setFontName('Font')
|
||||
->build();
|
||||
|
||||
$this->writeToXLSXFileWithMultipleStyles($dataRows, $fileName, [$style, $style2]);
|
||||
@@ -128,7 +129,7 @@ class WriterWithStyleTest extends \PHPUnit_Framework_TestCase
|
||||
$defaultFontElement = $fontElements->item(0);
|
||||
$this->assertChildrenNumEquals(3, $defaultFontElement, 'The default font should only have 3 properties.');
|
||||
$this->assertFirstChildHasAttributeEquals((string) Writer::DEFAULT_FONT_SIZE, $defaultFontElement, 'sz', 'val');
|
||||
$this->assertFirstChildHasAttributeEquals(Style::DEFAULT_FONT_COLOR, $defaultFontElement, 'color', 'rgb');
|
||||
$this->assertFirstChildHasAttributeEquals(Color::toARGB(Style::DEFAULT_FONT_COLOR), $defaultFontElement, 'color', 'rgb');
|
||||
$this->assertFirstChildHasAttributeEquals(Writer::DEFAULT_FONT_NAME, $defaultFontElement, 'name', 'val');
|
||||
|
||||
// Second font should contain data from the first created style
|
||||
@@ -139,34 +140,15 @@ class WriterWithStyleTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertChildExists($secondFontElement, 'u');
|
||||
$this->assertChildExists($secondFontElement, 'strike');
|
||||
$this->assertFirstChildHasAttributeEquals((string) Writer::DEFAULT_FONT_SIZE, $secondFontElement, 'sz', 'val');
|
||||
$this->assertFirstChildHasAttributeEquals(Style::DEFAULT_FONT_COLOR, $secondFontElement, 'color', 'rgb');
|
||||
$this->assertFirstChildHasAttributeEquals(Color::toARGB(Style::DEFAULT_FONT_COLOR), $secondFontElement, 'color', 'rgb');
|
||||
$this->assertFirstChildHasAttributeEquals(Writer::DEFAULT_FONT_NAME, $secondFontElement, 'name', 'val');
|
||||
|
||||
// Third font should contain data from the second created style
|
||||
$thirdFontElement = $fontElements->item(2);
|
||||
$this->assertChildrenNumEquals(3, $thirdFontElement, 'The font should only have 3 properties.');
|
||||
$this->assertFirstChildHasAttributeEquals('15', $thirdFontElement, 'sz', 'val');
|
||||
$this->assertFirstChildHasAttributeEquals(Color::RED, $thirdFontElement, 'color', 'rgb');
|
||||
$this->assertFirstChildHasAttributeEquals('Arial', $thirdFontElement, 'name', 'val');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testAddRowWithStyleShouldAddWrapTextAlignmentInfoInStylesXmlFileIfSpecified()
|
||||
{
|
||||
$fileName = 'test_add_row_with_style_should_add_wrap_text_alignment.xlsx';
|
||||
$dataRows = [
|
||||
['xlsx--11', 'xlsx--12'],
|
||||
];
|
||||
$style = (new StyleBuilder())->setShouldWrapText()->build();
|
||||
|
||||
$this->writeToXLSXFile($dataRows, $fileName,$style);
|
||||
|
||||
$cellXfsDomElement = $this->getXmlSectionFromStylesXmlFile($fileName, 'cellXfs');
|
||||
$xfElement = $cellXfsDomElement->getElementsByTagName('xf')->item(1);
|
||||
$this->assertEquals(1, $xfElement->getAttribute('applyAlignment'));
|
||||
$this->assertFirstChildHasAttributeEquals('1', $xfElement, 'alignment', 'wrapText');
|
||||
$this->assertFirstChildHasAttributeEquals(Color::toARGB(Color::RED), $thirdFontElement, 'color', 'rgb');
|
||||
$this->assertFirstChildHasAttributeEquals('Font', $thirdFontElement, 'name', 'val');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -212,6 +194,25 @@ class WriterWithStyleTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals('1', $cellDomElements[1]->getAttribute('s'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testAddRowWithStyleShouldAddWrapTextAlignmentInfoInStylesXmlFileIfSpecified()
|
||||
{
|
||||
$fileName = 'test_add_row_with_style_should_add_wrap_text_alignment.xlsx';
|
||||
$dataRows = [
|
||||
['xlsx--11', 'xlsx--12'],
|
||||
];
|
||||
$style = (new StyleBuilder())->setShouldWrapText()->build();
|
||||
|
||||
$this->writeToXLSXFile($dataRows, $fileName,$style);
|
||||
|
||||
$cellXfsDomElement = $this->getXmlSectionFromStylesXmlFile($fileName, 'cellXfs');
|
||||
$xfElement = $cellXfsDomElement->getElementsByTagName('xf')->item(1);
|
||||
$this->assertEquals(1, $xfElement->getAttribute('applyAlignment'));
|
||||
$this->assertFirstChildHasAttributeEquals('1', $xfElement, 'alignment', 'wrapText');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
@@ -294,12 +295,9 @@ class WriterWithStyleTest extends \PHPUnit_Framework_TestCase
|
||||
$resourcePath = $this->getGeneratedResourcePath($fileName);
|
||||
$pathToStylesXmlFile = $resourcePath . '#xl/styles.xml';
|
||||
|
||||
$xmlReader = new \XMLReader();
|
||||
$xmlReader = new XMLReader();
|
||||
$xmlReader->open('zip://' . $pathToStylesXmlFile);
|
||||
|
||||
while ($xmlReader->read() && ($xmlReader->nodeType !== \XMLReader::ELEMENT || $xmlReader->name !== $section)) {
|
||||
// do nothing
|
||||
}
|
||||
$xmlReader->readUntilNodeFound($section);
|
||||
|
||||
return $xmlReader->expand();
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user