diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2bd4015..2893061 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -10,7 +10,7 @@ jobs: strategy: matrix: - php: ['7.3', '7.4', '8.0', '8.1', '8.2'] + php: ['8.0', '8.1', '8.2'] stability: ['prefer-lowest', 'prefer-stable'] name: PHP ${{ matrix.php }} - ${{ matrix.stability }} @@ -37,4 +37,7 @@ jobs: run: composer update --${{ matrix.stability }} --prefer-dist --no-interaction --no-progress - name: Execute tests - run: vendor/bin/phpunit --verbose \ No newline at end of file + run: vendor/bin/phpunit --verbose + + - name: Check coding standard + run: vendor/bin/php-cs-fixer --no-interaction --dry-run --diff -v fix lib/ \ No newline at end of file diff --git a/.gitignore b/.gitignore index 2fa8999..428a311 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ /example/test.xlsx /example/~$test.xlsx /.phpunit.result.cache +/.php-cs-fixer.cache diff --git a/README.md b/README.md index b70d6f1..6741618 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Build Status](https://github.com/Ticketpark/HtmlPhpExcel/actions/workflows/tests.yml/badge.svg)](https://github.com/Ticketpark/HtmlPhpExcel/actions) -This is a php library based on [PhpSpreadsheet](https://github.com/PHPOffice/PhpSpreadsheet) which simplifies converting html tables to excel files. It allows styling right within the html template with specific attributes. +This is a php library based on [FastExcelWriter](https://github.com/aVadim483/fast-excel-writer), simplifying converting html tables to excel files. It allows styling right within the html template with specific attributes. ## Installation @@ -16,68 +16,66 @@ composer require ticketpark/htmlphpexcel ```php Column AColumn BValue AValue B'; $htmlPhpExcel = new \Ticketpark\HtmlPhpExcel\HtmlPhpExcel($html); -// Create and output the excel file to the browser -$htmlPhpExcel->process()->output(); - -// Alternatively create the excel and save to a file $htmlPhpExcel->process()->save('myFile.xlsx'); -// or get the \PhpOffice\PhpSpreadsheet\Spreadsheet object to do further work with it -$phpExcelObject = $htmlPhpExcel->process()->getExcelObject(); - ``` -For a more complex example with styling options see [example directory](example). +For a more complex example see [example directory](example). ## Styling -There is support for specific html attributes to allow styling of the excel output. The attributes expect the content to be json_encoded. - -* `_excel-styles`
Supports everything which is possible with PhpSpreadsheet's `applyFromArray()` method ([also see here](https://phpspreadsheet.readthedocs.io/en/latest/topics/recipes/#valid-array-keys-for-style-applyfromarray)). +Styles are set with an html element `_excel-styles`. The attribute expects the content to be in json format. Example: ```html - - + +
Foo
+ Cell value +
``` -* `_excel-dimensions`
Supports changing dimensions of rows (when applied to a `` or ``) or column (when applied to a ``), +You can use any style supported by `fast-excel-writer`, of which the most common are: -Example: -```html - - - - -
Foo
-``` +* border-color +* border-style +* fill-color +* fill-pattern +* font-color +* font-size +* format +* format-text-wrap +* height +* text-align +* text-color +* text-rotation +* text-wrap +* vertical-align +* width + +More information (though unfortunately limited) is available in the [docs of FastExcelWriter](https://github.com/aVadim483/fast-excel-writer/blob/master/docs/04-styles.md). -* `_excel-explicit`
Supports applying an explicit cell value type. +## Adding comments to cells Example: ```html - - + +
0022
+ Cell value +
``` -* `_excel-comment`
Adds comment to cell. - -Examle: -```html - - - - -
Cell value
-``` +## History +* v2.x of this library is based on `FastExcelWriter` +* v1.x of this library was based on `PhpSpreadsheet` +* v0.x of this library was based on `PhpExcel` \ No newline at end of file diff --git a/composer.json b/composer.json index 7db3e13..e66f421 100644 --- a/composer.json +++ b/composer.json @@ -1,22 +1,24 @@ { "name": "ticketpark/htmlphpexcel", "type": "library", - "description": "A php library based on PHPExcel to convert html tables to Excel files, including styling.", - "keywords": ["html", "tables", "excel", "phpexcel"], + "description": "A php library based to convert html tables to Excel files, including styling.", + "keywords": ["html", "tables", "excel", "phpexcel", "phpspreadsheet", "fastexcelwriter"], "homepage": "https://github.com/Ticketpark/HtmlPhpExcel", "license": "MIT", "authors": [ {"name": "Manuel Reinhard", "email": "manu@sprain.ch"} ], "require": { - "php": "^7.3|^8.0.0|^8.1.0|^8.2.0", + "php": "^8.0.0|^8.1.0|^8.2.0", "ext-json": "*", "ext-dom": "*", - "doctrine/collections": "^1.6|^2.0", - "phpoffice/phpspreadsheet": "^1.23" + "ext-intl": "*", + "avadim/fast-excel-writer": "^4.5" }, "require-dev": { - "phpunit/phpunit": "^9.0" + "phpunit/phpunit": "^9.0", + "rector/rector": "^0.18.5", + "friendsofphp/php-cs-fixer": "^3.35" }, "autoload": { "psr-4": { "Ticketpark\\HtmlPhpExcel\\": "lib/HtmlPhpExcel" } diff --git a/example/example.html b/example/example.html index 17c6e4e..7f97958 100644 --- a/example/example.html +++ b/example/example.html @@ -1,8 +1,9 @@ + - + @@ -10,21 +11,21 @@ - - - + + + - + - + @@ -35,23 +36,19 @@ - + - - + + - - - - - - - + + +
An Excel worksheetAn Excel worksheet
Column AColumn B
Column AColumn B
Left alignRight alignRight align
5 6 00220022
251520.20251520.20
No need to fill all cells.And no need to care about how many cells there are in each row.
Merge cells!No need to fill all cells.And no need to care about how many cells there are in each row.Ich bin ein Ümläøut.
diff --git a/lib/HtmlPhpExcel/Elements/BaseElement.php b/lib/HtmlPhpExcel/Elements/BaseElement.php index 97df400..f171f9b 100644 --- a/lib/HtmlPhpExcel/Elements/BaseElement.php +++ b/lib/HtmlPhpExcel/Elements/BaseElement.php @@ -1,30 +1,24 @@ attributes = new ArrayCollection(); - } + private array $attributes = []; public function addAttribute(string $key, string $value): void { - $this->attributes->set($key, $value); + $this->attributes[$key] = $value; } - public function getAttribute($key): ?string + public function getAttribute(string $key): ?string { - return $this->attributes->get($key); + if (!isset($this->attributes[$key])) { + return null; + } + + return $this->attributes[$key]; } -} \ No newline at end of file +} diff --git a/lib/HtmlPhpExcel/Elements/Cell.php b/lib/HtmlPhpExcel/Elements/Cell.php index 183fff9..e02138f 100644 --- a/lib/HtmlPhpExcel/Elements/Cell.php +++ b/lib/HtmlPhpExcel/Elements/Cell.php @@ -1,29 +1,20 @@ ) - * - * @var bool - */ - private $isHeader = false; + private ?string $value = null; + private bool $isHeader = false; public function setValue(string $value): void { $this->value = $value; } - public function getValue(): string + public function getValue(): ?string { return $this->value; } @@ -37,4 +28,4 @@ public function isHeader(): bool { return $this->isHeader; } -} \ No newline at end of file +} diff --git a/lib/HtmlPhpExcel/Elements/Document.php b/lib/HtmlPhpExcel/Elements/Document.php index 1b11c40..bc4f3ca 100644 --- a/lib/HtmlPhpExcel/Elements/Document.php +++ b/lib/HtmlPhpExcel/Elements/Document.php @@ -1,33 +1,23 @@ tables = new ArrayCollection(); - } + private array $tables = []; public function addTable(Table $table): void { - $this->tables->add($table); + $this->tables[] = $table; } - public function getTables(): ArrayCollection + /** + * @return array + */ + public function getTables(): array { return $this->tables; } -} \ No newline at end of file +} diff --git a/lib/HtmlPhpExcel/Elements/Element.php b/lib/HtmlPhpExcel/Elements/Element.php index 4345a09..35c02a3 100644 --- a/lib/HtmlPhpExcel/Elements/Element.php +++ b/lib/HtmlPhpExcel/Elements/Element.php @@ -2,4 +2,6 @@ namespace Ticketpark\HtmlPhpExcel\Elements; -interface Element {}; \ No newline at end of file +interface Element +{ +}; diff --git a/lib/HtmlPhpExcel/Elements/Row.php b/lib/HtmlPhpExcel/Elements/Row.php index a40a9f8..1e0d513 100644 --- a/lib/HtmlPhpExcel/Elements/Row.php +++ b/lib/HtmlPhpExcel/Elements/Row.php @@ -1,31 +1,23 @@ cells = new ArrayCollection(); - parent::__construct(); - } + private array $cells = []; public function addCell(Cell $cell): void { - $this->cells->add($cell); + $this->cells[] = $cell; } - public function getCells(): ArrayCollection + /** + * @return array + */ + public function getCells(): array { return $this->cells; } -} \ No newline at end of file +} diff --git a/lib/HtmlPhpExcel/Elements/Table.php b/lib/HtmlPhpExcel/Elements/Table.php index 9e3a0e3..2eaad54 100644 --- a/lib/HtmlPhpExcel/Elements/Table.php +++ b/lib/HtmlPhpExcel/Elements/Table.php @@ -1,31 +1,23 @@ rows = new ArrayCollection(); - parent::__construct(); - } + private array $rows = []; public function addRow(Row $row): void { - $this->rows->add($row); + $this->rows[] = $row; } - public function getRows(): ArrayCollection + /** + * @return array + */ + public function getRows(): array { return $this->rows; } -} \ No newline at end of file +} diff --git a/lib/HtmlPhpExcel/Exception/HtmlPhpExcelException.php b/lib/HtmlPhpExcel/Exception/HtmlPhpExcelException.php deleted file mode 100644 index 8236281..0000000 --- a/lib/HtmlPhpExcel/Exception/HtmlPhpExcelException.php +++ /dev/null @@ -1,12 +0,0 @@ - - */ -class HtmlPhpExcelException extends \Exception -{ -} diff --git a/lib/HtmlPhpExcel/Exception/InexistentExcelObjectException.php b/lib/HtmlPhpExcel/Exception/InexistentExcelObjectException.php new file mode 100644 index 0000000..5db2196 --- /dev/null +++ b/lib/HtmlPhpExcel/Exception/InexistentExcelObjectException.php @@ -0,0 +1,9 @@ +) must have to be parsed. * Default is none, which results in all rows of a parsed table. - * - * @var string */ - private $rowClass; + private ?string $rowClass = null; /** * The class attribute the rows () must have to be parsed. * Default is none, which results in all rows of a parsed table. - * - * @var string */ - private $rowClass; + private ?string $rowClass = null; /** * The class attribute the rows (
or ) must have to be parsed. * Default is none, which results in all cells of a parsed row. - * - * @var string */ - private $cellClass; + private ?string $cellClass = null; + + /** + * The default styles to be applied to all excel cells + */ + private array $defaultStyles = []; /** - * The Spreadsheet instance generated with this class - * - * @var Spreadsheet + * The default styles additionally to be applied to header cells () */ - private $spreadsheet; + private array $defaultHeaderStyles = []; /** * The document instance which contains the parsed html elements - * - * @var \Ticketpark\HtmlPhpExcel\Elements\Document */ - private $document; + private HtmlPhpExcelElement\Document $document; /** - * Determines if the values should be encoded in some way before writing to the excel cell - * - * @var null|string + * The instance of the Excel creator used within this library. */ - private $changeEncoding; + private ?Excel $excel = null; - public function __construct(string $htmlStringOrFile = null) - { - $this->htmlStringOrFile = $htmlStringOrFile; + public function __construct( + private string $htmlStringOrFile + ) { } - public function setTableClass(string $class = null): self + public function setTableClass(?string $class): self { $this->tableClass = $class; return $this; } - public function setRowClass(string $class = null): self + public function setRowClass(?string $class): self { $this->rowClass = $class; return $this; } - public function setCellClass(string $class = null): self + public function setCellClass(?string $class): self { $this->cellClass = $class; return $this; } - public function process(Spreadsheet $spreadsheet = null): self + public function setDefaultStyles(array $defaultStyles): self { - if ($spreadsheet) { - $this->spreadsheet = $spreadsheet; - } else { - $this->spreadsheet = new Spreadsheet(); - } - - $this->parseHtml(); - $this->createExcel(); + $this->defaultStyles = $defaultStyles; return $this; } - public function getExcelObject(): Spreadsheet + public function setDefaultHeaderStyles(array $defaultHeaderStyles): self { - if (!$this->spreadsheet instanceof Spreadsheet) { - throw new HtmlPhpExcelException('You must run process() first to create a PhpSpreadsheet instance'); - } + $this->defaultHeaderStyles = $defaultHeaderStyles; - return $this->spreadsheet; + return $this; } - public function output(string $filename = 'excel.xlsx', string $excelWriterType = 'xlsx'): void + public function process(?Excel $excel = null): self { - if (!$this->spreadsheet instanceof Spreadsheet) { - throw new HtmlPhpExcelException('You must run process() first to create a PhpSpreadsheet instance'); + $this->excel = $excel; + if (null === $this->excel) { + $this->excel = Excel::create(); } - header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); - header('Content-Disposition: attachment;filename="'.$filename.'"'); - header('Cache-Control: max-age=1'); + $this->parseHtml(); + $this->createExcel(); - $writer = IOFactory::createWriter($this->spreadsheet, ucfirst($excelWriterType)); - $writer->save('php://output'); + return $this; } - public function save(string $file, string $excelWriterType = 'xlsx'): self + public function download(string $filename): void { - if (!$this->spreadsheet instanceof Spreadsheet) { - throw new HtmlPhpExcelException('You must run process() first to create a PhpSpreadsheet instance'); - } - - $writer = IOFactory::createWriter($this->spreadsheet, ucfirst($excelWriterType)); - $writer->save($file); - - return $this; + $filename = str_ireplace('.xlsx', '', $filename); + $this->getExcelObject()->download($filename . '.xlsx'); } - public function utf8EncodeValues(): self + public function save(string $filename): bool { - $this->changeEncoding = 'utf8_encode'; + $filename = str_ireplace('.xlsx', '', $filename); - return $this; + return $this->getExcelObject()->save($filename . '.xlsx'); } - public function utf8DecodeValues(): self + public function getExcelObject(): Excel { - $this->changeEncoding = 'utf8_decode'; + if (null === $this->excel) { + throw new InexistentExcelObjectException('You must run process() before handling the excel object. '); + } - return $this; + return $this->excel; } private function parseHtml(): void @@ -169,139 +138,58 @@ private function parseHtml(): void private function createExcel(): void { // Loop over all tables in document - $tableNumber = 0; - foreach($this->document->getTables() as $table){ + foreach($this->document->getTables() as $table) { // Handle worksheets - if ($tableNumber > 0) { - $this->spreadsheet->createSheet(); - } - $excelWorksheet = $this->spreadsheet->setActiveSheetIndex($tableNumber); - if ($sheetTitle = $table->getAttribute('_excel-name')) { - $excelWorksheet->setTitle($sheetTitle); - } + $this->excel->makeSheet($table->getAttribute('_excel-name')); + $sheet = $this->excel->sheet(); // Loop over all rows - $rowNumber = $this->getHighestRow($excelWorksheet); - foreach($table->getRows() as $row){ - $rowStylesArray = $this->getRowStylesArray($row); - if (!empty($rowStylesArray)) { - $excelWorksheet->getStyle($rowNumber.':'.$rowNumber)->applyFromArray($rowStylesArray); - } - - $excelWorksheet->getCell('A'.$rowNumber); - $this->setDimensionsForRow($excelWorksheet, $excelWorksheet->getRowIterator($rowNumber)->current(), $row); - - // Loop over all cells in row - $cellNumber = 1; - foreach($row->getCells() as $cell){ - $excelCellIndex = Coordinate::stringFromColumnIndex($cellNumber).$rowNumber; - - // Skip cells withing merge range - while ($excelWorksheet->getCell($excelCellIndex)->isInMergeRange()) { - $cellNumber++; - $excelCellIndex = Coordinate::stringFromColumnIndex($cellNumber).$rowNumber; - } - - // Set value - $explicitCellType = $cell->getAttribute('_excel-explicit'); - if (!$explicitCellType) { - $explicitCellType = $row->getAttribute('_excel-explicit'); + $rowIndex = 1; + foreach($table->getRows() as $row) { + $rowStyles = $this->getStyles($row); + $sheet->setRowStyles( + $rowIndex, + empty($rowStyles) ? null : $rowStyles + ); + + // Loop over all cells in a row + $colIndex = 1; + foreach($row->getCells() as $cell) { + $cellStyles = $this->getStyles($cell); + $sheet->writeCell( + trim($cell->getValue()), + empty($cellStyles) ? null : $cellStyles + ); + + if (isset($cellStyles['width'])) { + $sheet->setColWidth($colIndex, $cellStyles['width']); } - if ($explicitCellType) { - $excelWorksheet->setCellValueExplicit( - $excelCellIndex, - $this->changeValueEncoding($cell->getValue()), - $this->convertStaticPhpSpreadsheetConstantsFromStringsToConstants($explicitCellType) - ); - } else { - $excelWorksheet->setCellValue( - $excelCellIndex, - $this->changeValueEncoding($cell->getValue()) - ); + if (isset($cellStyles['height'])) { + $sheet->setRowHeight($rowIndex, $cellStyles['height']); } $cellComment = $cell->getAttribute('_excel-comment'); if ($cellComment) { - $excelWorksheet->getComment($excelCellIndex)->getText()->createText($cellComment); - } - - // Merge cells - $colspan = $cell->getAttribute('colspan'); - $rowspan = $cell->getAttribute('rowspan'); - - if ($colspan || $rowspan) { - if ($colspan) {$colspan = $colspan - 1;} - if ($rowspan) {$rowspan = $rowspan - 1;} - $mergeCellsTargetCellIndex = Coordinate::stringFromColumnIndex($cellNumber + $colspan).($rowNumber + $rowspan); - $excelWorksheet->mergeCells($excelCellIndex.':'.$mergeCellsTargetCellIndex); - } - - // Set styles - $cellStylesArray = $this->getCellStylesArray($cell); - if (!empty($cellStylesArray)) { - $excelWorksheet->getStyle($excelCellIndex)->applyFromArray($cellStylesArray); + $sheet->addNote(Excel::cellAddress($rowIndex, $colIndex), $cellComment); } - $this->setDimensionsForCell($excelWorksheet, $excelWorksheet->getCell($excelCellIndex), $cell); - $cellNumber++; + $colIndex++; } - $rowNumber++; - } - - $tableNumber++; - } - } - - private function setDimensionsForRow(Worksheet $excelWorksheet, Row $excelElement, HtmlPhpExcelElement\Row $row): void - { - $dimensions = $this->getDimensionsArray($row); - - if (isset($dimensions['row'])) { - foreach($dimensions['row'] as $rowKey => $rowValue) { - $method = 'set'.ucfirst($rowKey); - $excelWorksheet->getRowDimension($excelElement->getRowIndex())->$method($rowValue); + $sheet->nextRow(); + $rowIndex++; } } } - private function setDimensionsForCell(Worksheet $excelWorksheet, Cell $excelElement, HtmlPhpExcelElement\Cell $cell): void + private function getStyles(HtmlPhpExcelElement\Element $documentElement): array { - $dimensions = $this->getDimensionsArray($cell); - - if (isset($dimensions['column'])) { - foreach($dimensions['column'] as $columnKey => $columnValue) { - $method = 'set'.ucfirst($columnKey); - $excelWorksheet->getColumnDimension($excelElement->getColumn())->$method($columnValue); - } - } - } - - private function getRowStylesArray(HtmlPhpExcelElement\Row $row): array - { - return $this->getStylesArray($row); - } - - private function getCellStylesArray(HtmlPhpExcelElement\Cell $cell): array - { - $styles = $this->getStylesArray($cell); - - if ($cell->isHeader()) { - $styles['font']['bold'] = true; - } - - return $styles; - } - - private function getStylesArray(HtmlPhpExcelElement\Element $documentElement): array - { - $styles = array(); - + $styles = []; if ($attributeStyles = $documentElement->getAttribute('_excel-styles')) { if (!is_array($attributeStyles)) { - $decodedJson = json_decode($attributeStyles, true); + $decodedJson = json_decode($attributeStyles, true, 512, JSON_THROW_ON_ERROR); if (null !== $decodedJson) { $attributeStyles = $decodedJson; } @@ -312,98 +200,10 @@ private function getStylesArray(HtmlPhpExcelElement\Element $documentElement): a $styles = $attributeStyles; } - $styles = $this->sanitizeArray($styles); - - return $styles; - } - - private function getDimensionsArray(HtmlPhpExcelElement\Element $documentElement): array - { - $dimensions = array(); - - if ($attributeDimensions= $documentElement->getAttribute('_excel-dimensions')) { - if (!is_array($attributeDimensions)) { - $decodedJson = json_decode($attributeDimensions, true); - if (null !== $decodedJson) { - $attributeDimensions = $decodedJson; - } - } - } - - if (is_array($attributeDimensions)) { - $dimensions = $attributeDimensions; - } - - $dimensions = $this->sanitizeArray($dimensions); - - return $dimensions; - } - - private function getHighestRow(Worksheet $excelWorksheet): int - { - $highestRow = $excelWorksheet->getHighestRow(); - - return $highestRow + ($highestRow > 1); - } - - private function sanitizeArray(array $array): array - { - foreach($array as $key => $value){ - if(is_array($value)){ - $array[$key] = $this->sanitizeArray($value); - } else { - $array[$key] = $this->convertStaticPhpSpreadsheetConstantsFromStringsToConstants($value); - } - } - - return $array; - } - - /** - * Turn Spreadsheet constants into actual constants - * - * Example: - * If the html element contains a _excel-styles attribute with the json-encoded version of the array below, - * the value PhpSpreadsheet_Style_Fill::FILL_SOLID would be treated as a string. - * We need to treat it as a static class constant and also apply the correct namespace. - * - * array ( - * 'fill' => array ( - * 'type' => 'PhpSpreadsheet_Style_Fill::FILL_SOLID', - * 'color' => array ( - * 'rgb' => '4F4F4F', - * ), - * ), - * ) - * - * @param string $value - * @return string - */ - private function convertStaticPhpSpreadsheetConstantsFromStringsToConstants(string $value) - { - if (strpos($value, 'PHPExcel_') === 0 || strpos($value, 'PhpSpreadsheet_') === 0) { - $parts = explode('::', $value); - - $namespaceParts = explode('_', $parts[0]); - $fqns = 'PhpOffice\\PhpSpreadsheet'; - unset($namespaceParts[0]); - foreach($namespaceParts as $namespacePart) { - $fqns .= '\\' . $namespacePart; - } - - $class = new \ReflectionClass($fqns); - $value = $class->getConstant($parts[1]); - } - - return $value; - } - - private function changeValueEncoding(string $value): string - { - if (null !== $this->changeEncoding) { - $value = call_user_func($this->changeEncoding, $value); - } - - return $value; + return array_merge( + $this->defaultStyles, + ($documentElement instanceof HtmlPhpExcelElement\Cell && $documentElement->isHeader()) ? $this->defaultHeaderStyles : [], + $styles + ); } } diff --git a/lib/HtmlPhpExcel/Parser/Parser.php b/lib/HtmlPhpExcel/Parser/Parser.php index bbdc939..98a2f3c 100644 --- a/lib/HtmlPhpExcel/Parser/Parser.php +++ b/lib/HtmlPhpExcel/Parser/Parser.php @@ -6,81 +6,58 @@ use Ticketpark\HtmlPhpExcel\Elements\Document; use Ticketpark\HtmlPhpExcel\Elements\Row; use Ticketpark\HtmlPhpExcel\Elements\Table; -use Ticketpark\HtmlPhpExcel\Exception\HtmlPhpExcelException; - -class Parser { +class Parser +{ /** * The html string to be parsed - * - * @var string */ - private $html; + private string $html; /** * The class attribute the tables must have to be parsed * Default is none, which results in all tables. - * - * @var string */ - private $tableClass; + private ?string $tableClass = null; /** * The class attribute the rows (
or ) must have to be parsed. * Default is none, which results in all cells of a parsed row. - * - * @var string */ - private $cellClass; + private ?string $cellClass = null; public function __construct(string $htmlStringOrFile = null) { if (null !== $htmlStringOrFile) { if (PHP_MAXPATHLEN >= strlen($htmlStringOrFile) && is_file($htmlStringOrFile)) { - $this->setHtmlFile($htmlStringOrFile); - } elseif (is_string($htmlStringOrFile)) { - $this->setHtml($htmlStringOrFile); + $this->html = file_get_contents($htmlStringOrFile); + } else { + $this->html = $htmlStringOrFile; } } } - public function setHtml(string $html): self - { - $this->html = $html; - - return $this; - } - - public function setHtmlFile(string $file): self - { - $this->html = file_get_contents($file); - - return $this; - } - - public function setTableClass(string $class = null): self + public function setTableClass(?string $class): self { $this->tableClass = $class; return $this; } - public function setRowClass(string $class = null): self + public function setRowClass(?string $class): self { $this->rowClass = $class; return $this; } - public function setCellClass(string $class = null): self + public function setCellClass(?string $class): self { $this->cellClass = $class; @@ -89,10 +66,6 @@ public function setCellClass(string $class = null): self public function parse(): Document { - if (null === $this->html) { - throw new HtmlPhpExcelException('You must provide html content first. Use setHtml() or setHtmlFile().'); - } - $dom = new \DOMDocument(); $dom->loadHTML($this->html); @@ -110,7 +83,7 @@ public function parse(): Document $row = new Row(); $htmlCells = $xpath->query( - './/td[contains(concat(" ", normalize-space(@class), " "), "'.$this->cellClass.'")] + './/td[contains(concat(" ", normalize-space(@class), " "), "'.$this->cellClass.'")] | .//th[contains(concat(" ", normalize-space(@class), " "), "'.$this->cellClass.'")]', $htmlRow ); @@ -147,4 +120,3 @@ public function parse(): Document return $document; } } - diff --git a/rector.php b/rector.php new file mode 100644 index 0000000..d08b69b --- /dev/null +++ b/rector.php @@ -0,0 +1,17 @@ +paths([ + __DIR__ . '/lib', + __DIR__ . '/tests', + ]); + + $rectorConfig->sets([ + LevelSetList::UP_TO_PHP_80 + ]); +}; diff --git a/tests/HtmlPhpExcel/Tests/HtmlPhpExcelTest.php b/tests/HtmlPhpExcel/Tests/HtmlPhpExcelTest.php index 3d9727d..b1eb708 100644 --- a/tests/HtmlPhpExcel/Tests/HtmlPhpExcelTest.php +++ b/tests/HtmlPhpExcel/Tests/HtmlPhpExcelTest.php @@ -2,18 +2,17 @@ namespace HtmlPhpExcel\Tests; +use avadim\FastExcelWriter\Excel; use PHPUnit\Framework\TestCase; -use Ticketpark\HtmlPhpExcel\Exception\HtmlPhpExcelException; +use Ticketpark\HtmlPhpExcel\Exception\InexistentExcelObjectException; use Ticketpark\HtmlPhpExcel\HtmlPhpExcel; /** - * HtmlPhpExcelTest - * * This only tests basic behaviour of the class, not the actual content of the excel files. */ class HtmlPhpExcelTest extends TestCase { - protected $pathToTestfiles; + private string $pathToTestfiles; public function setUp(): void { @@ -46,35 +45,33 @@ public function testSave() unlink($file); } - public function testGetExcelObject() + public function testItReturnsExcelInstance() { $htmlphpexcel = new HtmlPhpExcel('
'); - $excelObject = $htmlphpexcel->process()->getExcelObject(); - - $this->assertInstanceOf('PhpOffice\PhpSpreadsheet\Spreadsheet', $excelObject); + $this->assertInstanceOf(Excel::class, $htmlphpexcel->process()->getExcelObject()); } - public function testExceptionOutputWithoutProcess() + public function testItThrowsExceptionIfProcessIsNotRunBeforeGettingExcelObject() { - $this->expectException(HtmlPhpExcelException::class); + $this->expectException(InexistentExcelObjectException::class); $htmlphpexcel = new HtmlPhpExcel('
'); - $htmlphpexcel->output(); + $htmlphpexcel->getExcelObject(); } - public function testExceptionSaveWithoutProcess() + public function testItThrowsExceptionIfProcessIsNotRunBeforeSave() { - $this->expectException(HtmlPhpExcelException::class); + $this->expectException(InexistentExcelObjectException::class); $htmlphpexcel = new HtmlPhpExcel('
'); - $htmlphpexcel->save('foo.xls'); + $htmlphpexcel->save('foo'); } - public function testExceptionGetObjectWithoutProcess() + public function testItThrowsExceptionIfProcessIsNotRunBeforeDownload() { - $this->expectException(HtmlPhpExcelException::class); + $this->expectException(InexistentExcelObjectException::class); $htmlphpexcel = new HtmlPhpExcel('
'); - $htmlphpexcel->getExcelObject(); + $htmlphpexcel->download('foo'); } } diff --git a/tests/HtmlPhpExcel/Tests/Parser/ParserTest.php b/tests/HtmlPhpExcel/Tests/Parser/ParserTest.php index 375a8f3..5a8403b 100644 --- a/tests/HtmlPhpExcel/Tests/Parser/ParserTest.php +++ b/tests/HtmlPhpExcel/Tests/Parser/ParserTest.php @@ -3,23 +3,22 @@ namespace HtmlPhpExcel\Tests\Parser; use PHPUnit\Framework\TestCase; -use Ticketpark\HtmlPhpExcel\Exception\HtmlPhpExcelException; use Ticketpark\HtmlPhpExcel\Parser\Parser; class ParserTest extends TestCase { - private $pathToTestfiles = __DIR__.'/../../../testfiles/'; + private string $pathToTestfiles = __DIR__.'/../../../testfiles'; public function testSimpleTable() { $parser = new Parser('
row1cell1row1cell2
row2cell1row2cell2
'); $document = $parser->parse(); - $this->assertEquals(1, $document->getTables()->count()); - $this->assertEquals(2, $document->getTables()->current()->getRows()->count()); + $this->assertEquals(1, count($document->getTables())); + $this->assertEquals(2, count($document->getTables()[0]->getRows())); - foreach($document->getTables()->current()->getRows() as $row){ - $this->assertEquals(2, $row->getCells()->count()); + foreach($document->getTables()[0]->getRows() as $row){ + $this->assertEquals(2, count($row->getCells())); } } @@ -32,12 +31,12 @@ public function testMultipleTables() '); $document = $parser->parse(); - $this->assertEquals(2, $document->getTables()->count()); + $this->assertEquals(2, count($document->getTables())); foreach($document->getTables() as $table){ - $this->assertEquals(2, $table->getRows()->count()); + $this->assertEquals(2, count($table->getRows())); foreach($table->getRows() as $row){ - $this->assertEquals(2, $row->getCells()->count()); + $this->assertEquals(2, count($row->getCells())); } } } @@ -51,7 +50,7 @@ public function testMultipleTablesWithTableClass() '); $document = $parser->setTableClass('pickme')->parse(); - $this->assertEquals(1, $document->getTables()->count()); + $this->assertEquals(1, count($document->getTables())); } public function testMultipleTablesWithRowClass() @@ -64,7 +63,7 @@ public function testMultipleTablesWithRowClass() $document = $parser->setRowClass('pickme')->parse(); foreach($document->getTables() as $table){ - $this->assertEquals(1, $table->getRows()->count()); + $this->assertEquals(1, count($table->getRows())); } } @@ -79,7 +78,7 @@ public function testMultipleTablesWithCellClass() foreach($document->getTables() as $table){ foreach($table->getRows() as $row){ - $this->assertEquals(1, $row->getCells()->count()); + $this->assertEquals(1, count($row->getCells())); } } } @@ -97,12 +96,12 @@ public function testMultipleTablesWithMixedClasses() ->setCellClass('pickme') ->parse(); - $this->assertEquals(1, $document->getTables()->count()); + $this->assertEquals(1, count($document->getTables())); foreach($document->getTables() as $table){ - $this->assertEquals(1, $table->getRows()->count()); + $this->assertEquals(1, count($table->getRows())); foreach($table->getRows() as $row){ - $this->assertEquals(1, $row->getCells()->count()); + $this->assertEquals(1, count($row->getCells())); } } } @@ -120,12 +119,12 @@ public function testMultipleTablesWithMixedClassesAndOtherClasses() ->setCellClass('pickme') ->parse(); - $this->assertEquals(1, $document->getTables()->count()); + $this->assertEquals(1, count($document->getTables())); foreach($document->getTables() as $table){ - $this->assertEquals(1, $table->getRows()->count()); + $this->assertEquals(1, count($table->getRows())); foreach($table->getRows() as $row){ - $this->assertEquals(1, $row->getCells()->count()); + $this->assertEquals(1, count($row->getCells())); } } } @@ -135,7 +134,7 @@ public function testFindsHeaders() $parser = new Parser('
row1cell1row1cell2
row2cell1row2cell2
'); $document = $parser->parse(); - foreach($document->getTables()->current()->getRows() as $key => $row){ + foreach($document->getTables()[0]->getRows() as $key => $row){ foreach($row->getCells() as $cell){ if (0 === $key) { $this->assertTrue($cell->isHeader()); @@ -172,27 +171,10 @@ public function testFindsAttributes() } } - public function testSetHtml() + public function testWithFile() { - $parser = new Parser(); - $parser->setHtml('
'); + $parser = new Parser($this->pathToTestfiles . '/test.html'); $document = $parser->parse(); - $this->assertEquals(1, $document->getTables()->count()); - } - - public function testSetHtmlFile() - { - $parser = new Parser(); - $parser->setHtmlFile($this->pathToTestfiles.'test.html'); - $document = $parser->parse(); - $this->assertEquals(1, $document->getTables()->count()); - } - - public function testExceptionWithoutHtmlContent() - { - $this->expectException(HtmlPhpExcelException::class); - - $parser = new Parser(); - $parser->parse(); + $this->assertEquals(1, count($document->getTables())); } }