createUnwritableFolderIfNeeded(); $filePath = $this->getGeneratedUnwritableResourcePath($fileName); $writer = WriterFactory::create(Type::CSV); @$writer->openToFile($filePath); $row = EntityFactory::createRow([ EntityFactory::createCell('csv--11'), EntityFactory::createCell('csv--12'), ]); $writer->addRow($row); $writer->close(); } /** * @expectedException \Box\Spout\Writer\Exception\WriterNotOpenedException */ public function testWriteShouldThrowExceptionIfCallAddRowBeforeOpeningWriter() { $writer = WriterFactory::create(Type::CSV); $row = EntityFactory::createRow([ EntityFactory::createCell('csv--11'), EntityFactory::createCell('csv--12'), ]); $writer->addRow($row); $writer->close(); } /** * @expectedException \Box\Spout\Writer\Exception\WriterNotOpenedException */ public function testWriteShouldThrowExceptionIfCallAddRowsBeforeOpeningWriter() { $writer = WriterFactory::create(Type::CSV); $row = EntityFactory::createRow([ EntityFactory::createCell('csv--11'), EntityFactory::createCell('csv--12'), ]); $writer->addRows([$row]); $writer->close(); } /** * @expectedException \Box\Spout\Common\Exception\InvalidArgumentException */ public function testAddRowsShouldThrowExceptionIfRowsAreNotArrayOfRows() { $writer = WriterFactory::create(Type::CSV); $row = new \stdClass(); $writer->addRows([$row]); $writer->close(); } /** * @return void */ public function testCloseShouldNoopWhenWriterIsNotOpened() { $fileName = 'test_double_close_calls.csv'; $this->createGeneratedFolderIfNeeded($fileName); $resourcePath = $this->getGeneratedResourcePath($fileName); $writer = WriterFactory::create(Type::CSV); $writer->close(); // This call should not cause any error $writer->openToFile($resourcePath); $writer->close(); $writer->close(); // This call should not cause any error } /** * @return void */ public function testWriteShouldAddUtf8Bom() { $allRows = [ ['csv--11', 'csv--12'], ]; $writtenContent = $this->writeToCsvFileAndReturnWrittenContent($allRows, 'csv_with_utf8_bom.csv'); $this->assertContains(EncodingHelper::BOM_UTF8, $writtenContent, 'The CSV file should contain a UTF-8 BOM'); } /** * @return void */ public function testWriteShouldNotAddUtf8Bom() { $allRows = [ ['csv--11', 'csv--12'], ]; $writtenContent = $this->writeToCsvFileAndReturnWrittenContent($allRows, 'csv_no_bom.csv', ',', '"', false); $this->assertNotContains(EncodingHelper::BOM_UTF8, $writtenContent, 'The CSV file should not contain a UTF-8 BOM'); } /** * @return void */ public function testWriteShouldSupportAssociativeArrays() { $allRows = [ ['foo' => 'csv--11', 'bar' => 'csv--12'], ]; $writtenContent = $this->writeToCsvFileAndReturnWrittenContent($allRows, 'csv_from_associative_arrays.csv'); $writtenContent = $this->trimWrittenContent($writtenContent); $this->assertEquals('csv--11,csv--12', $writtenContent, 'Values from associative arrays should be written'); } /** * @return void */ public function testWriteShouldSupportNullValues() { $allRows = [ ['csv--11', null, 'csv--13'], ]; $writtenContent = $this->writeToCsvFileAndReturnWrittenContent($allRows, 'csv_with_null_values.csv'); $writtenContent = $this->trimWrittenContent($writtenContent); $this->assertEquals('csv--11,,csv--13', $writtenContent, 'The null values should be replaced by empty values'); } /** * @return void */ public function testWriteShouldSkipEmptyRows() { $allRows = [ ['csv--11', 'csv--12'], [], ['csv--31', 'csv--32'], ]; $writtenContent = $this->writeToCsvFileAndReturnWrittenContent($allRows, 'csv_with_empty_rows.csv'); $writtenContent = $this->trimWrittenContent($writtenContent); $this->assertEquals("csv--11,csv--12\ncsv--31,csv--32", $writtenContent, 'Empty rows should be skipped'); } /** * @return void */ public function testWriteShouldSupportCustomFieldDelimiter() { $allRows = [ ['csv--11', 'csv--12', 'csv--13'], ['csv--21', 'csv--22', 'csv--23'], ]; $writtenContent = $this->writeToCsvFileAndReturnWrittenContent($allRows, 'csv_with_pipe_delimiters.csv', '|'); $writtenContent = $this->trimWrittenContent($writtenContent); $this->assertEquals("csv--11|csv--12|csv--13\ncsv--21|csv--22|csv--23", $writtenContent, 'The fields should be delimited with |'); } /** * @return void */ public function testWriteShouldSupportCustomFieldEnclosure() { $allRows = [ ['This is, a comma', 'csv--12', 'csv--13'], ]; $writtenContent = $this->writeToCsvFileAndReturnWrittenContent($allRows, 'csv_with_pound_enclosures.csv', ',', '#'); $writtenContent = $this->trimWrittenContent($writtenContent); $this->assertEquals('#This is, a comma#,csv--12,csv--13', $writtenContent, 'The fields should be enclosed with #'); } /** * @return void */ public function testWriteShouldAcceptCellObjects() { $allRows = [ [EntityFactory::createCell('String Value'), EntityFactory::createCell(1)], ]; $writtenContent = $this->writeToCsvFileAndReturnWrittenContent($allRows, 'csv_with_cell_objects.csv'); $writtenContent = $this->trimWrittenContent($writtenContent); $this->assertEquals('"String Value",1', $writtenContent); } /** * @param array $allRows * @param string $fileName * @param string $fieldDelimiter * @param string $fieldEnclosure * @param bool $shouldAddBOM * @return string|null */ private function writeToCsvFileAndReturnWrittenContent($allRows, $fileName, $fieldDelimiter = ',', $fieldEnclosure = '"', $shouldAddBOM = true) { $this->createGeneratedFolderIfNeeded($fileName); $resourcePath = $this->getGeneratedResourcePath($fileName); /** @var \Box\Spout\Writer\CSV\Writer $writer */ $writer = WriterFactory::create(Type::CSV); $writer->setFieldDelimiter($fieldDelimiter); $writer->setFieldEnclosure($fieldEnclosure); $writer->setShouldAddBOM($shouldAddBOM); $writer->openToFile($resourcePath); $writer->addRows(array_map(function ($oneRow) { return EntityFactory::createRow(array_map(function ($value) { return EntityFactory::createCell($value); }, $oneRow)); }, $allRows)); $writer->close(); return file_get_contents($resourcePath); } /** * @param string $writtenContent * @return string */ private function trimWrittenContent($writtenContent) { // remove line feeds and UTF-8 BOM return trim($writtenContent, PHP_EOL . EncodingHelper::BOM_UTF8); } }