First external release
This commit is contained in:
commit
5e199009e6
81 files changed
+5447
No files matched your search
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
namespace Box\Spout\Reader;
|
||||
|
||||
use Box\Spout\Common\Type;
|
||||
use Box\Spout\TestUsingResource;
|
||||
|
||||
/**
|
||||
* Class CSVTest
|
||||
*
|
||||
* @package Box\Spout\Reader
|
||||
*/
|
||||
class CSVTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
use TestUsingResource;
|
||||
|
||||
/**
|
||||
* @expectedException \Box\Spout\Common\Exception\IOException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testReadShouldThrowExceptionIfFileDoesNotExist()
|
||||
{
|
||||
$this->getAllRowsForFile('/path/to/fake/file.csv');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testReadStandardCSV()
|
||||
{
|
||||
$allRows = $this->getAllRowsForFile('csv_standard.csv');
|
||||
|
||||
$expectedRows = [
|
||||
['csv--11', 'csv--12', 'csv--13'],
|
||||
['csv--21', 'csv--22', 'csv--23'],
|
||||
['csv--31', 'csv--32', 'csv--33'],
|
||||
];
|
||||
$this->assertEquals($expectedRows, $allRows);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testReadShouldNotStopAtCommaIfEnclosed()
|
||||
{
|
||||
$allRows = $this->getAllRowsForFile('csv_with_comma_enclosed.csv');
|
||||
$this->assertEquals('This is, a comma', $allRows[0][0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testReadShouldKeepEmptyCells()
|
||||
{
|
||||
$allRows = $this->getAllRowsForFile('csv_with_empty_cells.csv');
|
||||
|
||||
$expectedRows = [
|
||||
['csv--11', 'csv--12', 'csv--13'],
|
||||
['csv--21', '', 'csv--23'],
|
||||
['csv--31', 'csv--32', ''],
|
||||
];
|
||||
$this->assertEquals($expectedRows, $allRows);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testReadShouldSkipEmptyLines()
|
||||
{
|
||||
$allRows = $this->getAllRowsForFile('csv_with_empty_line.csv');
|
||||
|
||||
$expectedRows = [
|
||||
['csv--11', 'csv--12', 'csv--13'],
|
||||
['csv--31', 'csv--32', 'csv--33'],
|
||||
];
|
||||
$this->assertEquals($expectedRows, $allRows);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testReadShouldHaveTheRightNumberOfCells()
|
||||
{
|
||||
$allRows = $this->getAllRowsForFile('csv_with_different_cells_number.csv');
|
||||
|
||||
$expectedRows = [
|
||||
['csv--11', 'csv--12', 'csv--13'],
|
||||
['csv--21', 'csv--22'],
|
||||
['csv--31'],
|
||||
];
|
||||
$this->assertEquals($expectedRows, $allRows);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testReadShouldSupportCustomFieldDelimiter()
|
||||
{
|
||||
$allRows = $this->getAllRowsForFile('csv_delimited_with_pipes.csv', '|');
|
||||
|
||||
$expectedRows = [
|
||||
['csv--11', 'csv--12', 'csv--13'],
|
||||
['csv--21', 'csv--22', 'csv--23'],
|
||||
['csv--31', 'csv--32', 'csv--33'],
|
||||
];
|
||||
$this->assertEquals($expectedRows, $allRows);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testReadShouldSupportCustomFieldEnclosure()
|
||||
{
|
||||
$allRows = $this->getAllRowsForFile('csv_text_enclosed_with_pound.csv', ',', '#');
|
||||
$this->assertEquals('This is, a comma', $allRows[0][0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testReadShouldSkipUtf8Bom()
|
||||
{
|
||||
$allRows = $this->getAllRowsForFile('csv_with_utf8_bom.csv');
|
||||
|
||||
$expectedRows = [
|
||||
['csv--11', 'csv--12', 'csv--13'],
|
||||
['csv--21', 'csv--22', 'csv--23'],
|
||||
];
|
||||
$this->assertEquals($expectedRows, $allRows);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $fileName
|
||||
* @param string|void $fieldDelimiter
|
||||
* @param string|void $fieldEnclosure
|
||||
* @return array All the read rows the given file
|
||||
*/
|
||||
private function getAllRowsForFile($fileName, $fieldDelimiter = ",", $fieldEnclosure = '"')
|
||||
{
|
||||
$allRows = [];
|
||||
$resourcePath = $this->getResourcePath($fileName);
|
||||
|
||||
$reader = ReaderFactory::create(Type::CSV);
|
||||
$reader->setFieldDelimiter($fieldDelimiter);
|
||||
$reader->setFieldEnclosure($fieldEnclosure);
|
||||
|
||||
$reader->open($resourcePath);
|
||||
|
||||
while ($reader->hasNextRow()) {
|
||||
$allRows[] = $reader->nextRow();
|
||||
}
|
||||
|
||||
$reader->close();
|
||||
|
||||
return $allRows;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace Box\Spout\Reader\Helper\XLSX;
|
||||
|
||||
use Box\Spout\TestUsingResource;
|
||||
|
||||
/**
|
||||
* Class SharedStringsHelperTest
|
||||
*
|
||||
* @package Box\Spout\Reader\Helper\XLSX
|
||||
*/
|
||||
class SharedStringsHelperTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
use TestUsingResource;
|
||||
|
||||
/** @var SharedStringsHelper */
|
||||
private $sharedStringsHelper;
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function setUp()
|
||||
{
|
||||
$resourcePath = $this->getResourcePath('one_sheet_with_shared_strings.xlsx');
|
||||
$this->sharedStringsHelper = new SharedStringsHelper($resourcePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function tearDown()
|
||||
{
|
||||
$this->sharedStringsHelper->cleanup();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testExtractSharedStringsShouldCreateTempFileWithSharedStrings()
|
||||
{
|
||||
$this->sharedStringsHelper->extractSharedStrings();
|
||||
|
||||
$tempFolder = \ReflectionHelper::getValueOnObject($this->sharedStringsHelper, 'tempFolder');
|
||||
|
||||
$filesInTempFolder = $this->getFilesInFolder($tempFolder);
|
||||
$this->assertEquals(1, count($filesInTempFolder), 'One temp file should have been created in the temp folder.');
|
||||
|
||||
$tempFileContents = file_get_contents($filesInTempFolder[0]);
|
||||
$tempFileContentsPerLine = explode("\n", $tempFileContents);
|
||||
|
||||
$this->assertEquals('s1--A1', $tempFileContentsPerLine[0]);
|
||||
$this->assertEquals('s1--E5', $tempFileContentsPerLine[24]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all files that are in the given folder.
|
||||
* It does not include "." and ".." and is not recursive.
|
||||
*
|
||||
* @param string $folderPath
|
||||
* @return array
|
||||
*/
|
||||
private function getFilesInFolder($folderPath)
|
||||
{
|
||||
$files = [];
|
||||
$directoryIterator = new \DirectoryIterator($folderPath);
|
||||
|
||||
foreach ($directoryIterator as $fileInfo) {
|
||||
if ($fileInfo->isFile()) {
|
||||
$files[] = $fileInfo->getPathname();
|
||||
}
|
||||
}
|
||||
|
||||
return $files;
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Box\Spout\Reader\Exception\SharedStringNotFoundException
|
||||
* @return void
|
||||
*/
|
||||
public function testGetStringAtIndexShouldThrowExceptionIfStringNotFound()
|
||||
{
|
||||
$this->sharedStringsHelper->extractSharedStrings();
|
||||
$this->sharedStringsHelper->getStringAtIndex(PHP_INT_MAX);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testGetStringAtIndexShouldReturnTheCorrectStringIfFound()
|
||||
{
|
||||
$this->sharedStringsHelper->extractSharedStrings();
|
||||
|
||||
$sharedString = $this->sharedStringsHelper->getStringAtIndex(0);
|
||||
$this->assertEquals('s1--A1', $sharedString);
|
||||
|
||||
$sharedString = $this->sharedStringsHelper->getStringAtIndex(24);
|
||||
$this->assertEquals('s1--E5', $sharedString);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
<?php
|
||||
|
||||
namespace Box\Spout\Reader;
|
||||
|
||||
use Box\Spout\Common\Type;
|
||||
use Box\Spout\TestUsingResource;
|
||||
|
||||
/**
|
||||
* Class XLSXTest
|
||||
*
|
||||
* @package Box\Spout\Reader
|
||||
*/
|
||||
class XLSXTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
use TestUsingResource;
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function dataProviderForTestReadShouldThrowException()
|
||||
{
|
||||
return [
|
||||
['/path/to/fake/file.xlsx'],
|
||||
['file_with_no_sheets_in_content_types.xlsx'],
|
||||
['file_corrupted.xlsx'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataProviderForTestReadShouldThrowException
|
||||
* @expectedException \Box\Spout\Common\Exception\IOException
|
||||
*
|
||||
* @param string $filePath
|
||||
* @return void
|
||||
*/
|
||||
public function testReadShouldThrowException($filePath)
|
||||
{
|
||||
$this->getAllRowsForFile($filePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function dataProviderForTestReadForAllWorksheets()
|
||||
{
|
||||
return [
|
||||
['one_sheet_with_shared_strings.xlsx', 5, 5],
|
||||
['one_sheet_with_inline_strings.xlsx', 5, 5],
|
||||
['two_sheets_with_shared_strings.xlsx', 10, 5],
|
||||
['two_sheets_with_inline_strings.xlsx', 10, 5]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataProviderForTestReadForAllWorksheets
|
||||
*
|
||||
* @param string $resourceName
|
||||
* @param int $expectedNumOfRows
|
||||
* @param int $expectedNumOfCellsPerRow
|
||||
* @return void
|
||||
*/
|
||||
public function testReadForAllWorksheets($resourceName, $expectedNumOfRows, $expectedNumOfCellsPerRow)
|
||||
{
|
||||
$allRows = $this->getAllRowsForFile($resourceName);
|
||||
|
||||
$this->assertEquals($expectedNumOfRows, count($allRows), "There should be $expectedNumOfRows rows");
|
||||
foreach ($allRows as $row) {
|
||||
$this->assertEquals($expectedNumOfCellsPerRow, count($row), "There should be $expectedNumOfCellsPerRow cells for every row");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testReadShouldKeepEmptyCellsAtTheEndIfDimensionsSpecified()
|
||||
{
|
||||
$allRows = $this->getAllRowsForFile('sheet_without_dimensions_but_spans_and_empty_cells.xlsx');
|
||||
|
||||
$this->assertEquals(2, count($allRows), 'There should be 2 rows');
|
||||
foreach ($allRows as $row) {
|
||||
$this->assertEquals(5, count($row), 'There should be 5 cells for every row, because empty rows should be preserved');
|
||||
}
|
||||
|
||||
$expectedRows = [
|
||||
['s1--A1', 's1--B1', 's1--C1', 's1--D1', 's1--E1'],
|
||||
['s1--A2', 's1--B2', 's1--C2', '', ''],
|
||||
];
|
||||
$this->assertEquals($expectedRows, $allRows);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testReadShouldKeepEmptyCellsAtTheEndIfNoDimensionsButSpansSpecified()
|
||||
{
|
||||
$allRows = $this->getAllRowsForFile('sheet_without_dimensions_and_empty_cells.xlsx');
|
||||
|
||||
$this->assertEquals(2, count($allRows), 'There should be 2 rows');
|
||||
$this->assertEquals(5, count($allRows[0]), 'There should be 5 cells in the first row');
|
||||
$this->assertEquals(3, count($allRows[1]), 'There should be only 3 cells in the second row, because empty rows at the end should be skip');
|
||||
|
||||
$expectedRows = [
|
||||
['s1--A1', 's1--B1', 's1--C1', 's1--D1', 's1--E1'],
|
||||
['s1--A2', 's1--B2', 's1--C2'],
|
||||
];
|
||||
$this->assertEquals($expectedRows, $allRows);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testReadShouldSkipEmptyCellsAtTheEndIfDimensionsNotSpecified()
|
||||
{
|
||||
$allRows = $this->getAllRowsForFile('sheet_without_dimensions_and_empty_cells.xlsx');
|
||||
|
||||
$this->assertEquals(2, count($allRows), 'There should be 2 rows');
|
||||
$this->assertEquals(5, count($allRows[0]), 'There should be 5 cells in the first row');
|
||||
$this->assertEquals(3, count($allRows[1]), 'There should be only 3 cells in the second row, because empty rows at the end should be skip');
|
||||
|
||||
$expectedRows = [
|
||||
['s1--A1', 's1--B1', 's1--C1', 's1--D1', 's1--E1'],
|
||||
['s1--A2', 's1--B2', 's1--C2'],
|
||||
];
|
||||
$this->assertEquals($expectedRows, $allRows);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testReadShouldSkipEmptyRows()
|
||||
{
|
||||
$allRows = $this->getAllRowsForFile('sheet_with_empty_rows.xlsx');
|
||||
|
||||
$this->assertEquals(2, count($allRows), 'There should be only 2 rows, because the empty row is skipped');
|
||||
|
||||
$expectedRows = [
|
||||
['s1--A1', 's1--B1', 's1--C1', 's1--D1', 's1--E1'],
|
||||
['s1--A3', 's1--B3', 's1--C3', 's1--D3', 's1--E3'],
|
||||
];
|
||||
$this->assertEquals($expectedRows, $allRows);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testReadShouldSkipPronunciationData()
|
||||
{
|
||||
$allRows = $this->getAllRowsForFile('sheet_with_pronunciation.xlsx');
|
||||
|
||||
$expectedRow = ['名前', '一二三四'];
|
||||
$this->assertEquals($expectedRow, $allRows[0], 'Pronunciation data should be removed.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testReadShouldBeProtectedAgainstBillionLaughsAttack()
|
||||
{
|
||||
$allRows = $this->getAllRowsForFile('billion_laughs_test_file.xlsx');
|
||||
|
||||
$expectedMaxMemoryUsage = 10 * 1024 * 1024; // 10MB
|
||||
$this->assertLessThan($expectedMaxMemoryUsage, memory_get_peak_usage(true), 'Entities should not be expanded and therefore consume all the memory.');
|
||||
|
||||
$expectedFirstRow = ['s1--A1', 's1--B1', 's1--C1', 's1--D1', 's1--E1'];
|
||||
$this->assertEquals($expectedFirstRow, $allRows[0], 'Entities should be ignored when reading XML files.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $fileName
|
||||
* @return array All the read rows the given file
|
||||
*/
|
||||
private function getAllRowsForFile($fileName)
|
||||
{
|
||||
$allRows = [];
|
||||
$resourcePath = $this->getResourcePath($fileName);
|
||||
|
||||
$reader = ReaderFactory::create(Type::XLSX);
|
||||
$reader->open($resourcePath);
|
||||
|
||||
while ($reader->hasNextSheet()) {
|
||||
$reader->nextSheet();
|
||||
|
||||
while ($reader->hasNextRow()) {
|
||||
$allRows[] = $reader->nextRow();
|
||||
}
|
||||
}
|
||||
|
||||
$reader->close();
|
||||
|
||||
return $allRows;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user