diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 5a68f5579..c32d9fd3e 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -930,7 +930,7 @@ parameters: path: src/PhpSpreadsheet/Reader/Xls.php - message: "#^Unreachable statement \\- code above always terminates\\.$#" - count: 8 + count: 7 path: src/PhpSpreadsheet/Reader/Xls.php - @@ -974,10 +974,6 @@ parameters: message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\RichText\\\\Run\\:\\:\\$font \\(PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Font\\) does not accept PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Font\\|null\\.$#" count: 1 path: src/PhpSpreadsheet/RichText/Run.php - - - message: "#^Cannot access offset 1 on array\\|false\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Drawing.php - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Escher\\\\DgContainer\\:\\:getDgId\\(\\) has no return type specified\\.$#" count: 1 @@ -1422,26 +1418,6 @@ parameters: message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Trend\\\\Trend\\:\\:calculate\\(\\) has parameter \\$yValues with no type specified\\.$#" count: 1 path: src/PhpSpreadsheet/Shared/Trend/Trend.php - - - message: "#^Call to function is_array\\(\\) with string will always evaluate to false\\.$#" - count: 1 - path: src/PhpSpreadsheet/Spreadsheet.php - - - message: "#^Parameter \\#1 \\$worksheet of method PhpOffice\\\\PhpSpreadsheet\\\\Spreadsheet\\:\\:getIndex\\(\\) expects PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet, PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\|null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Spreadsheet.php - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Spreadsheet\\:\\:\\$workbookViewVisibilityValues has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Spreadsheet.php - - - message: "#^Strict comparison using \\=\\=\\= between PhpOffice\\\\PhpSpreadsheet\\\\Spreadsheet and null will always evaluate to false\\.$#" - count: 1 - path: src/PhpSpreadsheet/Spreadsheet.php - - - message: "#^Unreachable statement \\- code above always terminates\\.$#" - count: 1 - path: src/PhpSpreadsheet/Spreadsheet.php - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\ConditionalFormatting\\\\ConditionalDataBar\\:\\:setConditionalFormattingRuleExt\\(\\) has no return type specified\\.$#" count: 1 diff --git a/samples/Basic/27_Images_Xlsx.php b/samples/Basic/27_Images_Xlsx.php index dc129e46c..ebeab3c55 100644 --- a/samples/Basic/27_Images_Xlsx.php +++ b/samples/Basic/27_Images_Xlsx.php @@ -1,13 +1,26 @@ log('Load Xlsx template file'); $reader = IOFactory::createReader('Xlsx'); +// Note that Xlsx converts bmp to png, so it needs to be added +// programmatically rather than in template. +// Also note Xls converts both bmp and gif to png. $spreadsheet = $reader->load(__DIR__ . '/../templates/27template.xlsx'); +$sheet = $spreadsheet->getActiveSheet(); +$drawing = new Drawing(); +$drawing->setName('Test BMP'); +$drawing->setPath(__DIR__ . '/../images/bmp.bmp'); +$drawing->setCoordinates('G17'); +$drawing->setWorksheet($sheet); + +$sheet->getCell('G16')->setValue('BMP'); +$sheet->getStyle('G16')->getFont()->setName('Arial Black')->setBold(true); // Save $helper->write($spreadsheet, __FILE__); diff --git a/samples/templates/27template.xlsx b/samples/templates/27template.xlsx index f897d2e05..9651f1735 100644 Binary files a/samples/templates/27template.xlsx and b/samples/templates/27template.xlsx differ diff --git a/src/PhpSpreadsheet/Calculation/Engineering/ConvertUOM.php b/src/PhpSpreadsheet/Calculation/Engineering/ConvertUOM.php index b7c298dbc..8541a6cc1 100644 --- a/src/PhpSpreadsheet/Calculation/Engineering/ConvertUOM.php +++ b/src/PhpSpreadsheet/Calculation/Engineering/ConvertUOM.php @@ -564,7 +564,7 @@ class ConvertUOM } elseif ($fromUOM === $toUOM) { return $value / $toMultiplier; } elseif ($fromCategory === self::CATEGORY_TEMPERATURE) { - return self::convertTemperature($fromUOM, $toUOM, $value); + return self::convertTemperature($fromUOM, $toUOM, /** @scrutinizer ignore-type */ $value); } $baseValue = $value * (1.0 / self::$unitConversions[$fromCategory][$fromUOM]); diff --git a/src/PhpSpreadsheet/Calculation/Statistical/Conditional.php b/src/PhpSpreadsheet/Calculation/Statistical/Conditional.php index 51e6b0043..0f39c0465 100644 --- a/src/PhpSpreadsheet/Calculation/Statistical/Conditional.php +++ b/src/PhpSpreadsheet/Calculation/Statistical/Conditional.php @@ -218,7 +218,8 @@ class Conditional { $conditions = self::buildConditions(1, ...$args); - return array_map(null, ...$conditions); + // Scrutinizer thinks first parameter of array_map can't be null. It is wrong. + return array_map(/** @scrutinizer ignore-type */ null, ...$conditions); } private static function buildConditionSetForValueRange(...$args): array @@ -234,7 +235,7 @@ class Conditional ); } - return array_map(null, ...$conditions); + return array_map(/** @scrutinizer ignore-type */ null, ...$conditions); } private static function buildConditions(int $startOffset, ...$args): array @@ -281,7 +282,7 @@ class Conditional ++$pairCount; } - return array_map(null, ...$database); + return array_map(/** @scrutinizer ignore-type */ null, ...$database); } private static function databaseFromRangeAndValue(array $range, array $valueRange = []): array @@ -293,11 +294,7 @@ class Conditional $valueRange = $range; } - $database = array_map( - null, - array_merge([self::CONDITION_COLUMN_NAME], $range), - array_merge([self::VALUE_COLUMN_NAME], $valueRange) - ); + $database = array_map(/** @scrutinizer ignore-type */ null, array_merge([self::CONDITION_COLUMN_NAME], $range), array_merge([self::VALUE_COLUMN_NAME], $valueRange)); return $database; } diff --git a/src/PhpSpreadsheet/Calculation/Statistical/Distributions/Beta.php b/src/PhpSpreadsheet/Calculation/Statistical/Distributions/Beta.php index 51cb6411b..8b41ac87f 100644 --- a/src/PhpSpreadsheet/Calculation/Statistical/Distributions/Beta.php +++ b/src/PhpSpreadsheet/Calculation/Statistical/Distributions/Beta.php @@ -268,6 +268,7 @@ class Beta return $frac; } + /* private static function betaValue(float $a, float $b): float { return (Gamma::gammaValue($a) * Gamma::gammaValue($b)) / @@ -278,4 +279,5 @@ class Beta { return self::incompleteBeta($value, $a, $b) / self::betaValue($a, $b); } + */ } diff --git a/src/PhpSpreadsheet/Calculation/TextData/Extract.php b/src/PhpSpreadsheet/Calculation/TextData/Extract.php index ee7e31b77..4d0a8ab9e 100644 --- a/src/PhpSpreadsheet/Calculation/TextData/Extract.php +++ b/src/PhpSpreadsheet/Calculation/TextData/Extract.php @@ -138,7 +138,7 @@ class Extract $matchEnd = (int) $matchEnd; $split = self::validateTextBeforeAfter($text, $delimiter, $instance, $matchMode, $matchEnd, $ifNotFound); - if (is_array($split) === false) { + if (is_string($split)) { return $split; } if (Helpers::extractString(Functions::flattenSingleValue($delimiter ?? '')) === '') { @@ -196,7 +196,7 @@ class Extract $matchEnd = (int) $matchEnd; $split = self::validateTextBeforeAfter($text, $delimiter, $instance, $matchMode, $matchEnd, $ifNotFound); - if (is_array($split) === false) { + if (is_string($split)) { return $split; } if (Helpers::extractString(Functions::flattenSingleValue($delimiter ?? '')) === '') { @@ -222,7 +222,7 @@ class Extract * @param int $matchEnd * @param mixed $ifNotFound * - * @return string|string[] + * @return array|string */ private static function validateTextBeforeAfter(string $text, $delimiter, int $instance, $matchMode, $matchEnd, $ifNotFound) { diff --git a/src/PhpSpreadsheet/Calculation/TextData/Replace.php b/src/PhpSpreadsheet/Calculation/TextData/Replace.php index 03b663211..124f00170 100644 --- a/src/PhpSpreadsheet/Calculation/TextData/Replace.php +++ b/src/PhpSpreadsheet/Calculation/TextData/Replace.php @@ -102,24 +102,17 @@ class Replace return $returnValue; } - /** - * @return string - */ - private static function executeSubstitution(string $text, string $fromText, string $toText, int $instance) + private static function executeSubstitution(string $text, string $fromText, string $toText, int $instance): string { $pos = -1; while ($instance > 0) { $pos = mb_strpos($text, $fromText, $pos + 1, 'UTF-8'); if ($pos === false) { - break; + return $text; } --$instance; } - if ($pos !== false) { - return Functions::scalar(self::REPLACE($text, ++$pos, StringHelper::countCharacters($fromText), $toText)); - } - - return $text; + return Functions::scalar(self::REPLACE($text, ++$pos, StringHelper::countCharacters($fromText), $toText)); } } diff --git a/src/PhpSpreadsheet/Helper/Sample.php b/src/PhpSpreadsheet/Helper/Sample.php index a0063bd33..5ca546e07 100644 --- a/src/PhpSpreadsheet/Helper/Sample.php +++ b/src/PhpSpreadsheet/Helper/Sample.php @@ -131,7 +131,7 @@ class Sample $writer = IOFactory::createWriter($spreadsheet, $writerType); $callStartTime = microtime(true); $writer->save($path); - $this->logWrite($writer, $path, $callStartTime); + $this->logWrite($writer, $path, /** @scrutinizer ignore-type */ $callStartTime); } $this->logEndingNotes(); @@ -169,7 +169,7 @@ class Sample { $originalExtension = pathinfo($filename, PATHINFO_EXTENSION); - return $this->getTemporaryFolder() . '/' . str_replace('.' . $originalExtension, '.' . $extension, basename($filename)); + return $this->getTemporaryFolder() . '/' . str_replace('.' . /** @scrutinizer ignore-type */ $originalExtension, '.' . $extension, basename($filename)); } /** diff --git a/src/PhpSpreadsheet/Helper/TextGrid.php b/src/PhpSpreadsheet/Helper/TextGrid.php index acb9ae60e..ed146a55d 100644 --- a/src/PhpSpreadsheet/Helper/TextGrid.php +++ b/src/PhpSpreadsheet/Helper/TextGrid.php @@ -52,7 +52,7 @@ class TextGrid $maxRow = max($this->rows); $maxRowLength = strlen((string) $maxRow) + 1; - $columnWidths = $this->getColumnWidths($this->matrix); + $columnWidths = $this->getColumnWidths(); $this->renderColumnHeader($maxRowLength, $columnWidths); $this->renderRows($maxRowLength, $columnWidths); @@ -108,7 +108,7 @@ class TextGrid $this->gridDisplay .= '+' . PHP_EOL; } - private function getColumnWidths(array $matrix): array + private function getColumnWidths(): array { $columnCount = count($this->matrix, COUNT_RECURSIVE) / count($this->matrix); $columnWidths = []; diff --git a/src/PhpSpreadsheet/Reader/Csv.php b/src/PhpSpreadsheet/Reader/Csv.php index 65a71edb0..4f128d6f0 100644 --- a/src/PhpSpreadsheet/Reader/Csv.php +++ b/src/PhpSpreadsheet/Reader/Csv.php @@ -555,7 +555,7 @@ class Csv extends BaseReader fclose($this->fileHandle); // Trust file extension if any - $extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION)); + $extension = strtolower(/** @scrutinizer ignore-type */ pathinfo($filename, PATHINFO_EXTENSION)); if (in_array($extension, ['csv', 'tsv'])) { return true; } diff --git a/src/PhpSpreadsheet/Reader/Xls.php b/src/PhpSpreadsheet/Reader/Xls.php index a79a20a9c..bdec4c93c 100644 --- a/src/PhpSpreadsheet/Reader/Xls.php +++ b/src/PhpSpreadsheet/Reader/Xls.php @@ -4947,8 +4947,6 @@ class Xls extends BaseReader case 0x28: // TODO: Investigate structure for .xls SHEETLAYOUT record as saved by MS Office Excel 2007 return; - - break; } } } diff --git a/src/PhpSpreadsheet/Reader/Xlsx/Chart.php b/src/PhpSpreadsheet/Reader/Xlsx/Chart.php index 93e0c5d98..d42df9a37 100644 --- a/src/PhpSpreadsheet/Reader/Xlsx/Chart.php +++ b/src/PhpSpreadsheet/Reader/Xlsx/Chart.php @@ -832,6 +832,7 @@ class Chart foreach ($seriesValueSet->lvl as $seriesLevelIdx => $seriesLevel) { foreach ($seriesLevel as $seriesValueIdx => $seriesValue) { + $seriesValue = Xlsx::testSimpleXml($seriesValue); switch ($seriesValueIdx) { case 'ptCount': $pointCount = self::getAttribute($seriesValue, 'val', 'integer'); diff --git a/src/PhpSpreadsheet/Reader/Xlsx/Styles.php b/src/PhpSpreadsheet/Reader/Xlsx/Styles.php index 8d380907a..5b089fa87 100644 --- a/src/PhpSpreadsheet/Reader/Xlsx/Styles.php +++ b/src/PhpSpreadsheet/Reader/Xlsx/Styles.php @@ -278,7 +278,7 @@ class Styles extends BaseParserClass */ public function readStyle(Style $docStyle, $style): void { - if ($style->numFmt instanceof SimpleXMLElement) { + if ($style instanceof SimpleXMLElement) { $this->readNumberFormat($docStyle->getNumberFormat(), $style->numFmt); } else { $docStyle->getNumberFormat()->setFormatCode(self::formatGeneral((string) $style->numFmt)); diff --git a/src/PhpSpreadsheet/Reader/Xml.php b/src/PhpSpreadsheet/Reader/Xml.php index d8f0d9dcd..565a5af75 100644 --- a/src/PhpSpreadsheet/Reader/Xml.php +++ b/src/PhpSpreadsheet/Reader/Xml.php @@ -278,7 +278,7 @@ class Xml extends BaseReader if ( isset($this->loadSheetsOnly, $worksheet_ss['Name']) && - (!in_array($worksheet_ss['Name'], $this->loadSheetsOnly)) + (!in_array($worksheet_ss['Name'], /** @scrutinizer ignore-type */ $this->loadSheetsOnly)) ) { continue; } diff --git a/src/PhpSpreadsheet/Shared/Drawing.php b/src/PhpSpreadsheet/Shared/Drawing.php index 3378958c8..f69310fc6 100644 --- a/src/PhpSpreadsheet/Shared/Drawing.php +++ b/src/PhpSpreadsheet/Shared/Drawing.php @@ -3,6 +3,7 @@ namespace PhpOffice\PhpSpreadsheet\Shared; use GdImage; +use PhpOffice\PhpSpreadsheet\Reader\Exception as ReaderException; use SimpleXMLElement; class Drawing @@ -159,109 +160,18 @@ class Drawing * @param string $bmpFilename Path to Windows DIB (BMP) image * * @return GdImage|resource + * + * @deprecated 1.26 use Php function imagecreatefrombmp instead + * + * @codeCoverageIgnore */ public static function imagecreatefrombmp($bmpFilename) { - // Load the image into a string - $file = fopen($bmpFilename, 'rb'); - /** @phpstan-ignore-next-line */ - $read = fread($file, 10); - // @phpstan-ignore-next-line - while (!feof($file) && ($read != '')) { - // @phpstan-ignore-next-line - $read .= fread($file, 1024); + $retVal = @imagecreatefrombmp($bmpFilename); + if ($retVal === false) { + throw new ReaderException("Unable to create image from $bmpFilename"); } - /** @phpstan-ignore-next-line */ - $temp = unpack('H*', $read); - $hex = $temp[1]; - $header = substr($hex, 0, 108); - - // Process the header - // Structure: http://www.fastgraph.com/help/bmp_header_format.html - $width = 0; - $height = 0; - if (substr($header, 0, 4) == '424d') { - // Cut it in parts of 2 bytes - $header_parts = str_split($header, 2); - - // Get the width 4 bytes - $width = hexdec($header_parts[19] . $header_parts[18]); - - // Get the height 4 bytes - $height = hexdec($header_parts[23] . $header_parts[22]); - - // Unset the header params - unset($header_parts); - } - - // Define starting X and Y - $x = 0; - $y = 1; - - // Create newimage - - /** @phpstan-ignore-next-line */ - $image = imagecreatetruecolor($width, $height); - - // Grab the body from the image - $body = substr($hex, 108); - - // Calculate if padding at the end-line is needed - // Divided by two to keep overview. - // 1 byte = 2 HEX-chars - $body_size = (strlen($body) / 2); - $header_size = ($width * $height); - - // Use end-line padding? Only when needed - $usePadding = ($body_size > ($header_size * 3) + 4); - - // Using a for-loop with index-calculation instaid of str_split to avoid large memory consumption - // Calculate the next DWORD-position in the body - for ($i = 0; $i < $body_size; $i += 3) { - // Calculate line-ending and padding - if ($x >= $width) { - // If padding needed, ignore image-padding - // Shift i to the ending of the current 32-bit-block - if ($usePadding) { - $i += $width % 4; - } - - // Reset horizontal position - $x = 0; - - // Raise the height-position (bottom-up) - ++$y; - - // Reached the image-height? Break the for-loop - if ($y > $height) { - break; - } - } - - // Calculation of the RGB-pixel (defined as BGR in image-data) - // Define $i_pos as absolute position in the body - $i_pos = $i * 2; - $r = hexdec($body[$i_pos + 4] . $body[$i_pos + 5]); - $g = hexdec($body[$i_pos + 2] . $body[$i_pos + 3]); - $b = hexdec($body[$i_pos] . $body[$i_pos + 1]); - - // Calculate and draw the pixel - - /** @phpstan-ignore-next-line */ - $color = imagecolorallocate($image, $r, $g, $b); - // @phpstan-ignore-next-line - imagesetpixel($image, $x, $height - $y, $color); - - // Raise the horizontal position - ++$x; - } - - // Unset the body / free the memory - unset($body); - - // Return image-object - // @phpstan-ignore-next-line - return $image; + return $retVal; } } diff --git a/src/PhpSpreadsheet/Shared/Font.php b/src/PhpSpreadsheet/Shared/Font.php index e90c679b6..dfe9f77ae 100644 --- a/src/PhpSpreadsheet/Shared/Font.php +++ b/src/PhpSpreadsheet/Shared/Font.php @@ -348,8 +348,8 @@ class Font } // Special case if there are one or more newline characters ("\n") - $cellText = $cellText ?? ''; - if (strpos(/** @scrutinizer ignore-type */ $cellText, "\n") !== false) { + $cellText = (string) $cellText; + if (strpos($cellText, "\n") !== false) { $lineTexts = explode("\n", $cellText); $lineWidths = []; foreach ($lineTexts as $lineText) { diff --git a/src/PhpSpreadsheet/Shared/PasswordHasher.php b/src/PhpSpreadsheet/Shared/PasswordHasher.php index 0d58a8686..e9414f97e 100644 --- a/src/PhpSpreadsheet/Shared/PasswordHasher.php +++ b/src/PhpSpreadsheet/Shared/PasswordHasher.php @@ -99,7 +99,7 @@ class PasswordHasher $saltValue = base64_decode($salt); $encodedPassword = mb_convert_encoding($password, 'UCS-2LE', 'UTF-8'); - $hashValue = hash($phpAlgorithm, $saltValue . $encodedPassword, true); + $hashValue = hash($phpAlgorithm, $saltValue . /** @scrutinizer ignore-type */ $encodedPassword, true); for ($i = 0; $i < $spinCount; ++$i) { $hashValue = hash($phpAlgorithm, $hashValue . pack('L', $i), true); } diff --git a/src/PhpSpreadsheet/Shared/Trend/BestFit.php b/src/PhpSpreadsheet/Shared/Trend/BestFit.php index 7df489533..b2b0d9440 100644 --- a/src/PhpSpreadsheet/Shared/Trend/BestFit.php +++ b/src/PhpSpreadsheet/Shared/Trend/BestFit.php @@ -332,9 +332,21 @@ abstract class BestFit return $this->yBestFitValues; } + /** @var mixed */ + private static $scrutinizerZeroPointZero = 0.0; + + /** + * @param mixed $x + * @param mixed $y + */ + private static function scrutinizerLooseCompare($x, $y): bool + { + return $x == $y; + } + protected function calculateGoodnessOfFit($sumX, $sumY, $sumX2, $sumY2, $sumXY, $meanX, $meanY, $const): void { - $SSres = $SScov = $SScor = $SStot = $SSsex = 0.0; + $SSres = $SScov = $SStot = $SSsex = 0.0; foreach ($this->xValues as $xKey => $xValue) { $bestFitY = $this->yBestFitValues[$xKey] = $this->getValueOfYForX($xValue); @@ -360,7 +372,8 @@ abstract class BestFit } else { $this->stdevOfResiduals = sqrt($SSres / $this->DFResiduals); } - if (($SStot == 0.0) || ($SSres == $SStot)) { + // Scrutinizer thinks $SSres == $SStot is always true. It is wrong. + if ($SStot == self::$scrutinizerZeroPointZero || self::scrutinizerLooseCompare($SSres, $SStot)) { $this->goodnessOfFit = 1; } else { $this->goodnessOfFit = 1 - ($SSres / $SStot); diff --git a/src/PhpSpreadsheet/Spreadsheet.php b/src/PhpSpreadsheet/Spreadsheet.php index 364700e25..4624ec0ad 100644 --- a/src/PhpSpreadsheet/Spreadsheet.php +++ b/src/PhpSpreadsheet/Spreadsheet.php @@ -21,7 +21,7 @@ class Spreadsheet private const DEFINED_NAME_IS_RANGE = false; private const DEFINED_NAME_IS_FORMULA = true; - private static $workbookViewVisibilityValues = [ + private const WORKBOOK_VIEW_VISIBILITY_VALUES = [ self::VISIBILITY_VISIBLE, self::VISIBILITY_HIDDEN, self::VISIBILITY_VERY_HIDDEN, @@ -376,7 +376,7 @@ class Spreadsheet { $extension = pathinfo($path, PATHINFO_EXTENSION); - return is_array($extension) ? '' : $extension; + return substr(/** @scrutinizer ignore-type */$extension, 0); } /** @@ -393,8 +393,6 @@ class Spreadsheet switch ($what) { case 'all': return $this->ribbonBinObjects; - - break; case 'names': case 'data': if (is_array($this->ribbonBinObjects) && isset($this->ribbonBinObjects[$what])) { @@ -644,7 +642,7 @@ class Spreadsheet } } - if ($worksheet->getParent() === null) { + if ($worksheet->getParent() === null) { // @phpstan-ignore-line $worksheet->rebindParent($this); } @@ -763,7 +761,7 @@ class Spreadsheet */ public function setIndexByName($worksheetName, $newIndexPosition) { - $oldIndex = $this->getIndex($this->getSheetByName($worksheetName)); + $oldIndex = $this->getIndex($this->getSheetByNameOrThrow($worksheetName)); $worksheet = array_splice( $this->workSheetCollection, $oldIndex, @@ -1582,7 +1580,7 @@ class Spreadsheet $visibility = self::VISIBILITY_VISIBLE; } - if (in_array($visibility, self::$workbookViewVisibilityValues)) { + if (in_array($visibility, self::WORKBOOK_VIEW_VISIBILITY_VALUES)) { $this->visibility = $visibility; } else { throw new Exception('Invalid visibility value.'); diff --git a/src/PhpSpreadsheet/Style/NumberFormat/DateFormatter.php b/src/PhpSpreadsheet/Style/NumberFormat/DateFormatter.php index 6c4d9d6ba..ba54b5359 100644 --- a/src/PhpSpreadsheet/Style/NumberFormat/DateFormatter.php +++ b/src/PhpSpreadsheet/Style/NumberFormat/DateFormatter.php @@ -177,6 +177,6 @@ class DateFormatter private static function escapeQuotesCallback(array $matches): string { - return '\\' . implode('\\', str_split($matches[1])); + return '\\' . implode('\\', /** @scrutinizer ignore-type */ str_split($matches[1])); } } diff --git a/src/PhpSpreadsheet/Worksheet/PageSetup.php b/src/PhpSpreadsheet/Worksheet/PageSetup.php index 07c4b4127..93030dbd1 100644 --- a/src/PhpSpreadsheet/Worksheet/PageSetup.php +++ b/src/PhpSpreadsheet/Worksheet/PageSetup.php @@ -746,15 +746,14 @@ class PageSetup if ($index == 0) { $this->printArea = $this->printArea ? ($this->printArea . ',' . $value) : $value; } else { - /** @phpstan-ignore-next-line */ - $printAreas = explode(',', $this->printArea); + $printAreas = explode(',', (string) $this->printArea); if ($index < 0) { - $index = abs($index) - 1; + $index = (int) abs($index) - 1; } if ($index > count($printAreas)) { throw new PhpSpreadsheetException('Invalid index for setting print range.'); } - $printAreas = array_merge(array_slice($printAreas, 0, /** @scrutinizer ignore-type */ $index), [$value], array_slice($printAreas, /** @scrutinizer ignore-type */ $index)); + $printAreas = array_merge(array_slice($printAreas, 0, $index), [$value], array_slice($printAreas, $index)); $this->printArea = implode(',', $printAreas); } } else { diff --git a/src/PhpSpreadsheet/Writer/Xls.php b/src/PhpSpreadsheet/Writer/Xls.php index 69457357b..b740b6ffe 100644 --- a/src/PhpSpreadsheet/Writer/Xls.php +++ b/src/PhpSpreadsheet/Writer/Xls.php @@ -8,7 +8,6 @@ use PhpOffice\PhpSpreadsheet\Cell\Cell; use PhpOffice\PhpSpreadsheet\Cell\Coordinate; use PhpOffice\PhpSpreadsheet\RichText\RichText; use PhpOffice\PhpSpreadsheet\RichText\Run; -use PhpOffice\PhpSpreadsheet\Shared\Drawing as SharedDrawing; use PhpOffice\PhpSpreadsheet\Shared\Escher; use PhpOffice\PhpSpreadsheet\Shared\Escher\DgContainer; use PhpOffice\PhpSpreadsheet\Shared\Escher\DgContainer\SpgrContainer; @@ -435,9 +434,12 @@ class Xls extends BaseWriter switch ($imageFormat) { case 1: // GIF, not supported by BIFF8, we convert to PNG $blipType = BSE::BLIPTYPE_PNG; + $newImage = @imagecreatefromgif($filename); + if ($newImage === false) { + throw new Exception("Unable to create image from $filename"); + } ob_start(); - // @phpstan-ignore-next-line - imagepng(imagecreatefromgif($filename)); + imagepng($newImage); $blipData = ob_get_contents(); ob_end_clean(); @@ -454,9 +456,12 @@ class Xls extends BaseWriter break; case 6: // Windows DIB (BMP), we convert to PNG $blipType = BSE::BLIPTYPE_PNG; + $newImage = @imagecreatefrombmp($filename); + if ($newImage === false) { + throw new Exception("Unable to create image from $filename"); + } ob_start(); - // @phpstan-ignore-next-line - imagepng(SharedDrawing::imagecreatefrombmp($filename)); + imagepng($newImage); $blipData = ob_get_contents(); ob_end_clean(); diff --git a/tests/PhpSpreadsheetTests/Writer/Xls/XlsGifBmpTest.php b/tests/PhpSpreadsheetTests/Writer/Xls/XlsGifBmpTest.php index d1353fa35..412ca45be 100644 --- a/tests/PhpSpreadsheetTests/Writer/Xls/XlsGifBmpTest.php +++ b/tests/PhpSpreadsheetTests/Writer/Xls/XlsGifBmpTest.php @@ -3,6 +3,7 @@ namespace PhpOffice\PhpSpreadsheetTests\Writer\Xls; use DateTime; +use PhpOffice\PhpSpreadsheet\Reader\Exception as ReaderException; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Worksheet\Drawing; use PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing; @@ -40,13 +41,13 @@ class XlsGifBmpTest extends AbstractFunctional $drawing->setCoordinates('A1'); $reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xls'); + $spreadsheet->disconnectWorksheets(); $creationDatestamp = $reloadedSpreadsheet->getProperties()->getCreated(); $filstart = $creationDatestamp; $worksheet = $reloadedSpreadsheet->getActiveSheet(); $drawings = $worksheet->getDrawingCollection(); self::assertCount(1, $drawings); foreach ($worksheet->getDrawingCollection() as $drawing) { - // See if Scrutinizer approves this $mimeType = ($drawing instanceof MemoryDrawing) ? $drawing->getMimeType() : 'notmemorydrawing'; self::assertEquals('image/png', $mimeType); } @@ -55,6 +56,7 @@ class XlsGifBmpTest extends AbstractFunctional self::assertLessThanOrEqual($pgmend, $pgmstart); self::assertLessThanOrEqual($pgmend, $filstart); self::assertLessThanOrEqual($filstart, $pgmstart); + $reloadedSpreadsheet->disconnectWorksheets(); } public function testGif(): void @@ -71,6 +73,7 @@ class XlsGifBmpTest extends AbstractFunctional $drawing->setCoordinates('A1'); $reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xls'); + $spreadsheet->disconnectWorksheets(); $worksheet = $reloadedSpreadsheet->getActiveSheet(); $drawings = $worksheet->getDrawingCollection(); self::assertCount(1, $drawings); @@ -78,11 +81,13 @@ class XlsGifBmpTest extends AbstractFunctional $mimeType = ($drawing instanceof MemoryDrawing) ? $drawing->getMimeType() : 'notmemorydrawing'; self::assertEquals('image/png', $mimeType); } + $reloadedSpreadsheet->disconnectWorksheets(); } public function testInvalidTimestamp(): void { - $this->expectException(\PhpOffice\PhpSpreadsheet\Reader\Exception::class); + $this->expectException(ReaderException::class); + $this->expectExceptionMessage('Expecting 8 byte string'); \PhpOffice\PhpSpreadsheet\Shared\OLE::OLE2LocalDate(' '); } }