From 7e3807309de6794fb277ceb8ef9af8bb6969e775 Mon Sep 17 00:00:00 2001 From: oleibman <10341515+oleibman@users.noreply.github.com> Date: Fri, 9 Sep 2022 07:34:36 -0700 Subject: [PATCH 1/7] Reconcile Differences between Css and Excel For Cell Alignment (#3048) This PR expands on PR #2195 from @nkjackzhang. That PR has been stalled for some time awaiting requested fixes. Those fixes are part of this PR, and additional tests and samples are added. The original request was to handle `vertical-align:middle` in Css (Excel uses `center`). This PR does its best to also handle vertical alignment Excel values not found in Css - `justify` (as `middle`) and `distributed` (as `middle`). It likewises handles valid Css values not found in Excel (`baseline`, `sub`, and `text-bottom` as `bottom`; `super` and `text-top` as `top`; `middle` as `center`). It also handles horizontal alignment Excel values not found in Css - `center-continuous` as `center` and `distributed` as `justify`; I couldn't think of a reasonable equivalent for `fill`, so it is ignored. The values assigned for vertical and horizontal alignment are now lower-cased (special handling required for `centerContinuous`). --- samples/Basic/49_alignment.php | 80 +++++++++++++++++ src/PhpSpreadsheet/Style/Alignment.php | 69 +++++++++++++-- src/PhpSpreadsheet/Writer/Html.php | 24 ++--- src/PhpSpreadsheet/Writer/Xlsx/Style.php | 21 +++-- .../Style/AlignmentMiddleTest.php | 87 +++++++++++++++++++ .../Style/AlignmentTest.php | 31 ++++--- 6 files changed, 273 insertions(+), 39 deletions(-) create mode 100644 samples/Basic/49_alignment.php create mode 100644 tests/PhpSpreadsheetTests/Style/AlignmentMiddleTest.php diff --git a/samples/Basic/49_alignment.php b/samples/Basic/49_alignment.php new file mode 100644 index 00000000..83fdb3d4 --- /dev/null +++ b/samples/Basic/49_alignment.php @@ -0,0 +1,80 @@ +log('Create new Spreadsheet object'); +$spreadsheet = new Spreadsheet(); +$spreadsheet->getProperties()->setTitle('Alignment'); +$sheet = $spreadsheet->getActiveSheet(); +$hi = 'Hi There'; +$ju = 'This is a longer than normal sentence'; +$sheet->fromArray([ + ['', 'default', 'bottom', 'top', 'center', 'justify', 'distributed'], + ['default', $hi, $hi, $hi, $hi, $hi, $hi], + ['left', $hi, $hi, $hi, $hi, $hi, $hi], + ['right', $hi, $hi, $hi, $hi, $hi, $hi], + ['center', $hi, $hi, $hi, $hi, $hi, $hi], + ['justify', $ju, $ju, $ju, $ju, $ju, $ju], + ['distributed', $ju, $ju, $ju, $ju, $ju, $ju], +]); +$sheet->getColumnDimension('B')->setWidth(20); +$sheet->getColumnDimension('C')->setWidth(20); +$sheet->getColumnDimension('D')->setWidth(20); +$sheet->getColumnDimension('E')->setWidth(20); +$sheet->getColumnDimension('F')->setWidth(20); +$sheet->getColumnDimension('G')->setWidth(20); +$sheet->getRowDimension(2)->setRowHeight(30); +$sheet->getRowDimension(3)->setRowHeight(30); +$sheet->getRowDimension(4)->setRowHeight(30); +$sheet->getRowDimension(5)->setRowHeight(30); +$sheet->getRowDimension(6)->setRowHeight(40); +$sheet->getRowDimension(7)->setRowHeight(40); +$minRow = 2; +$maxRow = 7; +$minCol = 'B'; +$maxCol = 'g'; +$sheet->getStyle("C$minRow:C$maxRow") + ->getAlignment() + ->setVertical(Alignment::VERTICAL_BOTTOM); +$sheet->getStyle("D$minRow:D$maxRow") + ->getAlignment() + ->setVertical(Alignment::VERTICAL_TOP); +$sheet->getStyle("E$minRow:E$maxRow") + ->getAlignment() + ->setVertical(Alignment::VERTICAL_CENTER); +$sheet->getStyle("F$minRow:F$maxRow") + ->getAlignment() + ->setVertical(Alignment::VERTICAL_JUSTIFY); +$sheet->getStyle("G$minRow:G$maxRow") + ->getAlignment() + ->setVertical(Alignment::VERTICAL_DISTRIBUTED); +$sheet->getStyle("{$minCol}3:{$maxCol}3") + ->getAlignment() + ->setHorizontal(Alignment::HORIZONTAL_LEFT); +$sheet->getStyle("{$minCol}4:{$maxCol}4") + ->getAlignment() + ->setHorizontal(Alignment::HORIZONTAL_RIGHT); +$sheet->getStyle("{$minCol}5:{$maxCol}5") + ->getAlignment() + ->setHorizontal(Alignment::HORIZONTAL_CENTER); +$sheet->getStyle("{$minCol}6:{$maxCol}6") + ->getAlignment() + ->setHorizontal(Alignment::HORIZONTAL_JUSTIFY); +$sheet->getStyle("{$minCol}7:{$maxCol}7") + ->getAlignment() + ->setHorizontal(Alignment::HORIZONTAL_DISTRIBUTED); + +$sheet->getCell('A9')->setValue('Center Continuous A9-C9'); +$sheet->getStyle('A9:C9') + ->getAlignment() + ->setHorizontal(Alignment::HORIZONTAL_CENTER_CONTINUOUS); +$sheet->getCell('A10')->setValue('Fill'); +$sheet->getStyle('A10') + ->getAlignment() + ->setHorizontal(Alignment::HORIZONTAL_FILL); +$sheet->setSelectedCells('A1'); + +$helper->write($spreadsheet, __FILE__, ['Xlsx', 'Html', 'Xls']); diff --git a/src/PhpSpreadsheet/Style/Alignment.php b/src/PhpSpreadsheet/Style/Alignment.php index 83ac5b0d..68edfaca 100644 --- a/src/PhpSpreadsheet/Style/Alignment.php +++ b/src/PhpSpreadsheet/Style/Alignment.php @@ -15,6 +15,27 @@ class Alignment extends Supervisor const HORIZONTAL_JUSTIFY = 'justify'; const HORIZONTAL_FILL = 'fill'; const HORIZONTAL_DISTRIBUTED = 'distributed'; // Excel2007 only + private const HORIZONTAL_CENTER_CONTINUOUS_LC = 'centercontinuous'; + // Mapping for horizontal alignment + const HORIZONTAL_ALIGNMENT_FOR_XLSX = [ + self::HORIZONTAL_LEFT => self::HORIZONTAL_LEFT, + self::HORIZONTAL_RIGHT => self::HORIZONTAL_RIGHT, + self::HORIZONTAL_CENTER => self::HORIZONTAL_CENTER, + self::HORIZONTAL_CENTER_CONTINUOUS => self::HORIZONTAL_CENTER_CONTINUOUS, + self::HORIZONTAL_JUSTIFY => self::HORIZONTAL_JUSTIFY, + self::HORIZONTAL_FILL => self::HORIZONTAL_FILL, + self::HORIZONTAL_DISTRIBUTED => self::HORIZONTAL_DISTRIBUTED, + ]; + // Mapping for horizontal alignment CSS + const HORIZONTAL_ALIGNMENT_FOR_HTML = [ + self::HORIZONTAL_LEFT => self::HORIZONTAL_LEFT, + self::HORIZONTAL_RIGHT => self::HORIZONTAL_RIGHT, + self::HORIZONTAL_CENTER => self::HORIZONTAL_CENTER, + self::HORIZONTAL_CENTER_CONTINUOUS => self::HORIZONTAL_CENTER, + self::HORIZONTAL_JUSTIFY => self::HORIZONTAL_JUSTIFY, + //self::HORIZONTAL_FILL => self::HORIZONTAL_FILL, // no reasonable equivalent for fill + self::HORIZONTAL_DISTRIBUTED => self::HORIZONTAL_JUSTIFY, + ]; // Vertical alignment styles const VERTICAL_BOTTOM = 'bottom'; @@ -22,6 +43,45 @@ class Alignment extends Supervisor const VERTICAL_CENTER = 'center'; const VERTICAL_JUSTIFY = 'justify'; const VERTICAL_DISTRIBUTED = 'distributed'; // Excel2007 only + // Vertical alignment CSS + private const VERTICAL_BASELINE = 'baseline'; + private const VERTICAL_MIDDLE = 'middle'; + private const VERTICAL_SUB = 'sub'; + private const VERTICAL_SUPER = 'super'; + private const VERTICAL_TEXT_BOTTOM = 'text-bottom'; + private const VERTICAL_TEXT_TOP = 'text-top'; + + // Mapping for vertical alignment + const VERTICAL_ALIGNMENT_FOR_XLSX = [ + self::VERTICAL_BOTTOM => self::VERTICAL_BOTTOM, + self::VERTICAL_TOP => self::VERTICAL_TOP, + self::VERTICAL_CENTER => self::VERTICAL_CENTER, + self::VERTICAL_JUSTIFY => self::VERTICAL_JUSTIFY, + self::VERTICAL_DISTRIBUTED => self::VERTICAL_DISTRIBUTED, + // css settings that arent't in sync with Excel + self::VERTICAL_BASELINE => self::VERTICAL_BOTTOM, + self::VERTICAL_MIDDLE => self::VERTICAL_CENTER, + self::VERTICAL_SUB => self::VERTICAL_BOTTOM, + self::VERTICAL_SUPER => self::VERTICAL_TOP, + self::VERTICAL_TEXT_BOTTOM => self::VERTICAL_BOTTOM, + self::VERTICAL_TEXT_TOP => self::VERTICAL_TOP, + ]; + + // Mapping for vertical alignment for Html + const VERTICAL_ALIGNMENT_FOR_HTML = [ + self::VERTICAL_BOTTOM => self::VERTICAL_BOTTOM, + self::VERTICAL_TOP => self::VERTICAL_TOP, + self::VERTICAL_CENTER => self::VERTICAL_MIDDLE, + self::VERTICAL_JUSTIFY => self::VERTICAL_MIDDLE, + self::VERTICAL_DISTRIBUTED => self::VERTICAL_MIDDLE, + // css settings that arent't in sync with Excel + self::VERTICAL_BASELINE => self::VERTICAL_BASELINE, + self::VERTICAL_MIDDLE => self::VERTICAL_MIDDLE, + self::VERTICAL_SUB => self::VERTICAL_SUB, + self::VERTICAL_SUPER => self::VERTICAL_SUPER, + self::VERTICAL_TEXT_BOTTOM => self::VERTICAL_TEXT_BOTTOM, + self::VERTICAL_TEXT_TOP => self::VERTICAL_TEXT_TOP, + ]; // Read order const READORDER_CONTEXT = 0; @@ -202,8 +262,9 @@ class Alignment extends Supervisor */ public function setHorizontal(string $horizontalAlignment) { - if ($horizontalAlignment == '') { - $horizontalAlignment = self::HORIZONTAL_GENERAL; + $horizontalAlignment = strtolower($horizontalAlignment); + if ($horizontalAlignment === self::HORIZONTAL_CENTER_CONTINUOUS_LC) { + $horizontalAlignment = self::HORIZONTAL_CENTER_CONTINUOUS; } if ($this->isSupervisor) { @@ -239,9 +300,7 @@ class Alignment extends Supervisor */ public function setVertical($verticalAlignment) { - if ($verticalAlignment == '') { - $verticalAlignment = self::VERTICAL_BOTTOM; - } + $verticalAlignment = strtolower($verticalAlignment); if ($this->isSupervisor) { $styleArray = $this->getStyleArray(['vertical' => $verticalAlignment]); diff --git a/src/PhpSpreadsheet/Writer/Html.php b/src/PhpSpreadsheet/Writer/Html.php index 6a400673..c115cabb 100644 --- a/src/PhpSpreadsheet/Writer/Html.php +++ b/src/PhpSpreadsheet/Writer/Html.php @@ -230,13 +230,6 @@ class Html extends BaseWriter $this->editHtmlCallback = $callback; } - const VALIGN_ARR = [ - Alignment::VERTICAL_BOTTOM => 'bottom', - Alignment::VERTICAL_TOP => 'top', - Alignment::VERTICAL_CENTER => 'middle', - Alignment::VERTICAL_JUSTIFY => 'middle', - ]; - /** * Map VAlign. * @@ -246,17 +239,9 @@ class Html extends BaseWriter */ private function mapVAlign($vAlign) { - return array_key_exists($vAlign, self::VALIGN_ARR) ? self::VALIGN_ARR[$vAlign] : 'baseline'; + return Alignment::VERTICAL_ALIGNMENT_FOR_HTML[$vAlign] ?? ''; } - const HALIGN_ARR = [ - Alignment::HORIZONTAL_LEFT => 'left', - Alignment::HORIZONTAL_RIGHT => 'right', - Alignment::HORIZONTAL_CENTER => 'center', - Alignment::HORIZONTAL_CENTER_CONTINUOUS => 'center', - Alignment::HORIZONTAL_JUSTIFY => 'justify', - ]; - /** * Map HAlign. * @@ -266,7 +251,7 @@ class Html extends BaseWriter */ private function mapHAlign($hAlign) { - return array_key_exists($hAlign, self::HALIGN_ARR) ? self::HALIGN_ARR[$hAlign] : ''; + return Alignment::HORIZONTAL_ALIGNMENT_FOR_HTML[$hAlign] ?? ''; } const BORDER_ARR = [ @@ -988,7 +973,10 @@ class Html extends BaseWriter $css = []; // Create CSS - $css['vertical-align'] = $this->mapVAlign($alignment->getVertical() ?? ''); + $verticalAlign = $this->mapVAlign($alignment->getVertical() ?? ''); + if ($verticalAlign) { + $css['vertical-align'] = $verticalAlign; + } $textAlign = $this->mapHAlign($alignment->getHorizontal() ?? ''); if ($textAlign) { $css['text-align'] = $textAlign; diff --git a/src/PhpSpreadsheet/Writer/Xlsx/Style.php b/src/PhpSpreadsheet/Writer/Xlsx/Style.php index b24b7533..0442c25d 100644 --- a/src/PhpSpreadsheet/Writer/Xlsx/Style.php +++ b/src/PhpSpreadsheet/Writer/Xlsx/Style.php @@ -5,6 +5,7 @@ namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx; use PhpOffice\PhpSpreadsheet\Shared\StringHelper; use PhpOffice\PhpSpreadsheet\Shared\XMLWriter; use PhpOffice\PhpSpreadsheet\Spreadsheet; +use PhpOffice\PhpSpreadsheet\Style\Alignment; use PhpOffice\PhpSpreadsheet\Style\Border; use PhpOffice\PhpSpreadsheet\Style\Borders; use PhpOffice\PhpSpreadsheet\Style\Conditional; @@ -403,8 +404,14 @@ class Style extends WriterPart // alignment $objWriter->startElement('alignment'); - $objWriter->writeAttribute('horizontal', (string) $style->getAlignment()->getHorizontal()); - $objWriter->writeAttribute('vertical', (string) $style->getAlignment()->getVertical()); + $vertical = Alignment::VERTICAL_ALIGNMENT_FOR_XLSX[$style->getAlignment()->getVertical()] ?? ''; + $horizontal = Alignment::HORIZONTAL_ALIGNMENT_FOR_XLSX[$style->getAlignment()->getHorizontal()] ?? ''; + if ($horizontal !== '') { + $objWriter->writeAttribute('horizontal', $horizontal); + } + if ($vertical !== '') { + $objWriter->writeAttribute('vertical', $vertical); + } $textRotation = 0; if ($style->getAlignment()->getTextRotation() >= 0) { @@ -459,11 +466,13 @@ class Style extends WriterPart // alignment $objWriter->startElement('alignment'); - if ($style->getAlignment()->getHorizontal() !== null) { - $objWriter->writeAttribute('horizontal', $style->getAlignment()->getHorizontal()); + $horizontal = Alignment::HORIZONTAL_ALIGNMENT_FOR_XLSX[$style->getAlignment()->getHorizontal()] ?? ''; + if ($horizontal) { + $objWriter->writeAttribute('horizontal', $horizontal); } - if ($style->getAlignment()->getVertical() !== null) { - $objWriter->writeAttribute('vertical', $style->getAlignment()->getVertical()); + $vertical = Alignment::VERTICAL_ALIGNMENT_FOR_XLSX[$style->getAlignment()->getVertical()] ?? ''; + if ($vertical) { + $objWriter->writeAttribute('vertical', $vertical); } if ($style->getAlignment()->getTextRotation() !== null) { diff --git a/tests/PhpSpreadsheetTests/Style/AlignmentMiddleTest.php b/tests/PhpSpreadsheetTests/Style/AlignmentMiddleTest.php new file mode 100644 index 00000000..1d260a6e --- /dev/null +++ b/tests/PhpSpreadsheetTests/Style/AlignmentMiddleTest.php @@ -0,0 +1,87 @@ +spreadsheet !== null) { + $this->spreadsheet->disconnectWorksheets(); + $this->spreadsheet = null; + } + if ($this->outputFileName !== '') { + unlink($this->outputFileName); + $this->outputFileName = ''; + } + } + + public function testCenterWriteHtml(): void + { + // Html Writer changes vertical align center to middle + $this->spreadsheet = new Spreadsheet(); + $sheet = $this->spreadsheet->getActiveSheet(); + $sheet->getCell('A1')->setValue('Cell1'); + $sheet->getStyle('A1') + ->getAlignment() + ->setVertical(Alignment::VERTICAL_CENTER); + $writer = new HTML($this->spreadsheet); + $html = $writer->generateHtmlAll(); + self::assertStringContainsString('vertical-align:middle', $html); + self::assertStringNotContainsString('vertical-align:center', $html); + } + + public function testCenterWriteXlsx(): void + { + // Xlsx Writer uses vertical align center unchanged + $this->spreadsheet = new Spreadsheet(); + $sheet = $this->spreadsheet->getActiveSheet(); + $sheet->getCell('A1')->setValue('Cell1'); + $sheet->getStyle('A1') + ->getAlignment() + ->setVertical(Alignment::VERTICAL_CENTER); + $this->outputFileName = File::temporaryFilename(); + $writer = new Xlsx($this->spreadsheet); + $writer->save($this->outputFileName); + $zip = new ZipArchive(); + $zip->open($this->outputFileName); + $html = $zip->getFromName('xl/styles.xml'); + $zip->close(); + self::assertStringContainsString('vertical="center"', $html); + self::assertStringNotContainsString('vertical="middle"', $html); + } + + public function testCenterWriteXlsx2(): void + { + // Xlsx Writer changes vertical align middle to center + $this->spreadsheet = new Spreadsheet(); + $sheet = $this->spreadsheet->getActiveSheet(); + $sheet->getCell('A1')->setValue('Cell1'); + $sheet->getStyle('A1') + ->getAlignment() + ->setVertical('middle'); + $this->outputFileName = File::temporaryFilename(); + $writer = new Xlsx($this->spreadsheet); + $writer->save($this->outputFileName); + $zip = new ZipArchive(); + $zip->open($this->outputFileName); + $html = $zip->getFromName('xl/styles.xml'); + $zip->close(); + self::assertStringContainsString('vertical="center"', $html); + self::assertStringNotContainsString('vertical="middle"', $html); + } +} diff --git a/tests/PhpSpreadsheetTests/Style/AlignmentTest.php b/tests/PhpSpreadsheetTests/Style/AlignmentTest.php index d10e3211..6f50ce22 100644 --- a/tests/PhpSpreadsheetTests/Style/AlignmentTest.php +++ b/tests/PhpSpreadsheetTests/Style/AlignmentTest.php @@ -9,10 +9,21 @@ use PHPUnit\Framework\TestCase; class AlignmentTest extends TestCase { + /** @var ?Spreadsheet */ + private $spreadsheet; + + protected function tearDown(): void + { + if ($this->spreadsheet !== null) { + $this->spreadsheet->disconnectWorksheets(); + $this->spreadsheet = null; + } + } + public function testAlignment(): void { - $spreadsheet = new Spreadsheet(); - $sheet = $spreadsheet->getActiveSheet(); + $this->spreadsheet = new Spreadsheet(); + $sheet = $this->spreadsheet->getActiveSheet(); $cell1 = $sheet->getCell('A1'); $cell1->setValue('Cell1'); $cell1->getStyle()->getAlignment()->setTextRotation(45); @@ -31,8 +42,8 @@ class AlignmentTest extends TestCase public function testRotationTooHigh(): void { $this->expectException(PhpSpreadsheetException::class); - $spreadsheet = new Spreadsheet(); - $sheet = $spreadsheet->getActiveSheet(); + $this->spreadsheet = new Spreadsheet(); + $sheet = $this->spreadsheet->getActiveSheet(); $cell1 = $sheet->getCell('A1'); $cell1->setValue('Cell1'); $cell1->getStyle()->getAlignment()->setTextRotation(91); @@ -42,8 +53,8 @@ class AlignmentTest extends TestCase public function testRotationTooLow(): void { $this->expectException(PhpSpreadsheetException::class); - $spreadsheet = new Spreadsheet(); - $sheet = $spreadsheet->getActiveSheet(); + $this->spreadsheet = new Spreadsheet(); + $sheet = $this->spreadsheet->getActiveSheet(); $cell1 = $sheet->getCell('A1'); $cell1->setValue('Cell1'); $cell1->getStyle()->getAlignment()->setTextRotation(-91); @@ -52,8 +63,8 @@ class AlignmentTest extends TestCase public function testHorizontal(): void { - $spreadsheet = new Spreadsheet(); - $sheet = $spreadsheet->getActiveSheet(); + $this->spreadsheet = new Spreadsheet(); + $sheet = $this->spreadsheet->getActiveSheet(); $cell1 = $sheet->getCell('A1'); $cell1->setValue('X'); $cell1->getStyle()->getAlignment()->setHorizontal(Alignment::HORIZONTAL_LEFT)->setIndent(1); @@ -74,8 +85,8 @@ class AlignmentTest extends TestCase public function testReadOrder(): void { - $spreadsheet = new Spreadsheet(); - $sheet = $spreadsheet->getActiveSheet(); + $this->spreadsheet = new Spreadsheet(); + $sheet = $this->spreadsheet->getActiveSheet(); $cell1 = $sheet->getCell('A1'); $cell1->setValue('ABC'); $cell1->getStyle()->getAlignment()->setReadOrder(0); From b5f70de61d3ebe5ee09220e9c7f47d8a60f976a4 Mon Sep 17 00:00:00 2001 From: oleibman <10341515+oleibman@users.noreply.github.com> Date: Fri, 9 Sep 2022 07:56:11 -0700 Subject: [PATCH 2/7] More Scrutinizer Catch Up (#3050) * More Scrutinizer Catch Up Continue the work of PR #3043 by attending to the 12 remaining 'new' issues. * Php 8.1 Problem One new null-instead-of-string problem. --- phpstan-baseline.neon | 15 ------- .../Chart/33_Chart_create_line_dateaxis.php | 22 +++++----- src/PhpSpreadsheet/Chart/Axis.php | 2 +- src/PhpSpreadsheet/Chart/Chart.php | 6 ++- src/PhpSpreadsheet/Reader/Xlsx.php | 13 +++--- src/PhpSpreadsheet/Reader/Xlsx/AutoFilter.php | 12 +++--- src/PhpSpreadsheet/Reader/Xlsx/Chart.php | 40 +++++++++---------- src/PhpSpreadsheet/Worksheet/PageSetup.php | 9 +++-- src/PhpSpreadsheet/Worksheet/Worksheet.php | 2 +- src/PhpSpreadsheet/Writer/Html.php | 29 +++++++------- src/PhpSpreadsheet/Writer/Xls/Worksheet.php | 4 +- src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php | 8 ++-- .../Reader/Xlsx/AutoFilter2Test.php | 1 + tests/PhpSpreadsheetTests/RichTextTest.php | 3 -- 14 files changed, 78 insertions(+), 88 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index cc2eaa3d..3e2ccfc1 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -2590,21 +2590,6 @@ parameters: count: 1 path: src/PhpSpreadsheet/Worksheet/PageSetup.php - - - message: "#^Parameter \\#1 \\$value of method PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\PageSetup\\:\\:setFirstPageNumber\\(\\) expects int, null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Worksheet/PageSetup.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\PageSetup\\:\\:\\$pageOrder has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Worksheet/PageSetup.php - - - - message: "#^Strict comparison using \\=\\=\\= between int\\ and null will always evaluate to false\\.$#" - count: 1 - path: src/PhpSpreadsheet/Worksheet/PageSetup.php - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\SheetView\\:\\:\\$sheetViewTypes has no type specified\\.$#" count: 1 diff --git a/samples/Chart/33_Chart_create_line_dateaxis.php b/samples/Chart/33_Chart_create_line_dateaxis.php index 1a47e5aa..413866e2 100644 --- a/samples/Chart/33_Chart_create_line_dateaxis.php +++ b/samples/Chart/33_Chart_create_line_dateaxis.php @@ -101,10 +101,10 @@ $dataSeriesValues = [ // marker details $dataSeriesValues[0] ->getMarkerFillColor() - ->setColorProperties('0070C0', null, ChartColor::EXCEL_COLOR_TYPE_ARGB); + ->setColorProperties('0070C0', null, ChartColor::EXCEL_COLOR_TYPE_RGB); $dataSeriesValues[0] ->getMarkerBorderColor() - ->setColorProperties('002060', null, ChartColor::EXCEL_COLOR_TYPE_ARGB); + ->setColorProperties('002060', null, ChartColor::EXCEL_COLOR_TYPE_RGB); // line details - dashed, smooth line (Bezier) with arrows, 40% transparent $dataSeriesValues[0] @@ -129,18 +129,18 @@ $dataSeriesValues[1] // square marker border color ->setColorProperties('accent6', 3, ChartColor::EXCEL_COLOR_TYPE_SCHEME); $dataSeriesValues[1] // square marker fill color ->getMarkerFillColor() - ->setColorProperties('0FFF00', null, ChartColor::EXCEL_COLOR_TYPE_ARGB); + ->setColorProperties('0FFF00', null, ChartColor::EXCEL_COLOR_TYPE_RGB); $dataSeriesValues[1] ->setScatterLines(true) ->setSmoothLine(false) - ->setLineColorProperties('FF0000', 80, ChartColor::EXCEL_COLOR_TYPE_ARGB); + ->setLineColorProperties('FF0000', 80, ChartColor::EXCEL_COLOR_TYPE_RGB); $dataSeriesValues[1]->setLineWidth(2.0); // series 3 - metric3, markers, no line $dataSeriesValues[2] // triangle? fill //->setPointMarker('triangle') // let Excel choose shape, which is predicted to be a triangle ->getMarkerFillColor() - ->setColorProperties('FFFF00', null, ChartColor::EXCEL_COLOR_TYPE_ARGB); + ->setColorProperties('FFFF00', null, ChartColor::EXCEL_COLOR_TYPE_RGB); $dataSeriesValues[2] // triangle border ->getMarkerBorderColor() ->setColorProperties('accent4', null, ChartColor::EXCEL_COLOR_TYPE_SCHEME); @@ -239,7 +239,7 @@ $dataSeriesValues[0] ->setScatterlines(false); // disable connecting lines $dataSeriesValues[0] ->getMarkerFillColor() - ->setColorProperties('FFFF00', null, ChartColor::EXCEL_COLOR_TYPE_ARGB); + ->setColorProperties('FFFF00', null, ChartColor::EXCEL_COLOR_TYPE_RGB); $dataSeriesValues[0] ->getMarkerBorderColor() ->setColorProperties('accent4', null, ChartColor::EXCEL_COLOR_TYPE_SCHEME); @@ -326,7 +326,7 @@ $chart = new Chart( // Set the position of the chart in the chart sheet below the first chart $chart->setTopLeftPosition('A13'); $chart->setBottomRightPosition('P25'); -$chart->setRoundedCorners('true'); // Rounded corners in Chart Outline +$chart->setRoundedCorners(true); // Rounded corners in Chart Outline // Add the chart to the worksheet $chartSheet $chartSheet->addChart($chart); @@ -350,8 +350,8 @@ function dateRange(int $nrows, Spreadsheet $wrkbk): array $startDate = DateTime::createFromFormat('Y-m-d', $startDateStr); // php date obj // get date of first day of the quarter of the start date - $startMonth = $startDate->format('n'); // suppress leading zero - $startYr = $startDate->format('Y'); + $startMonth = (int) $startDate->format('n'); // suppress leading zero + $startYr = (int) $startDate->format('Y'); $qtr = intdiv($startMonth, 3) + (($startMonth % 3 > 0) ? 1 : 0); $qtrStartMonth = sprintf('%02d', 1 + (($qtr - 1) * 3)); $qtrStartStr = "$startYr-$qtrStartMonth-01"; @@ -360,8 +360,8 @@ function dateRange(int $nrows, Spreadsheet $wrkbk): array // end the xaxis at the end of the quarter of the last date $lastDateStr = $dataSheet->getCellByColumnAndRow(2, $nrows + 1)->getValue(); $lastDate = DateTime::createFromFormat('Y-m-d', $lastDateStr); - $lastMonth = $lastDate->format('n'); - $lastYr = $lastDate->format('Y'); + $lastMonth = (int) $lastDate->format('n'); + $lastYr = (int) $lastDate->format('Y'); $qtr = intdiv($lastMonth, 3) + (($lastMonth % 3 > 0) ? 1 : 0); $qtrEndMonth = 3 + (($qtr - 1) * 3); $lastDOM = cal_days_in_month(CAL_GREGORIAN, $qtrEndMonth, $lastYr); diff --git a/src/PhpSpreadsheet/Chart/Axis.php b/src/PhpSpreadsheet/Chart/Axis.php index 3ac5c3cd..9ebb081f 100644 --- a/src/PhpSpreadsheet/Chart/Axis.php +++ b/src/PhpSpreadsheet/Chart/Axis.php @@ -219,7 +219,7 @@ class Axis extends Properties * @param ?int $alpha * @param ?string $AlphaType */ - public function setFillParameters($color, $alpha = null, $AlphaType = self::EXCEL_COLOR_TYPE_ARGB): void + public function setFillParameters($color, $alpha = null, $AlphaType = ChartColor::EXCEL_COLOR_TYPE_RGB): void { $this->fillColor->setColorProperties($color, $alpha, $AlphaType); } diff --git a/src/PhpSpreadsheet/Chart/Chart.php b/src/PhpSpreadsheet/Chart/Chart.php index 036338c6..f41d7883 100644 --- a/src/PhpSpreadsheet/Chart/Chart.php +++ b/src/PhpSpreadsheet/Chart/Chart.php @@ -774,9 +774,11 @@ class Chart return $this->roundedCorners; } - public function setRoundedCorners(bool $roundedCorners): self + public function setRoundedCorners(?bool $roundedCorners): self { - $this->roundedCorners = $roundedCorners; + if ($roundedCorners !== null) { + $this->roundedCorners = $roundedCorners; + } return $this; } diff --git a/src/PhpSpreadsheet/Reader/Xlsx.php b/src/PhpSpreadsheet/Reader/Xlsx.php index 244baddd..fc38375a 100644 --- a/src/PhpSpreadsheet/Reader/Xlsx.php +++ b/src/PhpSpreadsheet/Reader/Xlsx.php @@ -306,22 +306,25 @@ class Xlsx extends BaseReader return (bool) $c->v; } - private static function castToError(SimpleXMLElement $c): ?string + private static function castToError(?SimpleXMLElement $c): ?string { - return isset($c->v) ? (string) $c->v : null; + return isset($c, $c->v) ? (string) $c->v : null; } - private static function castToString(SimpleXMLElement $c): ?string + private static function castToString(?SimpleXMLElement $c): ?string { - return isset($c->v) ? (string) $c->v : null; + return isset($c, $c->v) ? (string) $c->v : null; } /** * @param mixed $value * @param mixed $calculatedValue */ - private function castToFormula(SimpleXMLElement $c, string $r, string &$cellDataType, &$value, &$calculatedValue, array &$sharedFormulas, string $castBaseType): void + private function castToFormula(?SimpleXMLElement $c, string $r, string &$cellDataType, &$value, &$calculatedValue, array &$sharedFormulas, string $castBaseType): void { + if ($c === null) { + return; + } $attr = $c->f->attributes(); $cellDataType = 'f'; $value = "={$c->f}"; diff --git a/src/PhpSpreadsheet/Reader/Xlsx/AutoFilter.php b/src/PhpSpreadsheet/Reader/Xlsx/AutoFilter.php index 623c6691..39328adb 100644 --- a/src/PhpSpreadsheet/Reader/Xlsx/AutoFilter.php +++ b/src/PhpSpreadsheet/Reader/Xlsx/AutoFilter.php @@ -85,9 +85,9 @@ class AutoFilter } } - private function readCustomAutoFilter(SimpleXMLElement $filterColumn, Column $column): void + private function readCustomAutoFilter(?SimpleXMLElement $filterColumn, Column $column): void { - if ($filterColumn->customFilters) { + if (isset($filterColumn, $filterColumn->customFilters)) { $column->setFilterType(Column::AUTOFILTER_FILTERTYPE_CUSTOMFILTER); $customFilters = $filterColumn->customFilters; // Custom filters can an AND or an OR join; @@ -104,9 +104,9 @@ class AutoFilter } } - private function readDynamicAutoFilter(SimpleXMLElement $filterColumn, Column $column): void + private function readDynamicAutoFilter(?SimpleXMLElement $filterColumn, Column $column): void { - if ($filterColumn->dynamicFilter) { + if (isset($filterColumn, $filterColumn->dynamicFilter)) { $column->setFilterType(Column::AUTOFILTER_FILTERTYPE_DYNAMICFILTER); // We should only ever have one dynamic filter foreach ($filterColumn->dynamicFilter as $filterRule) { @@ -126,9 +126,9 @@ class AutoFilter } } - private function readTopTenAutoFilter(SimpleXMLElement $filterColumn, Column $column): void + private function readTopTenAutoFilter(?SimpleXMLElement $filterColumn, Column $column): void { - if ($filterColumn->top10) { + if (isset($filterColumn, $filterColumn->top10)) { $column->setFilterType(Column::AUTOFILTER_FILTERTYPE_TOPTENFILTER); // We should only ever have one top10 filter foreach ($filterColumn->top10 as $filterRule) { diff --git a/src/PhpSpreadsheet/Reader/Xlsx/Chart.php b/src/PhpSpreadsheet/Reader/Xlsx/Chart.php index 507c8f5b..6bc6d7c5 100644 --- a/src/PhpSpreadsheet/Reader/Xlsx/Chart.php +++ b/src/PhpSpreadsheet/Reader/Xlsx/Chart.php @@ -11,7 +11,7 @@ use PhpOffice\PhpSpreadsheet\Chart\GridLines; use PhpOffice\PhpSpreadsheet\Chart\Layout; use PhpOffice\PhpSpreadsheet\Chart\Legend; use PhpOffice\PhpSpreadsheet\Chart\PlotArea; -use PhpOffice\PhpSpreadsheet\Chart\Properties; +use PhpOffice\PhpSpreadsheet\Chart\Properties as ChartProperties; use PhpOffice\PhpSpreadsheet\Chart\Title; use PhpOffice\PhpSpreadsheet\Chart\TrendLine; use PhpOffice\PhpSpreadsheet\RichText\RichText; @@ -113,6 +113,7 @@ class Chart $plotSeries = $plotAttributes = []; $catAxRead = false; $plotNoFill = false; + /** @var SimpleXMLElement $chartDetail */ foreach ($chartDetails as $chartDetailKey => $chartDetail) { switch ($chartDetailKey) { case 'spPr': @@ -121,17 +122,18 @@ class Chart $plotNoFill = true; } if (isset($possibleNoFill->gradFill->gsLst)) { + /** @var SimpleXMLElement $gradient */ foreach ($possibleNoFill->gradFill->gsLst->gs as $gradient) { /** @var float */ $pos = self::getAttribute($gradient, 'pos', 'float'); $gradientArray[] = [ - $pos / Properties::PERCENTAGE_MULTIPLIER, + $pos / ChartProperties::PERCENTAGE_MULTIPLIER, new ChartColor($this->readColor($gradient)), ]; } } if (isset($possibleNoFill->gradFill->lin)) { - $gradientLin = Properties::XmlToAngle((string) self::getAttribute($possibleNoFill->gradFill->lin, 'ang', 'string')); + $gradientLin = ChartProperties::XmlToAngle((string) self::getAttribute($possibleNoFill->gradFill->lin, 'ang', 'string')); } break; @@ -464,12 +466,13 @@ class Chart $pointSize = null; $noFill = false; $bubble3D = false; - $dPtColors = []; + $dptColors = []; $markerFillColor = null; $markerBorderColor = null; $lineStyle = null; $labelLayout = null; $trendLines = []; + /** @var SimpleXMLElement $seriesDetail */ foreach ($seriesDetails as $seriesKey => $seriesDetail) { switch ($seriesKey) { case 'idx': @@ -487,7 +490,6 @@ class Chart break; case 'spPr': $children = $seriesDetail->children($this->aNamespace); - $ln = $children->ln; if (isset($children->ln)) { $ln = $children->ln; if (is_countable($ln->noFill) && count($ln->noFill) === 1) { @@ -1161,7 +1163,7 @@ class Chart } } - private function readEffects(SimpleXMLElement $chartDetail, ?Properties $chartObject): void + private function readEffects(SimpleXMLElement $chartDetail, ?ChartProperties $chartObject): void { if (!isset($chartObject, $chartDetail->spPr)) { return; @@ -1169,7 +1171,7 @@ class Chart $sppr = $chartDetail->spPr->children($this->aNamespace); if (isset($sppr->effectLst->glow)) { - $axisGlowSize = (float) self::getAttribute($sppr->effectLst->glow, 'rad', 'integer') / Properties::POINTS_WIDTH_MULTIPLIER; + $axisGlowSize = (float) self::getAttribute($sppr->effectLst->glow, 'rad', 'integer') / ChartProperties::POINTS_WIDTH_MULTIPLIER; if ($axisGlowSize != 0.0) { $colorArray = $this->readColor($sppr->effectLst->glow); $chartObject->setGlowProperties($axisGlowSize, $colorArray['value'], $colorArray['alpha'], $colorArray['type']); @@ -1180,7 +1182,7 @@ class Chart /** @var string */ $softEdgeSize = self::getAttribute($sppr->effectLst->softEdge, 'rad', 'string'); if (is_numeric($softEdgeSize)) { - $chartObject->setSoftEdges((float) Properties::xmlToPoints($softEdgeSize)); + $chartObject->setSoftEdges((float) ChartProperties::xmlToPoints($softEdgeSize)); } } @@ -1195,20 +1197,20 @@ class Chart if ($type !== '') { /** @var string */ $blur = self::getAttribute($sppr->effectLst->$type, 'blurRad', 'string'); - $blur = is_numeric($blur) ? Properties::xmlToPoints($blur) : null; + $blur = is_numeric($blur) ? ChartProperties::xmlToPoints($blur) : null; /** @var string */ $dist = self::getAttribute($sppr->effectLst->$type, 'dist', 'string'); - $dist = is_numeric($dist) ? Properties::xmlToPoints($dist) : null; + $dist = is_numeric($dist) ? ChartProperties::xmlToPoints($dist) : null; /** @var string */ $direction = self::getAttribute($sppr->effectLst->$type, 'dir', 'string'); - $direction = is_numeric($direction) ? Properties::xmlToAngle($direction) : null; + $direction = is_numeric($direction) ? ChartProperties::xmlToAngle($direction) : null; $algn = self::getAttribute($sppr->effectLst->$type, 'algn', 'string'); $rot = self::getAttribute($sppr->effectLst->$type, 'rotWithShape', 'string'); $size = []; foreach (['sx', 'sy'] as $sizeType) { $sizeValue = self::getAttribute($sppr->effectLst->$type, $sizeType, 'string'); if (is_numeric($sizeValue)) { - $size[$sizeType] = Properties::xmlToTenthOfPercent((string) $sizeValue); + $size[$sizeType] = ChartProperties::xmlToTenthOfPercent((string) $sizeValue); } else { $size[$sizeType] = null; } @@ -1216,7 +1218,7 @@ class Chart foreach (['kx', 'ky'] as $sizeType) { $sizeValue = self::getAttribute($sppr->effectLst->$type, $sizeType, 'string'); if (is_numeric($sizeValue)) { - $size[$sizeType] = Properties::xmlToAngle((string) $sizeValue); + $size[$sizeType] = ChartProperties::xmlToAngle((string) $sizeValue); } else { $size[$sizeType] = null; } @@ -1273,7 +1275,7 @@ class Chart return $result; } - private function readLineStyle(SimpleXMLElement $chartDetail, ?Properties $chartObject): void + private function readLineStyle(SimpleXMLElement $chartDetail, ?ChartProperties $chartObject): void { if (!isset($chartObject, $chartDetail->spPr)) { return; @@ -1287,7 +1289,7 @@ class Chart /** @var string */ $lineWidthTemp = self::getAttribute($sppr->ln, 'w', 'string'); if (is_numeric($lineWidthTemp)) { - $lineWidth = Properties::xmlToPoints($lineWidthTemp); + $lineWidth = ChartProperties::xmlToPoints($lineWidthTemp); } /** @var string */ $compoundType = self::getAttribute($sppr->ln, 'cmpd', 'string'); @@ -1296,15 +1298,13 @@ class Chart /** @var string */ $capType = self::getAttribute($sppr->ln, 'cap', 'string'); if (isset($sppr->ln->miter)) { - $joinType = Properties::LINE_STYLE_JOIN_MITER; + $joinType = ChartProperties::LINE_STYLE_JOIN_MITER; } elseif (isset($sppr->ln->bevel)) { - $joinType = Properties::LINE_STYLE_JOIN_BEVEL; + $joinType = ChartProperties::LINE_STYLE_JOIN_BEVEL; } else { $joinType = ''; } - $headArrowType = ''; $headArrowSize = ''; - $endArrowType = ''; $endArrowSize = ''; /** @var string */ $headArrowType = self::getAttribute($sppr->ln->headEnd, 'type', 'string'); @@ -1403,7 +1403,7 @@ class Chart /** @var string */ $textRotation = self::getAttribute($children->bodyPr, 'rot', 'string'); if (is_numeric($textRotation)) { - $whichAxis->setAxisOption('textRotation', (string) Properties::xmlToAngle($textRotation)); + $whichAxis->setAxisOption('textRotation', (string) ChartProperties::xmlToAngle($textRotation)); } } } diff --git a/src/PhpSpreadsheet/Worksheet/PageSetup.php b/src/PhpSpreadsheet/Worksheet/PageSetup.php index c23bfc59..4bdc2d4c 100644 --- a/src/PhpSpreadsheet/Worksheet/PageSetup.php +++ b/src/PhpSpreadsheet/Worksheet/PageSetup.php @@ -259,10 +259,11 @@ class PageSetup /** * First page number. * - * @var int + * @var ?int */ private $firstPageNumber; + /** @var string */ private $pageOrder = self::PAGEORDER_DOWN_THEN_OVER; /** @@ -375,7 +376,7 @@ class PageSetup { // Microsoft Office Excel 2007 only allows setting a scale between 10 and 400 via the user interface, // but it is apparently still able to handle any scale >= 0, where 0 results in 100 - if (($scale >= 0) || $scale === null) { + if ($scale === null || $scale >= 0) { $this->scale = $scale; if ($update) { $this->fitToPage = false; @@ -845,7 +846,7 @@ class PageSetup /** * Get first page number. * - * @return int + * @return ?int */ public function getFirstPageNumber() { @@ -855,7 +856,7 @@ class PageSetup /** * Set first page number. * - * @param int $value + * @param ?int $value * * @return $this */ diff --git a/src/PhpSpreadsheet/Worksheet/Worksheet.php b/src/PhpSpreadsheet/Worksheet/Worksheet.php index 413ec9ef..d13d4141 100644 --- a/src/PhpSpreadsheet/Worksheet/Worksheet.php +++ b/src/PhpSpreadsheet/Worksheet/Worksheet.php @@ -1359,7 +1359,7 @@ class Worksheet implements IComparable if ($rowDimension !== null && $rowDimension->getXfIndex() > 0) { // then there is a row dimension with explicit style, assign it to the cell - $cell->setXfIndex($rowDimension->getXfIndex()); + $cell->setXfIndex(/** @scrutinizer ignore-type */ $rowDimension->getXfIndex()); } elseif ($columnDimension !== null && $columnDimension->getXfIndex() > 0) { // then there is a column dimension, assign it to the cell $cell->setXfIndex($columnDimension->getXfIndex()); diff --git a/src/PhpSpreadsheet/Writer/Html.php b/src/PhpSpreadsheet/Writer/Html.php index c115cabb..fca5ee89 100644 --- a/src/PhpSpreadsheet/Writer/Html.php +++ b/src/PhpSpreadsheet/Writer/Html.php @@ -24,6 +24,7 @@ use PhpOffice\PhpSpreadsheet\Style\NumberFormat; use PhpOffice\PhpSpreadsheet\Style\Style; use PhpOffice\PhpSpreadsheet\Worksheet\Drawing; use PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing; +use PhpOffice\PhpSpreadsheet\Worksheet\PageSetup; use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet; class Html extends BaseWriter @@ -1277,23 +1278,22 @@ class Html extends BaseWriter } } - private function generateRowCellDataValue(Worksheet $worksheet, Cell $cell, ?string &$cellData): void + private function generateRowCellDataValue(Worksheet $worksheet, Cell $cell, string &$cellData): void { if ($cell->getValue() instanceof RichText) { $this->generateRowCellDataValueRich($cell, $cellData); } else { $origData = $this->preCalculateFormulas ? $cell->getCalculatedValue() : $cell->getValue(); $formatCode = $worksheet->getParent()->getCellXfByIndex($cell->getXfIndex())->getNumberFormat()->getFormatCode(); - if ($formatCode !== null) { - $cellData = NumberFormat::toFormattedString( - $origData, - $formatCode, - [$this, 'formatColor'] - ); - } + + $cellData = NumberFormat::toFormattedString( + $origData ?? '', + $formatCode ?? NumberFormat::FORMAT_GENERAL, + [$this, 'formatColor'] + ); if ($cellData === $origData) { - $cellData = htmlspecialchars($cellData ?? '', Settings::htmlEntityFlags()); + $cellData = htmlspecialchars($cellData, Settings::htmlEntityFlags()); } if ($worksheet->getParent()->getCellXfByIndex($cell->getXfIndex())->getFont()->getSuperscript()) { $cellData = '' . $cellData . ''; @@ -1477,8 +1477,8 @@ class Html extends BaseWriter && $this->isSpannedCell[$worksheet->getParent()->getIndex($worksheet)][$row + 1][$colNum]); // Colspan and Rowspan - $colspan = 1; - $rowspan = 1; + $colSpan = 1; + $rowSpan = 1; if (isset($this->isBaseCell[$worksheet->getParent()->getIndex($worksheet)][$row + 1][$colNum])) { $spans = $this->isBaseCell[$worksheet->getParent()->getIndex($worksheet)][$row + 1][$colNum]; $rowSpan = $spans['rowspan']; @@ -1791,7 +1791,8 @@ class Html extends BaseWriter public function getOrientation(): ?string { - return null; + // Expect Pdf classes to override this method. + return $this->isPdf ? PageSetup::ORIENTATION_PORTRAIT : null; } /** @@ -1830,9 +1831,9 @@ class Html extends BaseWriter $bottom = StringHelper::FormatNumber($worksheet->getPageMargins()->getBottom()) . 'in; '; $htmlPage .= 'margin-bottom: ' . $bottom; $orientation = $this->getOrientation() ?? $worksheet->getPageSetup()->getOrientation(); - if ($orientation === \PhpOffice\PhpSpreadsheet\Worksheet\PageSetup::ORIENTATION_LANDSCAPE) { + if ($orientation === PageSetup::ORIENTATION_LANDSCAPE) { $htmlPage .= 'size: landscape; '; - } elseif ($orientation === \PhpOffice\PhpSpreadsheet\Worksheet\PageSetup::ORIENTATION_PORTRAIT) { + } elseif ($orientation === PageSetup::ORIENTATION_PORTRAIT) { $htmlPage .= 'size: portrait; '; } $htmlPage .= '}' . PHP_EOL; diff --git a/src/PhpSpreadsheet/Writer/Xls/Worksheet.php b/src/PhpSpreadsheet/Writer/Xls/Worksheet.php index 8f09af69..847d772a 100644 --- a/src/PhpSpreadsheet/Writer/Xls/Worksheet.php +++ b/src/PhpSpreadsheet/Writer/Xls/Worksheet.php @@ -465,7 +465,7 @@ class Worksheet extends BIFFwriter switch ($calctype) { case 'integer': case 'double': - $this->writeNumber($row, $column, $calculatedValue, $xfIndex); + $this->writeNumber($row, $column, (float) $calculatedValue, $xfIndex); break; case 'string': @@ -473,7 +473,7 @@ class Worksheet extends BIFFwriter break; case 'boolean': - $this->writeBoolErr($row, $column, $calculatedValue, 0, $xfIndex); + $this->writeBoolErr($row, $column, (int) $calculatedValue, 0, $xfIndex); break; default: diff --git a/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php b/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php index 5680281f..1aa4f1ca 100644 --- a/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php +++ b/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php @@ -503,7 +503,7 @@ class Worksheet extends WriterPart private static function writeTimePeriodCondElements(XMLWriter $objWriter, Conditional $conditional, string $cellCoordinate): void { $txt = $conditional->getText(); - if ($txt !== null) { + if (!empty($txt)) { $objWriter->writeAttribute('timePeriod', $txt); if (empty($conditional->getConditions())) { if ($conditional->getOperatorType() == Conditional::TIMEPERIOD_TODAY) { @@ -536,7 +536,7 @@ class Worksheet extends WriterPart private static function writeTextCondElements(XMLWriter $objWriter, Conditional $conditional, string $cellCoordinate): void { $txt = $conditional->getText(); - if ($txt !== null) { + if (!empty($txt)) { $objWriter->writeAttribute('text', $txt); if (empty($conditional->getConditions())) { if ($conditional->getOperatorType() == Conditional::OPERATOR_CONTAINSTEXT) { @@ -1034,7 +1034,7 @@ class Worksheet extends WriterPart } else { $objWriter->writeAttribute('fitToWidth', '0'); } - if ($worksheet->getPageSetup()->getFirstPageNumber() !== null) { + if (!empty($worksheet->getPageSetup()->getFirstPageNumber())) { $objWriter->writeAttribute('firstPageNumber', (string) $worksheet->getPageSetup()->getFirstPageNumber()); $objWriter->writeAttribute('useFirstPageNumber', '1'); } @@ -1228,7 +1228,7 @@ class Worksheet extends WriterPart StringHelper::controlCharacterPHP2OOXML(htmlspecialchars($cellValue, Settings::htmlEntityFlags())) ); $objWriter->endElement(); - } elseif ($cellValue instanceof RichText) { + } else { $objWriter->startElement('is'); $this->getParentWriter()->getWriterPartstringtable()->writeRichText($objWriter, $cellValue); $objWriter->endElement(); diff --git a/tests/PhpSpreadsheetTests/Reader/Xlsx/AutoFilter2Test.php b/tests/PhpSpreadsheetTests/Reader/Xlsx/AutoFilter2Test.php index 0bb9f130..57c09de5 100644 --- a/tests/PhpSpreadsheetTests/Reader/Xlsx/AutoFilter2Test.php +++ b/tests/PhpSpreadsheetTests/Reader/Xlsx/AutoFilter2Test.php @@ -70,6 +70,7 @@ class AutoFilter2Test extends TestCase self::assertCount(1, $columns); $column = $columns['A'] ?? null; self::assertNotNull($column); + /** @scrutinizer ignore-call */ $ruleset = $column->getRules(); self::assertCount(1, $ruleset); $rule = $ruleset[0]; diff --git a/tests/PhpSpreadsheetTests/RichTextTest.php b/tests/PhpSpreadsheetTests/RichTextTest.php index 49878529..e6f55514 100644 --- a/tests/PhpSpreadsheetTests/RichTextTest.php +++ b/tests/PhpSpreadsheetTests/RichTextTest.php @@ -28,9 +28,6 @@ class RichTextTest extends TestCase public function testTextElements(): void { $element1 = new TextElement('A'); - if ($element1->getFont() !== null) { - self::fail('Expected font to be null'); - } $element2 = new TextElement('B'); $element3 = new TextElement('C'); $richText = new RichText(); From 2fe66d097fc4f5a310d5e6e387f37011793007bb Mon Sep 17 00:00:00 2001 From: oleibman <10341515+oleibman@users.noreply.github.com> Date: Mon, 12 Sep 2022 08:23:43 -0700 Subject: [PATCH 3/7] Upgrade mitoteam/jpgraph for Php8.2 Usage (#3058) They just released a Php8.2-compatible version. We should use that version going forward. Some tests had been disabled in 8.2 due to the problems which the new release fixes; these are now restored. --- composer.json | 2 +- composer.lock | 23 +++++++++++-------- .../PhpSpreadsheetTests/Helper/SampleTest.php | 6 ----- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/composer.json b/composer.json index 46ee56b9..6835b05b 100644 --- a/composer.json +++ b/composer.json @@ -81,7 +81,7 @@ "dealerdirect/phpcodesniffer-composer-installer": "dev-master", "dompdf/dompdf": "^1.0 || ^2.0", "friendsofphp/php-cs-fixer": "^3.2", - "mitoteam/jpgraph": "^10.1", + "mitoteam/jpgraph": "10.2.2", "mpdf/mpdf": "8.1.1", "phpcompatibility/php-compatibility": "^9.3", "phpstan/phpstan": "^1.1", diff --git a/composer.lock b/composer.lock index 37e2dfa8..4097420d 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "dd19bb54ddc39f5b24f564818cb46c7e", + "content-hash": "8512207f173cb137bc2085b7fdf698bc", "packages": [ { "name": "ezyang/htmlpurifier", @@ -1342,20 +1342,23 @@ }, { "name": "mitoteam/jpgraph", - "version": "10.1.3", + "version": "10.2.2", "source": { "type": "git", "url": "https://github.com/mitoteam/jpgraph.git", - "reference": "425a2a0f0c97a28fe0aca60a4384ce85880e438a" + "reference": "6d87fc342afaf8a9a898a3122b5f0f34fc82c4cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mitoteam/jpgraph/zipball/425a2a0f0c97a28fe0aca60a4384ce85880e438a", - "reference": "425a2a0f0c97a28fe0aca60a4384ce85880e438a", + "url": "https://api.github.com/repos/mitoteam/jpgraph/zipball/6d87fc342afaf8a9a898a3122b5f0f34fc82c4cf", + "reference": "6d87fc342afaf8a9a898a3122b5f0f34fc82c4cf", "shasum": "" }, "require": { - "php": ">=5.5" + "php": ">=5.5 <=8.2" + }, + "replace": { + "jpgraph/jpgraph": "4.0.2" }, "type": "library", "autoload": { @@ -1372,16 +1375,16 @@ "name": "JpGraph team" } ], - "description": "Composer compatible version of JpGraph library with PHP 8.1 support", + "description": "Composer compatible version of JpGraph library with PHP 8.2 support", "homepage": "https://github.com/mitoteam/jpgraph", "keywords": [ "jpgraph" ], "support": { "issues": "https://github.com/mitoteam/jpgraph/issues", - "source": "https://github.com/mitoteam/jpgraph/tree/10.1.3" + "source": "https://github.com/mitoteam/jpgraph/tree/10.2.2" }, - "time": "2022-07-05T16:46:34+00:00" + "time": "2022-09-09T08:16:10+00:00" }, { "name": "mpdf/mpdf", @@ -5265,5 +5268,5 @@ "ext-zlib": "*" }, "platform-dev": [], - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.2.0" } diff --git a/tests/PhpSpreadsheetTests/Helper/SampleTest.php b/tests/PhpSpreadsheetTests/Helper/SampleTest.php index a104e8ff..2195155f 100644 --- a/tests/PhpSpreadsheetTests/Helper/SampleTest.php +++ b/tests/PhpSpreadsheetTests/Helper/SampleTest.php @@ -27,12 +27,6 @@ class SampleTest extends TestCase { $skipped = [ ]; - if (PHP_VERSION_ID >= 80200) { - // Hopefully temporary. Continue to try - // 32_chart_read_write_PDF/HTML - // so as not to lose track of the problem. - $skipped[] = 'Chart/35_Chart_render.php'; - } // Unfortunately some tests are too long to run with code-coverage // analysis on GitHub Actions, so we need to exclude them From 3e8d50547c0b7a8acf9352834b3e9155a86210b3 Mon Sep 17 00:00:00 2001 From: oleibman <10341515+oleibman@users.noreply.github.com> Date: Mon, 12 Sep 2022 08:45:13 -0700 Subject: [PATCH 4/7] Minor Fix for Percentage Formatting (#3053) Fix #1929. This was already substantially fixed, but there was a lingering problem with an unexpected leading space. It turns out there was also a problem with leading zeros, also fixed. There are also problems involving commas; fixing those seems too complicated to delay these changes, but I will add it to my to-do list. --- .../Style/NumberFormat/PercentageFormatter.php | 12 +++++++----- tests/PhpSpreadsheetTests/Style/NumberFormatTest.php | 2 +- tests/data/Style/NumberFormat.php | 9 +++++++-- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/PhpSpreadsheet/Style/NumberFormat/PercentageFormatter.php b/src/PhpSpreadsheet/Style/NumberFormat/PercentageFormatter.php index f4d3412b..07aaff1f 100644 --- a/src/PhpSpreadsheet/Style/NumberFormat/PercentageFormatter.php +++ b/src/PhpSpreadsheet/Style/NumberFormat/PercentageFormatter.php @@ -20,7 +20,8 @@ class PercentageFormatter extends BaseFormatter $format = str_replace('%', '%%', $format); $wholePartSize = strlen((string) floor($value)); - $decimalPartSize = $placeHolders = 0; + $decimalPartSize = 0; + $placeHolders = ''; // Number of decimals if (preg_match('/\.([?0]+)/u', $format, $matches)) { $decimalPartSize = strlen($matches[1]); @@ -29,12 +30,13 @@ class PercentageFormatter extends BaseFormatter $placeHolders = str_repeat(' ', strlen($matches[1]) - $decimalPartSize); } // Number of digits to display before the decimal - if (preg_match('/([#0,]+)\./u', $format, $matches)) { - $wholePartSize = max($wholePartSize, strlen($matches[1])); + if (preg_match('/([#0,]+)\.?/u', $format, $matches)) { + $firstZero = preg_replace('/^[#,]*/', '', $matches[1]); + $wholePartSize = max($wholePartSize, strlen($firstZero)); } - $wholePartSize += $decimalPartSize; - $replacement = "{$wholePartSize}.{$decimalPartSize}"; + $wholePartSize += $decimalPartSize + (int) ($decimalPartSize > 0); + $replacement = "0{$wholePartSize}.{$decimalPartSize}"; $mask = (string) preg_replace('/[#0,]+\.?[?#0,]*/ui', "%{$replacement}f{$placeHolders}", $format); /** @var float */ diff --git a/tests/PhpSpreadsheetTests/Style/NumberFormatTest.php b/tests/PhpSpreadsheetTests/Style/NumberFormatTest.php index e386b292..f09c34d7 100644 --- a/tests/PhpSpreadsheetTests/Style/NumberFormatTest.php +++ b/tests/PhpSpreadsheetTests/Style/NumberFormatTest.php @@ -47,7 +47,7 @@ class NumberFormatTest extends TestCase public function testFormatValueWithMask($expectedResult, ...$args): void { $result = NumberFormat::toFormattedString(...$args); - self::assertEquals($expectedResult, $result); + self::assertSame($expectedResult, $result); } public function providerNumberFormat(): array diff --git a/tests/data/Style/NumberFormat.php b/tests/data/Style/NumberFormat.php index 80f7080b..b307e23d 100644 --- a/tests/data/Style/NumberFormat.php +++ b/tests/data/Style/NumberFormat.php @@ -146,13 +146,13 @@ return [ '#,###', ], [ - 12, + '12', 12000, '#,', ], // Scaling test [ - 12.199999999999999, + '12.2', 12200000, '0.0,,', ], @@ -1486,4 +1486,9 @@ return [ '-1111.119', NumberFormat::FORMAT_ACCOUNTING_EUR, ], + 'issue 1929' => ['(79.3%)', -0.793, '#,##0.0%;(#,##0.0%)'], + 'percent without leading 0' => ['6.2%', 0.062, '##.0%'], + 'percent with leading 0' => ['06.2%', 0.062, '00.0%'], + 'percent lead0 no decimal' => ['06%', 0.062, '00%'], + 'percent nolead0 no decimal' => ['6%', 0.062, '##%'], ]; From 252474c1bd5bbe8984f4d06ac6711375bfd2fe40 Mon Sep 17 00:00:00 2001 From: oleibman <10341515+oleibman@users.noreply.github.com> Date: Wed, 14 Sep 2022 07:11:20 -0700 Subject: [PATCH 5/7] Scrutinizer Clean Up Tests (#3061) * Scrutinizer Clean Up Tests No source code involved. * Scrutinizer Whack-a-mole Fixed 17, added 10. Trying again. * Simplify Some Tests Eliminate some null assertions. * Dead Code Remove 2 statements. --- infra/DocumentGenerator.php | 2 +- ...dling_loader_exceptions_using_TryCatch.php | 2 +- src/PhpSpreadsheet/Spreadsheet.php | 13 ++ .../Engineering/ParseComplexTest.php | 8 +- .../Functions/Financial/IrrTest.php | 45 +++-- .../Functions/LookupRef/ColumnsTest.php | 8 +- .../Functions/LookupRef/IndexTest.php | 8 +- .../Functions/LookupRef/RowsTest.php | 8 +- .../Functions/MathTrig/RandBetweenTest.php | 2 +- tests/PhpSpreadsheetTests/DefinedNameTest.php | 36 ++-- .../Functional/PrintAreaTest.php | 3 +- .../PhpSpreadsheetTests/NamedFormulaTest.php | 12 +- tests/PhpSpreadsheetTests/NamedRangeTest.php | 12 +- .../Reader/Csv/CsvContiguousTest.php | 10 +- .../Reader/Xls/NumberFormatGeneralTest.php | 24 +-- .../Reader/Xls/RichTextSizeTest.php | 3 +- .../Reader/Xlsx/AutoFilter2Test.php | 9 +- .../Reader/Xlsx/ChartSheetTest.php | 7 +- .../Reader/Xlsx/Issue2501Test.php | 16 +- .../Reader/Xlsx/NamespaceNonStdTest.php | 10 +- .../Reader/Xlsx/NamespaceOpenpyxl35Test.php | 10 +- .../Reader/Xlsx/NamespaceStdTest.php | 10 +- .../Reader/Xlsx/PageSetup2Test.php | 3 +- .../Shared/PasswordHasherTest.php | 23 ++- tests/PhpSpreadsheetTests/SpreadsheetTest.php | 171 ++++++++++-------- .../ConditionalFormatting/CellMatcherTest.php | 92 ++++++---- .../Wizard/WizardFactoryTest.php | 9 +- .../Writer/Xls/VisibilityTest.php | 2 +- .../Writer/Xlsx/UnparsedDataCloneTest.php | 12 +- .../Writer/Xlsx/VisibilityTest.php | 2 +- tests/data/Calculation/Financial/IRR.php | 1 + 31 files changed, 292 insertions(+), 281 deletions(-) diff --git a/infra/DocumentGenerator.php b/infra/DocumentGenerator.php index e2c3c86c..8a6be076 100644 --- a/infra/DocumentGenerator.php +++ b/infra/DocumentGenerator.php @@ -41,7 +41,7 @@ class DocumentGenerator private static function tableRow(array $lengths, ?array $values = null): string { $result = ''; - foreach (array_map(null, $lengths, $values ?? []) as $i => [$length, $value]) { + foreach (array_map(/** @scrutinizer ignore-type */ null, $lengths, $values ?? []) as $i => [$length, $value]) { $pad = $value === null ? '-' : ' '; if ($i > 0) { $result .= '|' . $pad; diff --git a/samples/Reader/16_Handling_loader_exceptions_using_TryCatch.php b/samples/Reader/16_Handling_loader_exceptions_using_TryCatch.php index 603f6cb8..d984b7b6 100644 --- a/samples/Reader/16_Handling_loader_exceptions_using_TryCatch.php +++ b/samples/Reader/16_Handling_loader_exceptions_using_TryCatch.php @@ -11,5 +11,5 @@ $helper->log('Loading file ' . /** @scrutinizer ignore-type */ pathinfo($inputFi try { $spreadsheet = IOFactory::load($inputFileName); } catch (ReaderException $e) { - $helper->log('Error loading file "' . pathinfo($inputFileName, PATHINFO_BASENAME) . '": ' . $e->getMessage()); + $helper->log('Error loading file "' . /** @scrutinizer ignore-type */ pathinfo($inputFileName, PATHINFO_BASENAME) . '": ' . $e->getMessage()); } diff --git a/src/PhpSpreadsheet/Spreadsheet.php b/src/PhpSpreadsheet/Spreadsheet.php index 4bb93987..364700e2 100644 --- a/src/PhpSpreadsheet/Spreadsheet.php +++ b/src/PhpSpreadsheet/Spreadsheet.php @@ -724,6 +724,19 @@ class Spreadsheet return null; } + /** + * Get sheet by name, throwing exception if not found. + */ + public function getSheetByNameOrThrow(string $worksheetName): Worksheet + { + $worksheet = $this->getSheetByName($worksheetName); + if ($worksheet === null) { + throw new Exception("Sheet $worksheetName does not exist."); + } + + return $worksheet; + } + /** * Get index for sheet. * diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ParseComplexTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ParseComplexTest.php index 1022052e..a32d946f 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ParseComplexTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ParseComplexTest.php @@ -3,21 +3,15 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Engineering; use PhpOffice\PhpSpreadsheet\Calculation\Engineering; -use PhpOffice\PhpSpreadsheet\Calculation\Functions; use PHPUnit\Framework\TestCase; class ParseComplexTest extends TestCase { - protected function setUp(): void - { - Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL); - } - public function testParseComplex(): void { [$real, $imaginary, $suffix] = [1.23e-4, 5.67e+8, 'j']; - $result = Engineering::parseComplex('1.23e-4+5.67e+8j'); + $result = /** @scrutinizer ignore-deprecated */ Engineering::parseComplex('1.23e-4+5.67e+8j'); self::assertArrayHasKey('real', $result); self::assertEquals($real, $result['real']); self::assertArrayHasKey('imaginary', $result); diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Financial/IrrTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Financial/IrrTest.php index 3c4bdb5a..2565f6c2 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Financial/IrrTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Financial/IrrTest.php @@ -2,26 +2,45 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Financial; -use PhpOffice\PhpSpreadsheet\Calculation\Financial; -use PhpOffice\PhpSpreadsheet\Calculation\Functions; -use PHPUnit\Framework\TestCase; - -class IrrTest extends TestCase +class IrrTest extends AllSetupTeardown { - protected function setUp(): void - { - Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL); - } - /** * @dataProvider providerIRR * * @param mixed $expectedResult + * @param mixed $values */ - public function testIRR($expectedResult, ...$args): void + public function testIRR($expectedResult, $values = null): void { - $result = Financial::IRR(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + $this->mightHaveException($expectedResult); + $sheet = $this->getSheet(); + $formula = '=IRR('; + if ($values !== null) { + if (is_array($values)) { + $row = 0; + foreach ($values as $value) { + if (is_array($value)) { + foreach ($value as $arrayValue) { + ++$row; + $sheet->getCell("A$row")->setValue($arrayValue); + } + } else { + ++$row; + $sheet->getCell("A$row")->setValue($value); + } + } + $formula .= "A1:A$row"; + } else { + $sheet->getCell('A1')->setValue($values); + $formula .= 'A1'; + } + } + $formula .= ')'; + $sheet->getCell('D1')->setValue($formula); + $result = $sheet->getCell('D1')->getCalculatedValue(); + $this->adjustResult($result, $expectedResult); + + self::assertEqualsWithDelta($expectedResult, $result, 0.1E-8); } public function providerIRR(): array diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/LookupRef/ColumnsTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/LookupRef/ColumnsTest.php index f4f9bb9e..e8790cbf 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/LookupRef/ColumnsTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/LookupRef/ColumnsTest.php @@ -3,17 +3,11 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\LookupRef; use PhpOffice\PhpSpreadsheet\Calculation\Calculation; -use PhpOffice\PhpSpreadsheet\Calculation\Functions; use PhpOffice\PhpSpreadsheet\Calculation\LookupRef; use PHPUnit\Framework\TestCase; class ColumnsTest extends TestCase { - protected function setUp(): void - { - Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL); - } - /** * @dataProvider providerCOLUMNS * @@ -21,7 +15,7 @@ class ColumnsTest extends TestCase */ public function testCOLUMNS($expectedResult, ...$args): void { - $result = LookupRef::COLUMNS(...$args); + $result = LookupRef::COLUMNS(/** @scrutinizer ignore-type */ ...$args); self::assertEquals($expectedResult, $result); } diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/LookupRef/IndexTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/LookupRef/IndexTest.php index 03c87b50..fa3f4848 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/LookupRef/IndexTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/LookupRef/IndexTest.php @@ -3,17 +3,11 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\LookupRef; use PhpOffice\PhpSpreadsheet\Calculation\Calculation; -use PhpOffice\PhpSpreadsheet\Calculation\Functions; use PhpOffice\PhpSpreadsheet\Calculation\LookupRef; use PHPUnit\Framework\TestCase; class IndexTest extends TestCase { - protected function setUp(): void - { - Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL); - } - /** * @dataProvider providerINDEX * @@ -21,7 +15,7 @@ class IndexTest extends TestCase */ public function testINDEX($expectedResult, ...$args): void { - $result = LookupRef::INDEX(...$args); + $result = LookupRef::INDEX(/** @scrutinizer ignore-type */ ...$args); self::assertEquals($expectedResult, $result); } diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/LookupRef/RowsTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/LookupRef/RowsTest.php index 2155bdf1..fd9902f4 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/LookupRef/RowsTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/LookupRef/RowsTest.php @@ -3,17 +3,11 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\LookupRef; use PhpOffice\PhpSpreadsheet\Calculation\Calculation; -use PhpOffice\PhpSpreadsheet\Calculation\Functions; use PhpOffice\PhpSpreadsheet\Calculation\LookupRef; use PHPUnit\Framework\TestCase; class RowsTest extends TestCase { - protected function setUp(): void - { - Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL); - } - /** * @dataProvider providerROWS * @@ -21,7 +15,7 @@ class RowsTest extends TestCase */ public function testROWS($expectedResult, ...$args): void { - $result = LookupRef::ROWS(...$args); + $result = LookupRef::ROWS(/** @scrutinizer ignore-type */ ...$args); self::assertEquals($expectedResult, $result); } diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/RandBetweenTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/RandBetweenTest.php index 99cc1fa8..50b7117c 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/RandBetweenTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/RandBetweenTest.php @@ -60,7 +60,7 @@ class RandBetweenTest extends AllSetupTeardown $formula = "=RandBetween({$argument1}, {$argument2})"; $result = $calculation->_calculateFormulaValue($formula); self::assertIsArray($result); - self::assertCount($expectedRows, $result); + self::assertCount($expectedRows, /** @scrutinizer ignore-type */ $result); self::assertIsArray($result[0]); self::assertCount($expectedColumns, /** @scrutinizer ignore-type */ $result[0]); } diff --git a/tests/PhpSpreadsheetTests/DefinedNameTest.php b/tests/PhpSpreadsheetTests/DefinedNameTest.php index 82950880..c001f204 100644 --- a/tests/PhpSpreadsheetTests/DefinedNameTest.php +++ b/tests/PhpSpreadsheetTests/DefinedNameTest.php @@ -58,7 +58,7 @@ class DefinedNameTest extends TestCase DefinedName::createInstance('Foo', $this->spreadsheet->getActiveSheet(), '=A1') ); $this->spreadsheet->addDefinedName( - DefinedName::createInstance('FOO', $this->spreadsheet->getSheetByName('Sheet #2'), '=B1', true) + DefinedName::createInstance('FOO', $this->spreadsheet->getSheetByNameOrThrow('Sheet #2'), '=B1', true) ); self::assertCount(2, $this->spreadsheet->getDefinedNames()); @@ -66,7 +66,7 @@ class DefinedNameTest extends TestCase self::assertNotNull($definedName1); self::assertSame('=A1', $definedName1->getValue()); - $definedName2 = $this->spreadsheet->getDefinedName('foo', $this->spreadsheet->getSheetByName('Sheet #2')); + $definedName2 = $this->spreadsheet->getDefinedName('foo', $this->spreadsheet->getSheetByNameOrThrow('Sheet #2')); self::assertNotNull($definedName2); self::assertSame('=B1', $definedName2->getValue()); } @@ -103,13 +103,13 @@ class DefinedNameTest extends TestCase DefinedName::createInstance('Foo', $this->spreadsheet->getActiveSheet(), '=A1') ); $this->spreadsheet->addDefinedName( - DefinedName::createInstance('FOO', $this->spreadsheet->getSheetByName('Sheet #2'), '=B1', true) + DefinedName::createInstance('FOO', $this->spreadsheet->getSheetByNameOrThrow('Sheet #2'), '=B1', true) ); $this->spreadsheet->removeDefinedName('Foo', $this->spreadsheet->getActiveSheet()); self::assertCount(1, $this->spreadsheet->getDefinedNames()); - $definedName = $this->spreadsheet->getDefinedName('foo', $this->spreadsheet->getSheetByName('Sheet #2')); + $definedName = $this->spreadsheet->getDefinedName('foo', $this->spreadsheet->getSheetByNameOrThrow('Sheet #2')); self::assertNotNull($definedName); self::assertSame('=B1', $definedName->getValue()); } @@ -120,10 +120,10 @@ class DefinedNameTest extends TestCase DefinedName::createInstance('Foo', $this->spreadsheet->getActiveSheet(), '=A1') ); $this->spreadsheet->addDefinedName( - DefinedName::createInstance('FOO', $this->spreadsheet->getSheetByName('Sheet #2'), '=B1', true) + DefinedName::createInstance('FOO', $this->spreadsheet->getSheetByNameOrThrow('Sheet #2'), '=B1', true) ); - $this->spreadsheet->removeDefinedName('Foo', $this->spreadsheet->getSheetByName('Sheet #2')); + $this->spreadsheet->removeDefinedName('Foo', $this->spreadsheet->getSheetByNameOrThrow('Sheet #2')); self::assertCount(1, $this->spreadsheet->getDefinedNames()); $definedName = $this->spreadsheet->getDefinedName('foo'); @@ -154,10 +154,8 @@ class DefinedNameTest extends TestCase public function testChangeWorksheet(): void { - $sheet1 = $this->spreadsheet->getSheetByName('Sheet #1'); - $sheet2 = $this->spreadsheet->getSheetByName('Sheet #2'); - self::assertNotNull($sheet1); - self::assertNotNull($sheet2); + $sheet1 = $this->spreadsheet->getSheetByNameOrThrow('Sheet #1'); + $sheet2 = $this->spreadsheet->getSheetByNameOrThrow('Sheet #2'); $sheet1->getCell('A1')->setValue(1); $sheet2->getCell('A1')->setValue(2); @@ -172,10 +170,8 @@ class DefinedNameTest extends TestCase public function testLocalOnly(): void { - $sheet1 = $this->spreadsheet->getSheetByName('Sheet #1'); - $sheet2 = $this->spreadsheet->getSheetByName('Sheet #2'); - self::assertNotNull($sheet1); - self::assertNotNull($sheet2); + $sheet1 = $this->spreadsheet->getSheetByNameOrThrow('Sheet #1'); + $sheet2 = $this->spreadsheet->getSheetByNameOrThrow('Sheet #2'); $sheet1->getCell('A1')->setValue(1); $sheet2->getCell('A1')->setValue(2); @@ -190,10 +186,8 @@ class DefinedNameTest extends TestCase public function testScope(): void { - $sheet1 = $this->spreadsheet->getSheetByName('Sheet #1'); - $sheet2 = $this->spreadsheet->getSheetByName('Sheet #2'); - self::assertNotNull($sheet1); - self::assertNotNull($sheet2); + $sheet1 = $this->spreadsheet->getSheetByNameOrThrow('Sheet #1'); + $sheet2 = $this->spreadsheet->getSheetByNameOrThrow('Sheet #2'); $sheet1->getCell('A1')->setValue(1); $sheet2->getCell('A1')->setValue(2); @@ -208,10 +202,8 @@ class DefinedNameTest extends TestCase public function testClone(): void { - $sheet1 = $this->spreadsheet->getSheetByName('Sheet #1'); - $sheet2 = $this->spreadsheet->getSheetByName('Sheet #2'); - self::assertNotNull($sheet1); - self::assertNotNull($sheet2); + $sheet1 = $this->spreadsheet->getSheetByNameOrThrow('Sheet #1'); + $sheet2 = $this->spreadsheet->getSheetByNameOrThrow('Sheet #2'); $sheet1->getCell('A1')->setValue(1); $sheet2->getCell('A1')->setValue(2); diff --git a/tests/PhpSpreadsheetTests/Functional/PrintAreaTest.php b/tests/PhpSpreadsheetTests/Functional/PrintAreaTest.php index 700c7c7f..921c59f5 100644 --- a/tests/PhpSpreadsheetTests/Functional/PrintAreaTest.php +++ b/tests/PhpSpreadsheetTests/Functional/PrintAreaTest.php @@ -58,8 +58,7 @@ class PrintAreaTest extends AbstractFunctional private static function getPrintArea(Spreadsheet $spreadsheet, string $name): string { - $sheet = $spreadsheet->getSheetByName($name); - self::assertNotNull($sheet, "Unable to get sheet $name"); + $sheet = $spreadsheet->getSheetByNameOrThrow($name); return $sheet->getPageSetup()->getPrintArea(); } diff --git a/tests/PhpSpreadsheetTests/NamedFormulaTest.php b/tests/PhpSpreadsheetTests/NamedFormulaTest.php index 02e9d818..28857abe 100644 --- a/tests/PhpSpreadsheetTests/NamedFormulaTest.php +++ b/tests/PhpSpreadsheetTests/NamedFormulaTest.php @@ -62,7 +62,7 @@ class NamedFormulaTest extends TestCase new NamedFormula('Foo', $this->spreadsheet->getActiveSheet(), '=19%') ); $this->spreadsheet->addNamedFormula( - new NamedFormula('FOO', $this->spreadsheet->getSheetByName('Sheet #2'), '=16%', true) + new NamedFormula('FOO', $this->spreadsheet->getSheetByNameOrThrow('Sheet #2'), '=16%', true) ); self::assertCount(2, $this->spreadsheet->getNamedFormulae()); @@ -72,7 +72,7 @@ class NamedFormulaTest extends TestCase '=19%', $formula->getValue() ); - $formula = $this->spreadsheet->getNamedFormula('foo', $this->spreadsheet->getSheetByName('Sheet #2')); + $formula = $this->spreadsheet->getNamedFormula('foo', $this->spreadsheet->getSheetByNameOrThrow('Sheet #2')); self::assertNotNull($formula); self::assertSame( '=16%', @@ -100,13 +100,13 @@ class NamedFormulaTest extends TestCase new NamedFormula('Foo', $this->spreadsheet->getActiveSheet(), '=19%') ); $this->spreadsheet->addNamedFormula( - new NamedFormula('FOO', $this->spreadsheet->getSheetByName('Sheet #2'), '=16%', true) + new NamedFormula('FOO', $this->spreadsheet->getSheetByNameOrThrow('Sheet #2'), '=16%', true) ); $this->spreadsheet->removeNamedFormula('Foo', $this->spreadsheet->getActiveSheet()); self::assertCount(1, $this->spreadsheet->getNamedFormulae()); - $formula = $this->spreadsheet->getNamedFormula('foo', $this->spreadsheet->getSheetByName('Sheet #2')); + $formula = $this->spreadsheet->getNamedFormula('foo', $this->spreadsheet->getSheetByNameOrThrow('Sheet #2')); self::assertNotNull($formula); self::assertSame( '=16%', @@ -120,10 +120,10 @@ class NamedFormulaTest extends TestCase new NamedFormula('Foo', $this->spreadsheet->getActiveSheet(), '=19%') ); $this->spreadsheet->addNamedFormula( - new NamedFormula('FOO', $this->spreadsheet->getSheetByName('Sheet #2'), '=16%', true) + new NamedFormula('FOO', $this->spreadsheet->getSheetByNameOrThrow('Sheet #2'), '=16%', true) ); - $this->spreadsheet->removeNamedFormula('Foo', $this->spreadsheet->getSheetByName('Sheet #2')); + $this->spreadsheet->removeNamedFormula('Foo', $this->spreadsheet->getSheetByNameOrThrow('Sheet #2')); self::assertCount(1, $this->spreadsheet->getNamedFormulae()); $formula = $this->spreadsheet->getNamedFormula('foo'); diff --git a/tests/PhpSpreadsheetTests/NamedRangeTest.php b/tests/PhpSpreadsheetTests/NamedRangeTest.php index 402e7eba..9440ef21 100644 --- a/tests/PhpSpreadsheetTests/NamedRangeTest.php +++ b/tests/PhpSpreadsheetTests/NamedRangeTest.php @@ -62,7 +62,7 @@ class NamedRangeTest extends TestCase new NamedRange('Foo', $this->spreadsheet->getActiveSheet(), '=A1') ); $this->spreadsheet->addNamedRange( - new NamedRange('FOO', $this->spreadsheet->getSheetByName('Sheet #2'), '=B1', true) + new NamedRange('FOO', $this->spreadsheet->getSheetByNameOrThrow('Sheet #2'), '=B1', true) ); self::assertCount(2, $this->spreadsheet->getNamedRanges()); @@ -72,7 +72,7 @@ class NamedRangeTest extends TestCase '=A1', $range->getValue() ); - $range = $this->spreadsheet->getNamedRange('foo', $this->spreadsheet->getSheetByName('Sheet #2')); + $range = $this->spreadsheet->getNamedRange('foo', $this->spreadsheet->getSheetByNameOrThrow('Sheet #2')); self::assertNotNull($range); self::assertSame( '=B1', @@ -100,13 +100,13 @@ class NamedRangeTest extends TestCase new NamedRange('Foo', $this->spreadsheet->getActiveSheet(), '=A1') ); $this->spreadsheet->addNamedRange( - new NamedRange('FOO', $this->spreadsheet->getSheetByName('Sheet #2'), '=B1', true) + new NamedRange('FOO', $this->spreadsheet->getSheetByNameOrThrow('Sheet #2'), '=B1', true) ); $this->spreadsheet->removeNamedRange('Foo', $this->spreadsheet->getActiveSheet()); self::assertCount(1, $this->spreadsheet->getNamedRanges()); - $sheet = $this->spreadsheet->getNamedRange('foo', $this->spreadsheet->getSheetByName('Sheet #2')); + $sheet = $this->spreadsheet->getNamedRange('foo', $this->spreadsheet->getSheetByNameOrThrow('Sheet #2')); self::assertNotNull($sheet); self::assertSame( '=B1', @@ -120,10 +120,10 @@ class NamedRangeTest extends TestCase new NamedRange('Foo', $this->spreadsheet->getActiveSheet(), '=A1') ); $this->spreadsheet->addNamedRange( - new NamedRange('FOO', $this->spreadsheet->getSheetByName('Sheet #2'), '=B1', true) + new NamedRange('FOO', $this->spreadsheet->getSheetByNameOrThrow('Sheet #2'), '=B1', true) ); - $this->spreadsheet->removeNamedRange('Foo', $this->spreadsheet->getSheetByName('Sheet #2')); + $this->spreadsheet->removeNamedRange('Foo', $this->spreadsheet->getSheetByNameOrThrow('Sheet #2')); self::assertCount(1, $this->spreadsheet->getNamedRanges()); $range = $this->spreadsheet->getNamedRange('foo'); diff --git a/tests/PhpSpreadsheetTests/Reader/Csv/CsvContiguousTest.php b/tests/PhpSpreadsheetTests/Reader/Csv/CsvContiguousTest.php index 291a29d0..8c28c1e7 100644 --- a/tests/PhpSpreadsheetTests/Reader/Csv/CsvContiguousTest.php +++ b/tests/PhpSpreadsheetTests/Reader/Csv/CsvContiguousTest.php @@ -56,13 +56,11 @@ class CsvContiguousTest extends TestCase private static function getCellValue(Spreadsheet $spreadsheet, string $sheetName, string $cellAddress): string { - $sheet = $spreadsheet->getSheetByName($sheetName); + $sheet = $spreadsheet->getSheetByNameOrThrow($sheetName); $result = ''; - if ($sheet !== null) { - $value = $sheet->getCell($cellAddress)->getValue(); - if (is_scalar($value) || (is_object($value) && method_exists($value, '__toString'))) { - $result = (string) $value; - } + $value = $sheet->getCell($cellAddress)->getValue(); + if (is_scalar($value) || (is_object($value) && method_exists($value, '__toString'))) { + $result = (string) $value; } return $result; diff --git a/tests/PhpSpreadsheetTests/Reader/Xls/NumberFormatGeneralTest.php b/tests/PhpSpreadsheetTests/Reader/Xls/NumberFormatGeneralTest.php index a67fbb34..80867892 100644 --- a/tests/PhpSpreadsheetTests/Reader/Xls/NumberFormatGeneralTest.php +++ b/tests/PhpSpreadsheetTests/Reader/Xls/NumberFormatGeneralTest.php @@ -15,20 +15,16 @@ class NumberFormatGeneralTest extends AbstractFunctional $reader = new Xls(); $spreadsheet = $reader->load($filename); - $sheet = $spreadsheet->getSheetByName('Blad1'); - if ($sheet === null) { - self::fail('Expected to find sheet Blad1'); - } else { - $array = $sheet->toArray(); - self::assertSame('€ 2.95', $array[1][3]); - self::assertSame(2.95, $sheet->getCell('D2')->getValue()); - self::assertSame(2.95, $sheet->getCell('D2')->getCalculatedValue()); - self::assertSame('€ 2.95', $sheet->getCell('D2')->getFormattedValue()); - self::assertSame(21, $array[1][4]); - self::assertSame(21, $sheet->getCell('E2')->getValue()); - self::assertSame(21, $sheet->getCell('E2')->getCalculatedValue()); - self::assertSame('21', $sheet->getCell('E2')->getFormattedValue()); - } + $sheet = $spreadsheet->getSheetByNameOrThrow('Blad1'); + $array = $sheet->toArray(); + self::assertSame('€ 2.95', $array[1][3]); + self::assertSame(2.95, $sheet->getCell('D2')->getValue()); + self::assertSame(2.95, $sheet->getCell('D2')->getCalculatedValue()); + self::assertSame('€ 2.95', $sheet->getCell('D2')->getFormattedValue()); + self::assertSame(21, $array[1][4]); + self::assertSame(21, $sheet->getCell('E2')->getValue()); + self::assertSame(21, $sheet->getCell('E2')->getCalculatedValue()); + self::assertSame('21', $sheet->getCell('E2')->getFormattedValue()); $spreadsheet->disconnectWorksheets(); } } diff --git a/tests/PhpSpreadsheetTests/Reader/Xls/RichTextSizeTest.php b/tests/PhpSpreadsheetTests/Reader/Xls/RichTextSizeTest.php index 54274e8c..cf45dec1 100644 --- a/tests/PhpSpreadsheetTests/Reader/Xls/RichTextSizeTest.php +++ b/tests/PhpSpreadsheetTests/Reader/Xls/RichTextSizeTest.php @@ -12,8 +12,7 @@ class RichTextSizeTest extends AbstractFunctional $filename = 'tests/data/Reader/XLS/RichTextFontSize.xls'; $reader = new Xls(); $spreadsheet = $reader->load($filename); - $sheet = $spreadsheet->getSheetByName('橱柜门板'); - self::assertNotNull($sheet); + $sheet = $spreadsheet->getSheetByNameOrThrow('橱柜门板'); $text = $sheet->getCell('L15')->getValue(); $elements = $text->getRichTextElements(); self::assertEquals(10, $elements[2]->getFont()->getSize()); diff --git a/tests/PhpSpreadsheetTests/Reader/Xlsx/AutoFilter2Test.php b/tests/PhpSpreadsheetTests/Reader/Xlsx/AutoFilter2Test.php index 57c09de5..06d6b562 100644 --- a/tests/PhpSpreadsheetTests/Reader/Xlsx/AutoFilter2Test.php +++ b/tests/PhpSpreadsheetTests/Reader/Xlsx/AutoFilter2Test.php @@ -28,8 +28,7 @@ class AutoFilter2Test extends TestCase public function testReadDateRange(): void { $spreadsheet = IOFactory::load(self::TESTBOOK); - $sheet = $spreadsheet->getSheetByName('daterange'); - self::assertNotNull($sheet); + $sheet = $spreadsheet->getSheetByNameOrThrow('daterange'); $filter = $sheet->getAutoFilter(); $maxRow = 30; self::assertSame("A1:A$maxRow", $filter->getRange()); @@ -61,8 +60,7 @@ class AutoFilter2Test extends TestCase public function testReadTopTen(): void { $spreadsheet = IOFactory::load(self::TESTBOOK); - $sheet = $spreadsheet->getSheetByName('top10'); - self::assertNotNull($sheet); + $sheet = $spreadsheet->getSheetByNameOrThrow('top10'); $filter = $sheet->getAutoFilter(); $maxRow = 65; self::assertSame("A1:A$maxRow", $filter->getRange()); @@ -87,8 +85,7 @@ class AutoFilter2Test extends TestCase public function testReadDynamic(): void { $spreadsheet = IOFactory::load(self::TESTBOOK); - $sheet = $spreadsheet->getSheetByName('dynamic'); - self::assertNotNull($sheet); + $sheet = $spreadsheet->getSheetByNameOrThrow('dynamic'); $filter = $sheet->getAutoFilter(); $maxRow = 30; self::assertSame("A1:A$maxRow", $filter->getRange()); diff --git a/tests/PhpSpreadsheetTests/Reader/Xlsx/ChartSheetTest.php b/tests/PhpSpreadsheetTests/Reader/Xlsx/ChartSheetTest.php index 0f1605ff..e7862697 100644 --- a/tests/PhpSpreadsheetTests/Reader/Xlsx/ChartSheetTest.php +++ b/tests/PhpSpreadsheetTests/Reader/Xlsx/ChartSheetTest.php @@ -3,7 +3,6 @@ namespace PhpOffice\PhpSpreadsheetTests\Reader\Xlsx; use PhpOffice\PhpSpreadsheet\Reader\Xlsx; -use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet; use PHPUnit\Framework\TestCase; class ChartSheetTest extends TestCase @@ -16,8 +15,7 @@ class ChartSheetTest extends TestCase $spreadsheet = $reader->load($filename); self::assertCount(2, $spreadsheet->getAllSheets()); - $chartSheet = $spreadsheet->getSheetByName('Chart1'); - self::assertInstanceOf(Worksheet::class, $chartSheet); + $chartSheet = $spreadsheet->getSheetByNameOrThrow('Chart1'); self::assertSame(1, $chartSheet->getChartCount()); } @@ -29,7 +27,6 @@ class ChartSheetTest extends TestCase $spreadsheet = $reader->load($filename); self::assertCount(1, $spreadsheet->getAllSheets()); - $chartSheet = $spreadsheet->getSheetByName('Chart1'); - self::assertNull($chartSheet); + self::assertNull($spreadsheet->getSheetByName('Chart1')); } } diff --git a/tests/PhpSpreadsheetTests/Reader/Xlsx/Issue2501Test.php b/tests/PhpSpreadsheetTests/Reader/Xlsx/Issue2501Test.php index 6b090fe8..57958245 100644 --- a/tests/PhpSpreadsheetTests/Reader/Xlsx/Issue2501Test.php +++ b/tests/PhpSpreadsheetTests/Reader/Xlsx/Issue2501Test.php @@ -42,28 +42,20 @@ class Issue2501Test extends TestCase $filename = self::$testbook; $reader = IOFactory::createReader('Xlsx'); $spreadsheet = $reader->load($filename); - $sheet = $spreadsheet->getSheetByName('Columns'); + $sheet = $spreadsheet->getSheetByNameOrThrow('Columns'); $expected = [ 'A1:A1048576', 'B1:D1048576', 'E2:E4', ]; - if ($sheet === null) { - self::fail('Unable to find sheet Columns'); - } else { - self::assertSame($expected, array_values($sheet->getMergeCells())); - } - $sheet = $spreadsheet->getSheetByName('Rows'); + self::assertSame($expected, array_values($sheet->getMergeCells())); + $sheet = $spreadsheet->getSheetByNameOrThrow('Rows'); $expected = [ 'A1:XFD1', 'A2:XFD4', 'B5:D5', ]; - if ($sheet === null) { - self::fail('Unable to find sheet Rows'); - } else { - self::assertSame($expected, array_values($sheet->getMergeCells())); - } + self::assertSame($expected, array_values($sheet->getMergeCells())); $spreadsheet->disconnectWorksheets(); } diff --git a/tests/PhpSpreadsheetTests/Reader/Xlsx/NamespaceNonStdTest.php b/tests/PhpSpreadsheetTests/Reader/Xlsx/NamespaceNonStdTest.php index 1849c5bd..cc2c03dc 100644 --- a/tests/PhpSpreadsheetTests/Reader/Xlsx/NamespaceNonStdTest.php +++ b/tests/PhpSpreadsheetTests/Reader/Xlsx/NamespaceNonStdTest.php @@ -62,13 +62,9 @@ class NamespaceNonStdTest extends \PHPUnit\Framework\TestCase self::assertSame('A2', $sheet->getFreezePane()); self::assertSame('A2', $sheet->getTopLeftCell()); self::assertSame('B3', $sheet->getSelectedCells()); - $sheet = $spreadsheet->getSheetByName('SylkTest'); - if ($sheet === null) { - self::fail('Unable to load expected sheet'); - } else { - self::assertNull($sheet->getFreezePane()); - self::assertNull($sheet->getTopLeftCell()); - } + $sheet = $spreadsheet->getSheetByNameOrThrow('SylkTest'); + self::assertNull($sheet->getFreezePane()); + self::assertNull($sheet->getTopLeftCell()); } public function testLoadXlsx(): void diff --git a/tests/PhpSpreadsheetTests/Reader/Xlsx/NamespaceOpenpyxl35Test.php b/tests/PhpSpreadsheetTests/Reader/Xlsx/NamespaceOpenpyxl35Test.php index 1b1743c9..afb36862 100644 --- a/tests/PhpSpreadsheetTests/Reader/Xlsx/NamespaceOpenpyxl35Test.php +++ b/tests/PhpSpreadsheetTests/Reader/Xlsx/NamespaceOpenpyxl35Test.php @@ -100,13 +100,9 @@ class NamespaceOpenpyxl35Test extends \PHPUnit\Framework\TestCase ], ]; foreach ($expectedArray as $sheetName => $array1) { - $sheet = $spreadsheet->getSheetByName($sheetName); - if ($sheet === null) { - self::fail("Unable to find sheet $sheetName"); - } else { - foreach ($array1 as $key => $value) { - self::assertSame($value, self::getCellValue($sheet, $key), "error in sheet $sheetName cell $key"); - } + $sheet = $spreadsheet->getSheetByNameOrThrow($sheetName); + foreach ($array1 as $key => $value) { + self::assertSame($value, self::getCellValue($sheet, $key), "error in sheet $sheetName cell $key"); } } $spreadsheet->disconnectWorksheets(); diff --git a/tests/PhpSpreadsheetTests/Reader/Xlsx/NamespaceStdTest.php b/tests/PhpSpreadsheetTests/Reader/Xlsx/NamespaceStdTest.php index 8b47d141..5f8c8bc3 100644 --- a/tests/PhpSpreadsheetTests/Reader/Xlsx/NamespaceStdTest.php +++ b/tests/PhpSpreadsheetTests/Reader/Xlsx/NamespaceStdTest.php @@ -62,13 +62,9 @@ class NamespaceStdTest extends \PHPUnit\Framework\TestCase self::assertSame('A2', $sheet->getFreezePane()); self::assertSame('A2', $sheet->getTopLeftCell()); self::assertSame('B3', $sheet->getSelectedCells()); - $sheet = $spreadsheet->getSheetByName('SylkTest'); - if ($sheet === null) { - self::fail('Unable to load expected sheet'); - } else { - self::assertNull($sheet->getFreezePane()); - self::assertNull($sheet->getTopLeftCell()); - } + $sheet = $spreadsheet->getSheetByNameOrThrow('SylkTest'); + self::assertNull($sheet->getFreezePane()); + self::assertNull($sheet->getTopLeftCell()); } public function testLoadXlsx(): void diff --git a/tests/PhpSpreadsheetTests/Reader/Xlsx/PageSetup2Test.php b/tests/PhpSpreadsheetTests/Reader/Xlsx/PageSetup2Test.php index 1bbc88ac..12675b41 100644 --- a/tests/PhpSpreadsheetTests/Reader/Xlsx/PageSetup2Test.php +++ b/tests/PhpSpreadsheetTests/Reader/Xlsx/PageSetup2Test.php @@ -28,8 +28,7 @@ class PageSetup2Test extends TestCase public function testColumnBreak(): void { $spreadsheet = IOFactory::load(self::TESTBOOK); - $sheet = $spreadsheet->getSheetByName('colbreak'); - self::assertNotNull($sheet); + $sheet = $spreadsheet->getSheetByNameOrThrow('colbreak'); $breaks = $sheet->getBreaks(); self::assertCount(1, $breaks); $break = $breaks['D1'] ?? null; diff --git a/tests/PhpSpreadsheetTests/Shared/PasswordHasherTest.php b/tests/PhpSpreadsheetTests/Shared/PasswordHasherTest.php index 4b7923d8..c9912b8c 100644 --- a/tests/PhpSpreadsheetTests/Shared/PasswordHasherTest.php +++ b/tests/PhpSpreadsheetTests/Shared/PasswordHasherTest.php @@ -10,16 +10,27 @@ class PasswordHasherTest extends TestCase { /** * @dataProvider providerHashPassword - * - * @param mixed $expectedResult */ - public function testHashPassword($expectedResult, ...$args): void - { + public function testHashPassword( + string $expectedResult, + string $password, + ?string $algorithm = null, + ?string $salt = null, + ?int $spinCount = null + ): void { if ($expectedResult === 'exception') { $this->expectException(SpException::class); } - $result = PasswordHasher::hashPassword(...$args); - self::assertEquals($expectedResult, $result); + if ($algorithm === null) { + $result = PasswordHasher::hashPassword($password); + } elseif ($salt === null) { + $result = PasswordHasher::hashPassword($password, $algorithm); + } elseif ($spinCount === null) { + $result = PasswordHasher::hashPassword($password, $algorithm, $salt); + } else { + $result = PasswordHasher::hashPassword($password, $algorithm, $salt, $spinCount); + } + self::assertSame($expectedResult, $result); } public function providerHashPassword(): array diff --git a/tests/PhpSpreadsheetTests/SpreadsheetTest.php b/tests/PhpSpreadsheetTests/SpreadsheetTest.php index 11fb56e4..76e28b3d 100644 --- a/tests/PhpSpreadsheetTests/SpreadsheetTest.php +++ b/tests/PhpSpreadsheetTests/SpreadsheetTest.php @@ -2,28 +2,38 @@ namespace PhpOffice\PhpSpreadsheetTests; +use PhpOffice\PhpSpreadsheet\Exception as ssException; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet; use PHPUnit\Framework\TestCase; class SpreadsheetTest extends TestCase { - /** @var Spreadsheet */ - private $object; + /** @var ?Spreadsheet */ + private $spreadsheet; - protected function setUp(): void + protected function tearDown(): void { - parent::setUp(); - $this->object = new Spreadsheet(); - $sheet = $this->object->getActiveSheet(); + if ($this->spreadsheet !== null) { + $this->spreadsheet->disconnectWorksheets(); + $this->spreadsheet = null; + } + } + + private function getSpreadsheet(): Spreadsheet + { + $this->spreadsheet = $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); $sheet->setTitle('someSheet1'); $sheet = new Worksheet(); $sheet->setTitle('someSheet2'); - $this->object->addSheet($sheet); + $spreadsheet->addSheet($sheet); $sheet = new Worksheet(); $sheet->setTitle('someSheet 3'); - $this->object->addSheet($sheet); + $spreadsheet->addSheet($sheet); + + return $spreadsheet; } public function dataProviderForSheetNames(): array @@ -35,6 +45,7 @@ class SpreadsheetTest extends TestCase [1, "'someSheet2'"], [2, 'someSheet 3'], [2, "'someSheet 3'"], + [null, 'someSheet 33'], ]; return $array; @@ -43,135 +54,153 @@ class SpreadsheetTest extends TestCase /** * @dataProvider dataProviderForSheetNames */ - public function testGetSheetByName(int $index, string $sheetName): void + public function testGetSheetByName(?int $index, string $sheetName): void { - self::assertSame($this->object->getSheet($index), $this->object->getSheetByName($sheetName)); + $spreadsheet = $this->getSpreadsheet(); + if ($index === null) { + self::assertNull($spreadsheet->getSheetByName($sheetName)); + } else { + self::assertSame($spreadsheet->getSheet($index), $spreadsheet->getSheetByName($sheetName)); + } } public function testAddSheetDuplicateTitle(): void { - $this->expectException(\PhpOffice\PhpSpreadsheet\Exception::class); + $spreadsheet = $this->getSpreadsheet(); + $this->expectException(ssException::class); $sheet = new Worksheet(); $sheet->setTitle('someSheet2'); - $this->object->addSheet($sheet); + $spreadsheet->addSheet($sheet); } public function testAddSheetNoAdjustActive(): void { - $this->object->setActiveSheetIndex(2); - self::assertEquals(2, $this->object->getActiveSheetIndex()); + $spreadsheet = $this->getSpreadsheet(); + $spreadsheet->setActiveSheetIndex(2); + self::assertEquals(2, $spreadsheet->getActiveSheetIndex()); $sheet = new Worksheet(); $sheet->setTitle('someSheet4'); - $this->object->addSheet($sheet); - self::assertEquals(2, $this->object->getActiveSheetIndex()); + $spreadsheet->addSheet($sheet); + self::assertEquals(2, $spreadsheet->getActiveSheetIndex()); } public function testAddSheetAdjustActive(): void { - $this->object->setActiveSheetIndex(2); - self::assertEquals(2, $this->object->getActiveSheetIndex()); + $spreadsheet = $this->getSpreadsheet(); + $spreadsheet->setActiveSheetIndex(2); + self::assertEquals(2, $spreadsheet->getActiveSheetIndex()); $sheet = new Worksheet(); $sheet->setTitle('someSheet0'); - $this->object->addSheet($sheet, 0); - self::assertEquals(3, $this->object->getActiveSheetIndex()); + $spreadsheet->addSheet($sheet, 0); + self::assertEquals(3, $spreadsheet->getActiveSheetIndex()); } public function testRemoveSheetIndexTooHigh(): void { - $this->expectException(\PhpOffice\PhpSpreadsheet\Exception::class); - $this->object->removeSheetByIndex(4); + $spreadsheet = $this->getSpreadsheet(); + $this->expectException(ssException::class); + $spreadsheet->removeSheetByIndex(4); } public function testRemoveSheetNoAdjustActive(): void { - $this->object->setActiveSheetIndex(1); - self::assertEquals(1, $this->object->getActiveSheetIndex()); - $this->object->removeSheetByIndex(2); - self::assertEquals(1, $this->object->getActiveSheetIndex()); + $spreadsheet = $this->getSpreadsheet(); + $spreadsheet->setActiveSheetIndex(1); + self::assertEquals(1, $spreadsheet->getActiveSheetIndex()); + $spreadsheet->removeSheetByIndex(2); + self::assertEquals(1, $spreadsheet->getActiveSheetIndex()); } public function testRemoveSheetAdjustActive(): void { - $this->object->setActiveSheetIndex(2); - self::assertEquals(2, $this->object->getActiveSheetIndex()); - $this->object->removeSheetByIndex(1); - self::assertEquals(1, $this->object->getActiveSheetIndex()); + $spreadsheet = $this->getSpreadsheet(); + $spreadsheet->setActiveSheetIndex(2); + self::assertEquals(2, $spreadsheet->getActiveSheetIndex()); + $spreadsheet->removeSheetByIndex(1); + self::assertEquals(1, $spreadsheet->getActiveSheetIndex()); } public function testGetSheetIndexTooHigh(): void { - $this->expectException(\PhpOffice\PhpSpreadsheet\Exception::class); - $this->object->getSheet(4); + $spreadsheet = $this->getSpreadsheet(); + $this->expectException(ssException::class); + $spreadsheet->getSheet(4); } public function testGetIndexNonExistent(): void { - $this->expectException(\PhpOffice\PhpSpreadsheet\Exception::class); + $spreadsheet = $this->getSpreadsheet(); + $this->expectException(ssException::class); $sheet = new Worksheet(); $sheet->setTitle('someSheet4'); - $this->object->getIndex($sheet); + $spreadsheet->getIndex($sheet); } public function testSetIndexByName(): void { - $this->object->setIndexByName('someSheet1', 1); - self::assertEquals('someSheet2', $this->object->getSheet(0)->getTitle()); - self::assertEquals('someSheet1', $this->object->getSheet(1)->getTitle()); - self::assertEquals('someSheet 3', $this->object->getSheet(2)->getTitle()); + $spreadsheet = $this->getSpreadsheet(); + $spreadsheet->setIndexByName('someSheet1', 1); + self::assertEquals('someSheet2', $spreadsheet->getSheet(0)->getTitle()); + self::assertEquals('someSheet1', $spreadsheet->getSheet(1)->getTitle()); + self::assertEquals('someSheet 3', $spreadsheet->getSheet(2)->getTitle()); } public function testRemoveAllSheets(): void { - $this->object->setActiveSheetIndex(2); - self::assertEquals(2, $this->object->getActiveSheetIndex()); - $this->object->removeSheetByIndex(0); - self::assertEquals(1, $this->object->getActiveSheetIndex()); - $this->object->removeSheetByIndex(0); - self::assertEquals(0, $this->object->getActiveSheetIndex()); - $this->object->removeSheetByIndex(0); - self::assertEquals(-1, $this->object->getActiveSheetIndex()); + $spreadsheet = $this->getSpreadsheet(); + $spreadsheet->setActiveSheetIndex(2); + self::assertEquals(2, $spreadsheet->getActiveSheetIndex()); + $spreadsheet->removeSheetByIndex(0); + self::assertEquals(1, $spreadsheet->getActiveSheetIndex()); + $spreadsheet->removeSheetByIndex(0); + self::assertEquals(0, $spreadsheet->getActiveSheetIndex()); + $spreadsheet->removeSheetByIndex(0); + self::assertEquals(-1, $spreadsheet->getActiveSheetIndex()); $sheet = new Worksheet(); $sheet->setTitle('someSheet4'); - $this->object->addSheet($sheet); - self::assertEquals(0, $this->object->getActiveSheetIndex()); + $spreadsheet->addSheet($sheet); + self::assertEquals(0, $spreadsheet->getActiveSheetIndex()); } public function testBug1735(): void { - $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet(); - $spreadsheet->createSheet()->setTitle('addedsheet'); - $spreadsheet->setActiveSheetIndex(1); - $spreadsheet->removeSheetByIndex(0); - $sheet = $spreadsheet->getActiveSheet(); + $spreadsheet1 = new Spreadsheet(); + $spreadsheet1->createSheet()->setTitle('addedsheet'); + $spreadsheet1->setActiveSheetIndex(1); + $spreadsheet1->removeSheetByIndex(0); + $sheet = $spreadsheet1->getActiveSheet(); self::assertEquals('addedsheet', $sheet->getTitle()); } public function testSetActiveSheetIndexTooHigh(): void { - $this->expectException(\PhpOffice\PhpSpreadsheet\Exception::class); - $this->object->setActiveSheetIndex(4); + $spreadsheet = $this->getSpreadsheet(); + $this->expectException(ssException::class); + $spreadsheet->setActiveSheetIndex(4); } public function testSetActiveSheetNoSuchName(): void { - $this->expectException(\PhpOffice\PhpSpreadsheet\Exception::class); - $this->object->setActiveSheetIndexByName('unknown'); + $spreadsheet = $this->getSpreadsheet(); + $this->expectException(ssException::class); + $spreadsheet->setActiveSheetIndexByName('unknown'); } public function testAddExternal(): void { - $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet(); - $sheet = $spreadsheet->createSheet()->setTitle('someSheet19'); + $spreadsheet = $this->getSpreadsheet(); + $spreadsheet1 = new Spreadsheet(); + $sheet = $spreadsheet1->createSheet()->setTitle('someSheet19'); $sheet->getCell('A1')->setValue(1); $sheet->getCell('A1')->getStyle()->getFont()->setBold(true); $sheet->getCell('B1')->getStyle()->getFont()->setSuperscript(true); $sheet->getCell('C1')->getStyle()->getFont()->setSubscript(true); - self::assertCount(4, $spreadsheet->getCellXfCollection()); + self::assertCount(4, $spreadsheet1->getCellXfCollection()); self::assertEquals(1, $sheet->getCell('A1')->getXfIndex()); - $this->object->getActiveSheet()->getCell('A1')->getStyle()->getFont()->setBold(true); - self::assertCount(2, $this->object->getCellXfCollection()); - $sheet3 = $this->object->addExternalSheet($sheet); - self::assertCount(6, $this->object->getCellXfCollection()); + $spreadsheet->getActiveSheet()->getCell('A1')->getStyle()->getFont()->setBold(true); + self::assertCount(2, $spreadsheet->getCellXfCollection()); + $sheet3 = $spreadsheet->addExternalSheet($sheet); + self::assertCount(6, $spreadsheet->getCellXfCollection()); self::assertEquals('someSheet19', $sheet3->getTitle()); self::assertEquals(1, $sheet3->getCell('A1')->getValue()); self::assertTrue($sheet3->getCell('A1')->getStyle()->getFont()->getBold()); @@ -181,17 +210,17 @@ class SpreadsheetTest extends TestCase public function testAddExternalDuplicateName(): void { - $this->expectException(\PhpOffice\PhpSpreadsheet\Exception::class); - $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet(); + $this->expectException(ssException::class); + $spreadsheet = new Spreadsheet(); $sheet = $spreadsheet->createSheet()->setTitle('someSheet1'); $sheet->getCell('A1')->setValue(1); $sheet->getCell('A1')->getStyle()->getFont()->setBold(true); - $this->object->addExternalSheet($sheet); + $spreadsheet->addExternalSheet($sheet); } public function testAddExternalColumnDimensionStyles(): void { - $spreadsheet1 = new \PhpOffice\PhpSpreadsheet\Spreadsheet(); + $spreadsheet1 = new Spreadsheet(); $sheet1 = $spreadsheet1->createSheet()->setTitle('sheetWithColumnDimension'); $sheet1->getCell('A1')->setValue(1); $sheet1->getCell('A1')->getStyle()->getFont()->setItalic(true); @@ -200,7 +229,7 @@ class SpreadsheetTest extends TestCase self::assertEquals(1, $index); self::assertCount(2, $spreadsheet1->getCellXfCollection()); - $spreadsheet2 = new \PhpOffice\PhpSpreadsheet\Spreadsheet(); + $spreadsheet2 = new Spreadsheet(); $sheet2 = $spreadsheet2->createSheet()->setTitle('sheetWithTwoStyles'); $sheet2->getCell('A1')->setValue(1); $sheet2->getCell('A1')->getStyle()->getFont()->setBold(true); @@ -220,7 +249,7 @@ class SpreadsheetTest extends TestCase public function testAddExternalRowDimensionStyles(): void { - $spreadsheet1 = new \PhpOffice\PhpSpreadsheet\Spreadsheet(); + $spreadsheet1 = new Spreadsheet(); $sheet1 = $spreadsheet1->createSheet()->setTitle('sheetWithColumnDimension'); $sheet1->getCell('A1')->setValue(1); $sheet1->getCell('A1')->getStyle()->getFont()->setItalic(true); @@ -229,7 +258,7 @@ class SpreadsheetTest extends TestCase self::assertEquals(1, $index); self::assertCount(2, $spreadsheet1->getCellXfCollection()); - $spreadsheet2 = new \PhpOffice\PhpSpreadsheet\Spreadsheet(); + $spreadsheet2 = new Spreadsheet(); $sheet2 = $spreadsheet2->createSheet()->setTitle('sheetWithTwoStyles'); $sheet2->getCell('A1')->setValue(1); $sheet2->getCell('A1')->getStyle()->getFont()->setBold(true); diff --git a/tests/PhpSpreadsheetTests/Style/ConditionalFormatting/CellMatcherTest.php b/tests/PhpSpreadsheetTests/Style/ConditionalFormatting/CellMatcherTest.php index 2c6d0da8..decbad5b 100644 --- a/tests/PhpSpreadsheetTests/Style/ConditionalFormatting/CellMatcherTest.php +++ b/tests/PhpSpreadsheetTests/Style/ConditionalFormatting/CellMatcherTest.php @@ -2,9 +2,12 @@ namespace PhpOffice\PhpSpreadsheetTests\Style\ConditionalFormatting; +use PhpOffice\PhpSpreadsheet\Cell\Cell; +use PhpOffice\PhpSpreadsheet\Exception as ssException; use PhpOffice\PhpSpreadsheet\IOFactory; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\CellMatcher; +use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet; use PHPUnit\Framework\TestCase; class CellMatcherTest extends TestCase @@ -30,18 +33,26 @@ class CellMatcherTest extends TestCase } } + private function confirmString(Worksheet $worksheet, Cell $cell, string $cellAddress): string + { + $cfRange = $worksheet->getConditionalRange($cell->getCoordinate()) ?? ''; + if ($cfRange === '') { + self::fail("{$cellAddress} is not in a Conditional Format range"); + } + + return $cfRange; + } + /** * @dataProvider basicCellIsComparisonDataProvider */ public function testBasicCellIsComparison(string $sheetname, string $cellAddress, array $expectedMatches): void { $this->spreadsheet = $this->loadSpreadsheet(); - $worksheet = $this->spreadsheet->getSheetByName($sheetname); - self::assertNotNull($worksheet, "$sheetname not found in test workbook"); + $worksheet = $this->spreadsheet->getSheetByNameOrThrow($sheetname); $cell = $worksheet->getCell($cellAddress); - $cfRange = $worksheet->getConditionalRange($cell->getCoordinate()); - self::assertNotNull($cfRange, "{$cellAddress} is not in a Conditional Format range"); + $cfRange = $this->confirmString($worksheet, $cell, $cellAddress); $cfStyles = $worksheet->getConditionalStyles($cell->getCoordinate()); $matcher = new CellMatcher($cell, $cfRange); @@ -83,18 +94,35 @@ class CellMatcherTest extends TestCase ]; } + public function testNotInRange(): void + { + $this->spreadsheet = $this->loadSpreadsheet(); + $sheetname = 'cellIs Comparison'; + $worksheet = $this->spreadsheet->getSheetByNameOrThrow($sheetname); + $cell = $worksheet->getCell('J20'); + + $cfRange = $worksheet->getConditionalRange($cell->getCoordinate()); + self::assertNull($cfRange); + } + + public function testUnknownSheet(): void + { + $this->expectException(ssException::class); + $this->spreadsheet = $this->loadSpreadsheet(); + $sheetname = 'cellIs Comparisonxxx'; + $this->spreadsheet->getSheetByNameOrThrow($sheetname); + } + /** * @dataProvider rangeCellIsComparisonDataProvider */ public function testRangeCellIsComparison(string $sheetname, string $cellAddress, bool $expectedMatch): void { $this->spreadsheet = $this->loadSpreadsheet(); - $worksheet = $this->spreadsheet->getSheetByName($sheetname); - self::assertNotNull($worksheet, "$sheetname not found in test workbook"); + $worksheet = $this->spreadsheet->getSheetByNameOrThrow($sheetname); $cell = $worksheet->getCell($cellAddress); - $cfRange = $worksheet->getConditionalRange($cell->getCoordinate()); - self::assertNotNull($cfRange, "$cellAddress is not in a Conditional Format range"); + $cfRange = $this->confirmString($worksheet, $cell, $cellAddress); $cfStyle = $worksheet->getConditionalStyles($cell->getCoordinate()); $matcher = new CellMatcher($cell, $cfRange); @@ -132,12 +160,10 @@ class CellMatcherTest extends TestCase public function testCellIsMultipleExpression(string $sheetname, string $cellAddress, array $expectedMatches): void { $this->spreadsheet = $this->loadSpreadsheet(); - $worksheet = $this->spreadsheet->getSheetByName($sheetname); - self::assertNotNull($worksheet, "$sheetname not found in test workbook"); + $worksheet = $this->spreadsheet->getSheetByNameOrThrow($sheetname); $cell = $worksheet->getCell($cellAddress); - $cfRange = $worksheet->getConditionalRange($cell->getCoordinate()); - self::assertNotNull($cfRange, "$cellAddress is not in a Conditional Format range"); + $cfRange = $this->confirmString($worksheet, $cell, $cellAddress); $cfStyles = $worksheet->getConditionalStyles($cell->getCoordinate()); $matcher = new CellMatcher($cell, $cfRange); @@ -168,12 +194,10 @@ class CellMatcherTest extends TestCase public function testCellIsExpression(string $sheetname, string $cellAddress, bool $expectedMatch): void { $this->spreadsheet = $this->loadSpreadsheet(); - $worksheet = $this->spreadsheet->getSheetByName($sheetname); - self::assertNotNull($worksheet, "$sheetname not found in test workbook"); + $worksheet = $this->spreadsheet->getSheetByNameOrThrow($sheetname); $cell = $worksheet->getCell($cellAddress); - $cfRange = $worksheet->getConditionalRange($cell->getCoordinate()); - self::assertNotNull($cfRange, "$cellAddress is not in a Conditional Format range"); + $cfRange = $this->confirmString($worksheet, $cell, $cellAddress); $cfStyle = $worksheet->getConditionalStyles($cell->getCoordinate()); $matcher = new CellMatcher($cell, $cfRange); @@ -214,12 +238,10 @@ class CellMatcherTest extends TestCase public function testTextExpressions(string $sheetname, string $cellAddress, bool $expectedMatch): void { $this->spreadsheet = $this->loadSpreadsheet(); - $worksheet = $this->spreadsheet->getSheetByName($sheetname); - self::assertNotNull($worksheet, "$sheetname not found in test workbook"); + $worksheet = $this->spreadsheet->getSheetByNameOrThrow($sheetname); $cell = $worksheet->getCell($cellAddress); - $cfRange = $worksheet->getConditionalRange($cell->getCoordinate()); - self::assertNotNull($cfRange, "$cellAddress is not in a Conditional Format range"); + $cfRange = $this->confirmString($worksheet, $cell, $cellAddress); $cfStyle = $worksheet->getConditionalStyles($cell->getCoordinate()); $matcher = new CellMatcher($cell, $cfRange); @@ -324,12 +346,10 @@ class CellMatcherTest extends TestCase public function testBlankExpressions(string $sheetname, string $cellAddress, array $expectedMatches): void { $this->spreadsheet = $this->loadSpreadsheet(); - $worksheet = $this->spreadsheet->getSheetByName($sheetname); - self::assertNotNull($worksheet, "$sheetname not found in test workbook"); + $worksheet = $this->spreadsheet->getSheetByNameOrThrow($sheetname); $cell = $worksheet->getCell($cellAddress); - $cfRange = $worksheet->getConditionalRange($cell->getCoordinate()); - self::assertNotNull($cfRange, "$cellAddress is not in a Conditional Format range"); + $cfRange = $this->confirmString($worksheet, $cell, $cellAddress); $cfStyles = $worksheet->getConditionalStyles($cell->getCoordinate()); $matcher = new CellMatcher($cell, $cfRange); @@ -357,12 +377,10 @@ class CellMatcherTest extends TestCase public function testErrorExpressions(string $sheetname, string $cellAddress, array $expectedMatches): void { $this->spreadsheet = $this->loadSpreadsheet(); - $worksheet = $this->spreadsheet->getSheetByName($sheetname); - self::assertNotNull($worksheet, "$sheetname not found in test workbook"); + $worksheet = $this->spreadsheet->getSheetByNameOrThrow($sheetname); $cell = $worksheet->getCell($cellAddress); - $cfRange = $worksheet->getConditionalRange($cell->getCoordinate()); - self::assertNotNull($cfRange, "$cellAddress is not in a Conditional Format range"); + $cfRange = $this->confirmString($worksheet, $cell, $cellAddress); $cfStyles = $worksheet->getConditionalStyles($cell->getCoordinate()); $matcher = new CellMatcher($cell, $cfRange); @@ -389,12 +407,10 @@ class CellMatcherTest extends TestCase public function testDateOccurringExpressions(string $sheetname, string $cellAddress, bool $expectedMatch): void { $this->spreadsheet = $this->loadSpreadsheet(); - $worksheet = $this->spreadsheet->getSheetByName($sheetname); - self::assertNotNull($worksheet, "$sheetname not found in test workbook"); + $worksheet = $this->spreadsheet->getSheetByNameOrThrow($sheetname); $cell = $worksheet->getCell($cellAddress); - $cfRange = $worksheet->getConditionalRange($cell->getCoordinate()); - self::assertNotNull($cfRange, "$cellAddress is not in a Conditional Format range"); + $cfRange = $this->confirmString($worksheet, $cell, $cellAddress); $cfStyle = $worksheet->getConditionalStyles($cell->getCoordinate()); $matcher = new CellMatcher($cell, $cfRange); @@ -433,12 +449,10 @@ class CellMatcherTest extends TestCase public function testDuplicatesExpressions(string $sheetname, string $cellAddress, array $expectedMatches): void { $this->spreadsheet = $this->loadSpreadsheet(); - $worksheet = $this->spreadsheet->getSheetByName($sheetname); - self::assertNotNull($worksheet, "$sheetname not found in test workbook"); + $worksheet = $this->spreadsheet->getSheetByNameOrThrow($sheetname); $cell = $worksheet->getCell($cellAddress); - $cfRange = $worksheet->getConditionalRange($cell->getCoordinate()); - self::AssertNotNull($cfRange, "$cellAddress is not in a Conditional Format range"); + $cfRange = $this->confirmString($worksheet, $cell, $cellAddress); $cfStyles = $worksheet->getConditionalStyles($cell->getCoordinate()); $matcher = new CellMatcher($cell, $cfRange); @@ -469,12 +483,10 @@ class CellMatcherTest extends TestCase public function testCrossWorksheetExpressions(string $sheetname, string $cellAddress, bool $expectedMatch): void { $this->spreadsheet = $this->loadSpreadsheet(); - $worksheet = $this->spreadsheet->getSheetByName($sheetname); - self::assertNotNull($worksheet, "$sheetname not found in test workbook"); + $worksheet = $this->spreadsheet->getSheetByNameOrThrow($sheetname); $cell = $worksheet->getCell($cellAddress); - $cfRange = $worksheet->getConditionalRange($cell->getCoordinate()); - self::assertNotNull($cfRange, "$cellAddress is not in a Conditional Format range"); + $cfRange = $this->confirmString($worksheet, $cell, $cellAddress); $cfStyle = $worksheet->getConditionalStyles($cell->getCoordinate()); $matcher = new CellMatcher($cell, $cfRange); diff --git a/tests/PhpSpreadsheetTests/Style/ConditionalFormatting/Wizard/WizardFactoryTest.php b/tests/PhpSpreadsheetTests/Style/ConditionalFormatting/Wizard/WizardFactoryTest.php index c35c626e..2d4991a4 100644 --- a/tests/PhpSpreadsheetTests/Style/ConditionalFormatting/Wizard/WizardFactoryTest.php +++ b/tests/PhpSpreadsheetTests/Style/ConditionalFormatting/Wizard/WizardFactoryTest.php @@ -24,9 +24,9 @@ class WizardFactoryTest extends TestCase /** * @dataProvider basicWizardFactoryProvider * - * @param class-string $expectedWizard + * @psalm-param class-string $expectedWizard */ - public function testBasicWizardFactory(string $ruleType, $expectedWizard): void + public function testBasicWizardFactory(string $ruleType, string $expectedWizard): void { $wizard = $this->wizardFactory->newRule($ruleType); self::assertInstanceOf($expectedWizard, $wizard); @@ -54,10 +54,7 @@ class WizardFactoryTest extends TestCase $filename = 'tests/data/Style/ConditionalFormatting/CellMatcher.xlsx'; $reader = IOFactory::createReader('Xlsx'); $spreadsheet = $reader->load($filename); - $worksheet = $spreadsheet->getSheetByName($sheetName); - if ($worksheet === null) { - self::markTestSkipped("{$sheetName} not found in test workbook"); - } + $worksheet = $spreadsheet->getSheetByNameOrThrow($sheetName); $cell = $worksheet->getCell($cellAddress); $cfRange = $worksheet->getConditionalRange($cell->getCoordinate()); diff --git a/tests/PhpSpreadsheetTests/Writer/Xls/VisibilityTest.php b/tests/PhpSpreadsheetTests/Writer/Xls/VisibilityTest.php index 7de39328..8c4aa1b9 100644 --- a/tests/PhpSpreadsheetTests/Writer/Xls/VisibilityTest.php +++ b/tests/PhpSpreadsheetTests/Writer/Xls/VisibilityTest.php @@ -79,7 +79,7 @@ class VisibilityTest extends AbstractFunctional $reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xls'); foreach ($visibleSheets as $sheetName => $visibility) { - $reloadedWorksheet = $reloadedSpreadsheet->getSheetByName($sheetName) ?? new Worksheet(); + $reloadedWorksheet = $reloadedSpreadsheet->getSheetByNameOrThrow($sheetName); self::assertSame($visibility, $reloadedWorksheet->getSheetState()); } } diff --git a/tests/PhpSpreadsheetTests/Writer/Xlsx/UnparsedDataCloneTest.php b/tests/PhpSpreadsheetTests/Writer/Xlsx/UnparsedDataCloneTest.php index f9535714..eba7288f 100644 --- a/tests/PhpSpreadsheetTests/Writer/Xlsx/UnparsedDataCloneTest.php +++ b/tests/PhpSpreadsheetTests/Writer/Xlsx/UnparsedDataCloneTest.php @@ -77,19 +77,15 @@ class UnparsedDataCloneTest extends TestCase $reader1 = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx(); $spreadsheet1 = $reader1->load($resultFilename1); unlink($resultFilename1); - $sheet1c = $spreadsheet1->getSheetByName('Clone'); - self::assertNotNull($sheet1c); - $sheet1o = $spreadsheet1->getSheetByName('Original'); - self::assertNotNull($sheet1o); + $sheet1c = $spreadsheet1->getSheetByNameOrThrow('Clone'); + $sheet1o = $spreadsheet1->getSheetByNameOrThrow('Original'); $writer->save($resultFilename2); $reader2 = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx(); $spreadsheet2 = $reader2->load($resultFilename2); unlink($resultFilename2); - $sheet2c = $spreadsheet2->getSheetByName('Clone'); - self::assertNotNull($sheet2c); - $sheet2o = $spreadsheet2->getSheetByName('Original'); - self::assertNotNull($sheet2o); + $sheet2c = $spreadsheet2->getSheetByNameOrThrow('Clone'); + $sheet2o = $spreadsheet2->getSheetByNameOrThrow('Original'); self::assertEquals($spreadsheet1->getSheetCount(), $spreadsheet2->getSheetCount()); self::assertCount(1, $sheet1c->getDrawingCollection()); diff --git a/tests/PhpSpreadsheetTests/Writer/Xlsx/VisibilityTest.php b/tests/PhpSpreadsheetTests/Writer/Xlsx/VisibilityTest.php index 7e1ca967..ec2534fd 100644 --- a/tests/PhpSpreadsheetTests/Writer/Xlsx/VisibilityTest.php +++ b/tests/PhpSpreadsheetTests/Writer/Xlsx/VisibilityTest.php @@ -79,7 +79,7 @@ class VisibilityTest extends AbstractFunctional $reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xlsx'); foreach ($visibleSheets as $sheetName => $visibility) { - $reloadedWorksheet = $reloadedSpreadsheet->getSheetByName($sheetName) ?? new Worksheet(); + $reloadedWorksheet = $reloadedSpreadsheet->getSheetByNameOrThrow($sheetName); self::assertSame($visibility, $reloadedWorksheet->getSheetState()); } } diff --git a/tests/data/Calculation/Financial/IRR.php b/tests/data/Calculation/Financial/IRR.php index f6c24c13..5051182a 100644 --- a/tests/data/Calculation/Financial/IRR.php +++ b/tests/data/Calculation/Financial/IRR.php @@ -83,4 +83,5 @@ return [ -21000, ], ], + 'no arguments' => ['exception'], ]; From 6c1651e9955982186be45f578ce9c94cb61bfce4 Mon Sep 17 00:00:00 2001 From: oleibman <10341515+oleibman@users.noreply.github.com> Date: Wed, 14 Sep 2022 09:05:01 -0700 Subject: [PATCH 6/7] Floating-point Equality in Two Tests (#3064) * Floating-point Equality in Two Tests Merging a change today, Git reported failures that did not occur during "normal" unit testing. The merge still succeeded, but ... The problem was an error comparing float values for equal, and the inequality occurred beyond the 14th decimal digit. Change the tests in question, which incidentally were not part of the merged changed, to use assertEqualsWithDelta. * Egad - 112 More Precision-related Problems Spread across 9 test members. --- .../Functions/Engineering/ConvertUoMTest.php | 10 +++------- .../Calculation/Functions/Engineering/ErfCTest.php | 9 +-------- .../Functions/Engineering/ErfPreciseTest.php | 9 +-------- .../Calculation/Functions/Engineering/ErfTest.php | 9 +-------- .../Calculation/Functions/MathTrig/FactTest.php | 6 ++++-- .../Calculation/Functions/MathTrig/MUnitTest.php | 4 +++- .../Calculation/Functions/TextData/NumberValueTest.php | 6 ++++-- .../Cell/AdvancedValueBinderTest.php | 4 +++- tests/PhpSpreadsheetTests/Reader/Xlsx/XlsxTest.php | 10 ++++++---- tests/PhpSpreadsheetTests/Shared/FontTest.php | 6 ++++-- .../Shared/Trend/LinearBestFitTest.php | 10 ++++++---- 11 files changed, 36 insertions(+), 47 deletions(-) diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ConvertUoMTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ConvertUoMTest.php index 9a448824..f15725cb 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ConvertUoMTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ConvertUoMTest.php @@ -4,15 +4,11 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Engineering; use PhpOffice\PhpSpreadsheet\Calculation\Calculation; use PhpOffice\PhpSpreadsheet\Calculation\Engineering; -use PhpOffice\PhpSpreadsheet\Calculation\Functions; use PHPUnit\Framework\TestCase; class ConvertUoMTest extends TestCase { - protected function setUp(): void - { - Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL); - } + const UOM_PRECISION = 1E-12; public function testGetConversionGroups(): void { @@ -52,7 +48,7 @@ class ConvertUoMTest extends TestCase public function testCONVERTUOM($expectedResult, ...$args): void { $result = Engineering::CONVERTUOM(...$args); - self::assertEquals($expectedResult, $result); + self::assertEqualsWithDelta($expectedResult, $result, self::UOM_PRECISION); } public function providerCONVERTUOM(): array @@ -69,7 +65,7 @@ class ConvertUoMTest extends TestCase $formula = "=CONVERT({$value}, {$fromUoM}, {$toUoM})"; $result = $calculation->_calculateFormulaValue($formula); - self::assertEqualsWithDelta($expectedResult, $result, 1.0e-14); + self::assertEqualsWithDelta($expectedResult, $result, self::UOM_PRECISION); } public function providerConvertUoMArray(): array diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ErfCTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ErfCTest.php index f0a721c7..88e808ab 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ErfCTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ErfCTest.php @@ -4,18 +4,12 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Engineering; use PhpOffice\PhpSpreadsheet\Calculation\Calculation; use PhpOffice\PhpSpreadsheet\Calculation\Engineering; -use PhpOffice\PhpSpreadsheet\Calculation\Functions; use PHPUnit\Framework\TestCase; class ErfCTest extends TestCase { const ERF_PRECISION = 1E-12; - protected function setUp(): void - { - Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL); - } - /** * @dataProvider providerERFC * @@ -25,7 +19,6 @@ class ErfCTest extends TestCase public function testERFC($expectedResult, $lower): void { $result = Engineering::ERFC($lower); - self::assertEquals($expectedResult, $result); self::assertEqualsWithDelta($expectedResult, $result, self::ERF_PRECISION); } @@ -43,7 +36,7 @@ class ErfCTest extends TestCase $formula = "=ERFC({$lower})"; $result = $calculation->_calculateFormulaValue($formula); - self::assertEqualsWithDelta($expectedResult, $result, 1.0e-14); + self::assertEqualsWithDelta($expectedResult, $result, self::ERF_PRECISION); } public function providerErfCArray(): array diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ErfPreciseTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ErfPreciseTest.php index dc3ee84c..8a069ff1 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ErfPreciseTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ErfPreciseTest.php @@ -4,18 +4,12 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Engineering; use PhpOffice\PhpSpreadsheet\Calculation\Calculation; use PhpOffice\PhpSpreadsheet\Calculation\Engineering; -use PhpOffice\PhpSpreadsheet\Calculation\Functions; use PHPUnit\Framework\TestCase; class ErfPreciseTest extends TestCase { const ERF_PRECISION = 1E-12; - protected function setUp(): void - { - Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL); - } - /** * @dataProvider providerERFPRECISE * @@ -25,7 +19,6 @@ class ErfPreciseTest extends TestCase public function testERFPRECISE($expectedResult, $limit): void { $result = Engineering::ERFPRECISE($limit); - self::assertEquals($expectedResult, $result); self::assertEqualsWithDelta($expectedResult, $result, self::ERF_PRECISION); } @@ -43,7 +36,7 @@ class ErfPreciseTest extends TestCase $formula = "=ERF.PRECISE({$limit})"; $result = $calculation->_calculateFormulaValue($formula); - self::assertEqualsWithDelta($expectedResult, $result, 1.0e-14); + self::assertEqualsWithDelta($expectedResult, $result, self::ERF_PRECISION); } public function providerErfPreciseArray(): array diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ErfTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ErfTest.php index 4d13d47d..26e0381c 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ErfTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ErfTest.php @@ -4,18 +4,12 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Engineering; use PhpOffice\PhpSpreadsheet\Calculation\Calculation; use PhpOffice\PhpSpreadsheet\Calculation\Engineering; -use PhpOffice\PhpSpreadsheet\Calculation\Functions; use PHPUnit\Framework\TestCase; class ErfTest extends TestCase { const ERF_PRECISION = 1E-12; - protected function setUp(): void - { - Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL); - } - /** * @dataProvider providerERF * @@ -26,7 +20,6 @@ class ErfTest extends TestCase public function testERF($expectedResult, $lower, $upper = null): void { $result = Engineering::ERF($lower, $upper); - self::assertEquals($expectedResult, $result); self::assertEqualsWithDelta($expectedResult, $result, self::ERF_PRECISION); } @@ -44,7 +37,7 @@ class ErfTest extends TestCase $formula = "=ERF({$lower}, {$upper})"; $result = $calculation->_calculateFormulaValue($formula); - self::assertEqualsWithDelta($expectedResult, $result, 1.0e-14); + self::assertEqualsWithDelta($expectedResult, $result, self::ERF_PRECISION); } public function providerErfArray(): array diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/FactTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/FactTest.php index 328773e0..6bdfa570 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/FactTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/FactTest.php @@ -6,6 +6,8 @@ use PhpOffice\PhpSpreadsheet\Calculation\Calculation; class FactTest extends AllSetupTeardown { + const FACT_PRECISION = 1E-12; + /** * @dataProvider providerFACT * @@ -53,7 +55,7 @@ class FactTest extends AllSetupTeardown $sheet->getCell('B1')->setValue('=FACT(A1)'); } $result = $sheet->getCell('B1')->getCalculatedValue(); - self::assertEquals($expectedResult, $result); + self::assertEqualsWithDelta($expectedResult, $result, self::FACT_PRECISION); } public function providerFACTGnumeric(): array @@ -70,7 +72,7 @@ class FactTest extends AllSetupTeardown $formula = "=FACT({$array})"; $result = $calculation->_calculateFormulaValue($formula); - self::assertEqualsWithDelta($expectedResult, $result, 1.0e-14); + self::assertEqualsWithDelta($expectedResult, $result, self::FACT_PRECISION); } public function providerFactArray(): array diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/MUnitTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/MUnitTest.php index 96ebc45b..9ac68ee5 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/MUnitTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/MUnitTest.php @@ -6,6 +6,8 @@ use PhpOffice\PhpSpreadsheet\Calculation\MathTrig\MatrixFunctions; class MUnitTest extends AllSetupTeardown { + const MU_PRECISION = 1.0E-12; + public function testMUNIT(): void { $identity = MatrixFunctions::identity(3); @@ -15,7 +17,7 @@ class MUnitTest extends AllSetupTeardown self::assertEquals($startArray, $resultArray); $inverseArray = MatrixFunctions::inverse($startArray); $resultArray = MatrixFunctions::multiply($startArray, $inverseArray); - self::assertEquals($identity, $resultArray); + self::assertEqualsWithDelta($identity, $resultArray, self::MU_PRECISION); self::assertEquals('#VALUE!', MatrixFunctions::identity(0)); self::assertEquals('#VALUE!', MatrixFunctions::identity(-1)); self::assertEquals('#VALUE!', MatrixFunctions::identity('X')); diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/NumberValueTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/NumberValueTest.php index a100695f..1a909932 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/NumberValueTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/NumberValueTest.php @@ -6,6 +6,8 @@ use PhpOffice\PhpSpreadsheet\Calculation\Calculation; class NumberValueTest extends AllSetupTeardown { + const NV_PRECISION = 1.0E-8; + /** * @dataProvider providerNUMBERVALUE * @@ -34,7 +36,7 @@ class NumberValueTest extends AllSetupTeardown $sheet->getCell('B1')->setValue('=NUMBERVALUE(A1, A2, A3)'); } $result = $sheet->getCell('B1')->getCalculatedValue(); - self::assertEquals($expectedResult, $result); + self::assertEqualsWithDelta($expectedResult, $result, self::NV_PRECISION); } public function providerNUMBERVALUE(): array @@ -51,7 +53,7 @@ class NumberValueTest extends AllSetupTeardown $formula = "=NumberValue({$argument1}, {$argument2}, {$argument3})"; $result = $calculation->_calculateFormulaValue($formula); - self::assertEqualsWithDelta($expectedResult, $result, 1.0e-14); + self::assertEqualsWithDelta($expectedResult, $result, self::NV_PRECISION); } public function providerNumberValueArray(): array diff --git a/tests/PhpSpreadsheetTests/Cell/AdvancedValueBinderTest.php b/tests/PhpSpreadsheetTests/Cell/AdvancedValueBinderTest.php index 34ff2121..54f3e0cd 100644 --- a/tests/PhpSpreadsheetTests/Cell/AdvancedValueBinderTest.php +++ b/tests/PhpSpreadsheetTests/Cell/AdvancedValueBinderTest.php @@ -11,6 +11,8 @@ use PHPUnit\Framework\TestCase; class AdvancedValueBinderTest extends TestCase { + const AVB_PRECISION = 1.0E-8; + /** * @var string */ @@ -161,7 +163,7 @@ class AdvancedValueBinderTest extends TestCase $spreadsheet = new Spreadsheet(); $sheet = $spreadsheet->getActiveSheet(); $sheet->getCell('A1')->setValue($value); - self::assertEquals($valueBinded, $sheet->getCell('A1')->getValue()); + self::assertEqualsWithDelta($valueBinded, $sheet->getCell('A1')->getValue(), self::AVB_PRECISION); $spreadsheet->disconnectWorksheets(); } diff --git a/tests/PhpSpreadsheetTests/Reader/Xlsx/XlsxTest.php b/tests/PhpSpreadsheetTests/Reader/Xlsx/XlsxTest.php index e1271b9a..6b0ebf67 100644 --- a/tests/PhpSpreadsheetTests/Reader/Xlsx/XlsxTest.php +++ b/tests/PhpSpreadsheetTests/Reader/Xlsx/XlsxTest.php @@ -15,6 +15,8 @@ use PHPUnit\Framework\TestCase; class XlsxTest extends TestCase { + const XLSX_PRECISION = 1.0E-8; + public function testLoadXlsxRowColumnAttributes(): void { $filename = 'tests/data/Reader/XLSX/rowColumnAttributeTest.xlsx'; @@ -133,10 +135,10 @@ class XlsxTest extends TestCase $pageMargins = $worksheet->getPageMargins(); // Convert from inches to cm for testing - self::assertEquals(2.5, $pageMargins->getTop() * 2.54); - self::assertEquals(3.3, $pageMargins->getLeft() * 2.54); - self::assertEquals(3.3, $pageMargins->getRight() * 2.54); - self::assertEquals(1.3, $pageMargins->getHeader() * 2.54); + self::assertEqualsWithDelta(2.5, $pageMargins->getTop() * 2.54, self::XLSX_PRECISION); + self::assertEqualsWithDelta(3.3, $pageMargins->getLeft() * 2.54, self::XLSX_PRECISION); + self::assertEqualsWithDelta(3.3, $pageMargins->getRight() * 2.54, self::XLSX_PRECISION); + self::assertEqualsWithDelta(1.3, $pageMargins->getHeader() * 2.54, self::XLSX_PRECISION); self::assertEquals(PageSetup::PAPERSIZE_A4, $worksheet->getPageSetup()->getPaperSize()); self::assertEquals(['A10', 'A20', 'A30', 'A40', 'A50'], array_keys($worksheet->getBreaks())); diff --git a/tests/PhpSpreadsheetTests/Shared/FontTest.php b/tests/PhpSpreadsheetTests/Shared/FontTest.php index c733f8ee..2d5feb6e 100644 --- a/tests/PhpSpreadsheetTests/Shared/FontTest.php +++ b/tests/PhpSpreadsheetTests/Shared/FontTest.php @@ -8,6 +8,8 @@ use PHPUnit\Framework\TestCase; class FontTest extends TestCase { + const FONT_PRECISION = 1.0E-12; + public function testGetAutoSizeMethod(): void { $expectedResult = Font::AUTOSIZE_METHOD_APPROX; @@ -63,7 +65,7 @@ class FontTest extends TestCase public function testInchSizeToPixels($expectedResult, $size): void { $result = Font::inchSizeToPixels($size); - self::assertEquals($expectedResult, $result); + self::assertEqualsWithDelta($expectedResult, $result, self::FONT_PRECISION); } public function providerInchSizeToPixels(): array @@ -80,7 +82,7 @@ class FontTest extends TestCase public function testCentimeterSizeToPixels($expectedResult, $size): void { $result = Font::centimeterSizeToPixels($size); - self::assertEquals($expectedResult, $result); + self::assertEqualsWithDelta($expectedResult, $result, self::FONT_PRECISION); } public function providerCentimeterSizeToPixels(): array diff --git a/tests/PhpSpreadsheetTests/Shared/Trend/LinearBestFitTest.php b/tests/PhpSpreadsheetTests/Shared/Trend/LinearBestFitTest.php index 9ada87a5..34321227 100644 --- a/tests/PhpSpreadsheetTests/Shared/Trend/LinearBestFitTest.php +++ b/tests/PhpSpreadsheetTests/Shared/Trend/LinearBestFitTest.php @@ -7,6 +7,8 @@ use PHPUnit\Framework\TestCase; class LinearBestFitTest extends TestCase { + const LBF_PRECISION = 1.0E-8; + /** * @dataProvider providerLinearBestFit * @@ -27,13 +29,13 @@ class LinearBestFitTest extends TestCase ): void { $bestFit = new LinearBestFit($yValues, $xValues); $slope = $bestFit->getSlope(1); - self::assertEquals($expectedSlope[0], $slope); + self::assertEqualsWithDelta($expectedSlope[0], $slope, self::LBF_PRECISION); $slope = $bestFit->getSlope(); - self::assertEquals($expectedSlope[1], $slope); + self::assertEqualsWithDelta($expectedSlope[1], $slope, self::LBF_PRECISION); $intersect = $bestFit->getIntersect(1); - self::assertEquals($expectedIntersect[0], $intersect); + self::assertEqualsWithDelta($expectedIntersect[0], $intersect, self::LBF_PRECISION); $intersect = $bestFit->getIntersect(); - self::assertEquals($expectedIntersect[1], $intersect); + self::assertEqualsWithDelta($expectedIntersect[1], $intersect, self::LBF_PRECISION); $equation = $bestFit->getEquation(2); self::assertEquals($expectedEquation, $equation); From 8513c6418c61b41eebda73c4b9faaad85dd273bf Mon Sep 17 00:00:00 2001 From: oleibman <10341515+oleibman@users.noreply.github.com> Date: Wed, 14 Sep 2022 10:12:53 -0700 Subject: [PATCH 7/7] Memory Leak in Sample35 (#3062) * Memory Leak in Sample35 All but 6 chart samples can be rendered by Sample35. Of those 6, 3 of the problems are because the script runs out of memory processing them. Adopting a suggestion from @MAKS-dev in issue #2092, adding a call to gc_collect_cycles after the charts from each spreadsheet is rendered appears to make it possible to include those 3 spreadsheets in Sample35 after all. Also take advantage of this opportunity to correct a number (hopefully all) of Scrutinizer problems with JpgraphRendererBases. * Minor Fix Problem running 8.1 unit tests. * Resolve Problems with Pie 3D Charts Minor fix, leaving only one spreadsheet unusable in Sample35. The reasons for its unusability are now documented in the code. * Mitoteam Made Changes Discussing this problem with them, they decided they should make a change for Pie3D rather than forcing us to use the workaround pushed earlier. Change to require mitoteam 10.2.3, revert workaround. --- composer.json | 2 +- composer.lock | 16 ++--- samples/Chart/35_Chart_render.php | 13 ++-- .../Chart/Renderer/JpGraphRendererBase.php | 61 +++++++------------ 4 files changed, 38 insertions(+), 54 deletions(-) diff --git a/composer.json b/composer.json index 6835b05b..a4b033cd 100644 --- a/composer.json +++ b/composer.json @@ -81,7 +81,7 @@ "dealerdirect/phpcodesniffer-composer-installer": "dev-master", "dompdf/dompdf": "^1.0 || ^2.0", "friendsofphp/php-cs-fixer": "^3.2", - "mitoteam/jpgraph": "10.2.2", + "mitoteam/jpgraph": "10.2.3", "mpdf/mpdf": "8.1.1", "phpcompatibility/php-compatibility": "^9.3", "phpstan/phpstan": "^1.1", diff --git a/composer.lock b/composer.lock index 4097420d..508733ee 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "8512207f173cb137bc2085b7fdf698bc", + "content-hash": "b5bdb9f96d18ce59557436521053fdd9", "packages": [ { "name": "ezyang/htmlpurifier", @@ -1342,16 +1342,16 @@ }, { "name": "mitoteam/jpgraph", - "version": "10.2.2", + "version": "10.2.3", "source": { "type": "git", "url": "https://github.com/mitoteam/jpgraph.git", - "reference": "6d87fc342afaf8a9a898a3122b5f0f34fc82c4cf" + "reference": "21121535537e05c32e7964327b80746462a6057d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mitoteam/jpgraph/zipball/6d87fc342afaf8a9a898a3122b5f0f34fc82c4cf", - "reference": "6d87fc342afaf8a9a898a3122b5f0f34fc82c4cf", + "url": "https://api.github.com/repos/mitoteam/jpgraph/zipball/21121535537e05c32e7964327b80746462a6057d", + "reference": "21121535537e05c32e7964327b80746462a6057d", "shasum": "" }, "require": { @@ -1375,16 +1375,16 @@ "name": "JpGraph team" } ], - "description": "Composer compatible version of JpGraph library with PHP 8.2 support", + "description": "JpGraph library composer package with PHP 8.2 support", "homepage": "https://github.com/mitoteam/jpgraph", "keywords": [ "jpgraph" ], "support": { "issues": "https://github.com/mitoteam/jpgraph/issues", - "source": "https://github.com/mitoteam/jpgraph/tree/10.2.2" + "source": "https://github.com/mitoteam/jpgraph/tree/10.2.3" }, - "time": "2022-09-09T08:16:10+00:00" + "time": "2022-09-14T04:02:09+00:00" }, { "name": "mpdf/mpdf", diff --git a/samples/Chart/35_Chart_render.php b/samples/Chart/35_Chart_render.php index 891cd27c..f6dfeb46 100644 --- a/samples/Chart/35_Chart_render.php +++ b/samples/Chart/35_Chart_render.php @@ -25,12 +25,10 @@ if (count($inputFileNames) === 1) { $unresolvedErrors = []; } else { $unresolvedErrors = [ + // The following spreadsheet was created by 3rd party software, + // and doesn't include the data that usually accompanies a chart. + // That is good enough for Excel, but not for JpGraph. '32readwriteBubbleChart2.xlsx', - '32readwritePieChart3.xlsx', - '32readwritePieChart4.xlsx', - '32readwritePieChart3D1.xlsx', - '32readwritePieChartExploded1.xlsx', - '32readwritePieChartExploded3D1.xlsx', ]; } foreach ($inputFileNames as $inputFileName) { @@ -42,7 +40,9 @@ foreach ($inputFileNames as $inputFileName) { continue; } if (in_array($inputFileNameShort, $unresolvedErrors, true)) { - $helper->log('File ' . $inputFileNameShort . ' does not yet work with this script'); + $helper->log('*****'); + $helper->log('***** File ' . $inputFileNameShort . ' does not yet work with this script'); + $helper->log('*****'); continue; } @@ -92,6 +92,7 @@ foreach ($inputFileNames as $inputFileName) { $spreadsheet->disconnectWorksheets(); unset($spreadsheet); + gc_collect_cycles(); } $helper->log('Done rendering charts as images'); diff --git a/src/PhpSpreadsheet/Chart/Renderer/JpGraphRendererBase.php b/src/PhpSpreadsheet/Chart/Renderer/JpGraphRendererBase.php index d31a55b3..cb9b544b 100644 --- a/src/PhpSpreadsheet/Chart/Renderer/JpGraphRendererBase.php +++ b/src/PhpSpreadsheet/Chart/Renderer/JpGraphRendererBase.php @@ -102,13 +102,11 @@ abstract class JpGraphRendererBase implements IRenderer return $seriesPlot; } - private function formatDataSetLabels($groupID, $datasetLabels, $labelCount, $rotation = '') + private function formatDataSetLabels($groupID, $datasetLabels, $rotation = '') { - $datasetLabelFormatCode = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getFormatCode(); - if ($datasetLabelFormatCode !== null) { - // Retrieve any label formatting code - $datasetLabelFormatCode = stripslashes($datasetLabelFormatCode); - } + $datasetLabelFormatCode = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getFormatCode() ?? ''; + // Retrieve any label formatting code + $datasetLabelFormatCode = stripslashes($datasetLabelFormatCode); $testCurrentIndex = 0; foreach ($datasetLabels as $i => $datasetLabel) { @@ -273,7 +271,7 @@ abstract class JpGraphRendererBase implements IRenderer $this->renderTitle(); } - private function renderPlotLine($groupID, $filled = false, $combination = false, $dimensions = '2d'): void + private function renderPlotLine($groupID, $filled = false, $combination = false): void { $grouping = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping(); @@ -281,7 +279,7 @@ abstract class JpGraphRendererBase implements IRenderer $labelCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($index)->getPointCount(); if ($labelCount > 0) { $datasetLabels = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues(); - $datasetLabels = $this->formatDataSetLabels($groupID, $datasetLabels, $labelCount); + $datasetLabels = $this->formatDataSetLabels($groupID, $datasetLabels); $this->graph->xaxis->SetTickLabels($datasetLabels); } @@ -353,7 +351,7 @@ abstract class JpGraphRendererBase implements IRenderer $labelCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($index)->getPointCount(); if ($labelCount > 0) { $datasetLabels = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues(); - $datasetLabels = $this->formatDataSetLabels($groupID, $datasetLabels, $labelCount, $rotation); + $datasetLabels = $this->formatDataSetLabels($groupID, $datasetLabels, $rotation); // Rotate for bar rather than column chart if ($rotation == 'bar') { $datasetLabels = array_reverse($datasetLabels); @@ -430,11 +428,9 @@ abstract class JpGraphRendererBase implements IRenderer private function renderPlotScatter($groupID, $bubble): void { - $grouping = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping(); $scatterStyle = $bubbleSize = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle(); $seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount(); - $seriesPlots = []; // Loop through each data series in turn for ($i = 0; $i < $seriesCount; ++$i) { @@ -478,7 +474,6 @@ abstract class JpGraphRendererBase implements IRenderer $radarStyle = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle(); $seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount(); - $seriesPlots = []; // Loop through each data series in turn for ($i = 0; $i < $seriesCount; ++$i) { @@ -513,15 +508,11 @@ abstract class JpGraphRendererBase implements IRenderer private function renderPlotContour($groupID): void { - $contourStyle = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle(); - $seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount(); - $seriesPlots = []; $dataValues = []; // Loop through each data series in turn for ($i = 0; $i < $seriesCount; ++$i) { - $dataValuesY = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues(); $dataValuesX = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues(); $dataValues[$i] = $dataValuesX; @@ -565,7 +556,7 @@ abstract class JpGraphRendererBase implements IRenderer $labelCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount(); if ($labelCount > 0) { $datasetLabels = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues(); - $datasetLabels = $this->formatDataSetLabels($groupID, $datasetLabels, $labelCount); + $datasetLabels = $this->formatDataSetLabels($groupID, $datasetLabels); $this->graph->xaxis->SetTickLabels($datasetLabels); } @@ -575,21 +566,21 @@ abstract class JpGraphRendererBase implements IRenderer $this->graph->Add($seriesPlot); } - private function renderAreaChart($groupCount, $dimensions = '2d'): void + private function renderAreaChart($groupCount): void { $this->renderCartesianPlotArea(); for ($i = 0; $i < $groupCount; ++$i) { - $this->renderPlotLine($i, true, false, $dimensions); + $this->renderPlotLine($i, true, false); } } - private function renderLineChart($groupCount, $dimensions = '2d'): void + private function renderLineChart($groupCount): void { $this->renderCartesianPlotArea(); for ($i = 0; $i < $groupCount; ++$i) { - $this->renderPlotLine($i, false, false, $dimensions); + $this->renderPlotLine($i, false, false); } } @@ -626,19 +617,17 @@ abstract class JpGraphRendererBase implements IRenderer $iLimit = ($multiplePlots) ? $groupCount : 1; for ($groupID = 0; $groupID < $iLimit; ++$groupID) { - $grouping = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping(); $exploded = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle(); $datasetLabels = []; if ($groupID == 0) { $labelCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount(); if ($labelCount > 0) { $datasetLabels = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues(); - $datasetLabels = $this->formatDataSetLabels($groupID, $datasetLabels, $labelCount); + $datasetLabels = $this->formatDataSetLabels($groupID, $datasetLabels); } } $seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount(); - $seriesPlots = []; // For pie charts, we only display the first series: doughnut charts generally display all series $jLimit = ($multiplePlots) ? $seriesCount : 1; // Loop through each data series in turn @@ -669,7 +658,7 @@ abstract class JpGraphRendererBase implements IRenderer $seriesPlot->SetSize(($jLimit - $j) / ($jLimit * 4)); } - if ($doughnut) { + if ($doughnut && method_exists($seriesPlot, 'SetMidColor')) { $seriesPlot->SetMidColor('white'); } @@ -710,7 +699,7 @@ abstract class JpGraphRendererBase implements IRenderer } } - private function renderContourChart($groupCount, $dimensions): void + private function renderContourChart($groupCount): void { $this->renderCartesianPlotArea('intint'); @@ -719,7 +708,7 @@ abstract class JpGraphRendererBase implements IRenderer } } - private function renderCombinationChart($groupCount, $dimensions, $outputDestination) + private function renderCombinationChart($groupCount, $outputDestination) { $this->renderCartesianPlotArea(); @@ -728,10 +717,8 @@ abstract class JpGraphRendererBase implements IRenderer $chartType = $this->chart->getPlotArea()->getPlotGroupByIndex($i)->getPlotType(); switch ($chartType) { case 'area3DChart': - $dimensions = '3d'; - // no break case 'areaChart': - $this->renderPlotLine($i, true, true, $dimensions); + $this->renderPlotLine($i, true, true); break; case 'bar3DChart': @@ -742,10 +729,8 @@ abstract class JpGraphRendererBase implements IRenderer break; case 'line3DChart': - $dimensions = '3d'; - // no break case 'lineChart': - $this->renderPlotLine($i, false, true, $dimensions); + $this->renderPlotLine($i, false, true); break; case 'scatterChart': @@ -792,7 +777,7 @@ abstract class JpGraphRendererBase implements IRenderer return false; } else { - return $this->renderCombinationChart($groupCount, $dimensions, $outputDestination); + return $this->renderCombinationChart($groupCount, $outputDestination); } } @@ -801,7 +786,7 @@ abstract class JpGraphRendererBase implements IRenderer $dimensions = '3d'; // no break case 'areaChart': - $this->renderAreaChart($groupCount, $dimensions); + $this->renderAreaChart($groupCount); break; case 'bar3DChart': @@ -815,7 +800,7 @@ abstract class JpGraphRendererBase implements IRenderer $dimensions = '3d'; // no break case 'lineChart': - $this->renderLineChart($groupCount, $dimensions); + $this->renderLineChart($groupCount); break; case 'pie3DChart': @@ -845,10 +830,8 @@ abstract class JpGraphRendererBase implements IRenderer break; case 'surface3DChart': - $dimensions = '3d'; - // no break case 'surfaceChart': - $this->renderContourChart($groupCount, $dimensions); + $this->renderContourChart($groupCount); break; case 'stockChart':