diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ce38f646..87d933e2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -124,6 +124,37 @@ jobs: - name: Code style with PHP_CodeSniffer run: ./vendor/bin/phpcs -q --report=checkstyle | cs2pr + phpstan: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Setup PHP, with composer and extensions + uses: shivammathur/setup-php@v2 + with: + php-version: 7.4 + extensions: ctype, dom, gd, iconv, fileinfo, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib + coverage: none + tools: cs2pr + + - name: Get composer cache directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Cache composer dependencies + uses: actions/cache@v2 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install dependencies + run: composer install --no-progress --prefer-dist --optimize-autoloader + + - name: Static analysis with PHPStan + run: ./vendor/bin/phpstan analyse + coverage: runs-on: ubuntu-latest steps: diff --git a/composer.json b/composer.json index 3b4ed556..d0c3a16d 100644 --- a/composer.json +++ b/composer.json @@ -41,7 +41,8 @@ "check": [ "php-cs-fixer fix --ansi --dry-run --diff", "phpcs", - "phpunit --color=always" + "phpunit --color=always", + "phpstan analyse --ansi" ], "fix": [ "php-cs-fixer fix --ansi" @@ -79,6 +80,7 @@ "jpgraph/jpgraph": "^4.0", "mpdf/mpdf": "^8.0", "phpcompatibility/php-compatibility": "^9.3", + "phpstan/phpstan": "^0.12.82", "phpunit/phpunit": "^8.5", "squizlabs/php_codesniffer": "^3.5", "tecnickcom/tcpdf": "^6.3" diff --git a/composer.lock b/composer.lock index 3f6efb00..e4060972 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": "6c8f34baf3385a533fade30a9a9ad6f1", + "content-hash": "89b62d75519340c289a3a763245f1ca0", "packages": [ { "name": "ezyang/htmlpurifier", @@ -1963,6 +1963,66 @@ }, "time": "2021-03-17T13:42:18+00:00" }, + { + "name": "phpstan/phpstan", + "version": "0.12.82", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "3920f0fb0aff39263d3a4cb0bca120a67a1a6a11" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/3920f0fb0aff39263d3a4cb0bca120a67a1a6a11", + "reference": "3920f0fb0aff39263d3a4cb0bca120a67a1a6a11", + "shasum": "" + }, + "require": { + "php": "^7.1|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.12-dev" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "support": { + "issues": "https://github.com/phpstan/phpstan/issues", + "source": "https://github.com/phpstan/phpstan/tree/0.12.82" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://www.patreon.com/phpstan", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", + "type": "tidelift" + } + ], + "time": "2021-03-19T06:08:17+00:00" + }, { "name": "phpunit/php-code-coverage", "version": "7.0.14", diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 00000000..476513dc --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,11 @@ +parameters: + level: 1 + paths: + - src/ + - tests/ + ignoreErrors: + - '~^Class GdImage not found\.$~' + + # Ignore all JpGraph issues + - '~^Constant (MARK_CIRCLE|MARK_CROSS|MARK_DIAMOND|MARK_DTRIANGLE|MARK_FILLEDCIRCLE|MARK_SQUARE|MARK_STAR|MARK_UTRIANGLE|MARK_X|SIDE_RIGHT) not found\.$~' + - '~^Instantiated class (AccBarPlot|AccLinePlot|BarPlot|ContourPlot|Graph|GroupBarPlot|GroupBarPlot|LinePlot|LinePlot|PieGraph|PiePlot|PiePlot3D|PiePlotC|RadarGraph|RadarPlot|ScatterPlot|Spline|StockPlot) not found\.$~' diff --git a/src/PhpSpreadsheet/Calculation/Calculation.php b/src/PhpSpreadsheet/Calculation/Calculation.php index 967d05e5..0aa2a6da 100644 --- a/src/PhpSpreadsheet/Calculation/Calculation.php +++ b/src/PhpSpreadsheet/Calculation/Calculation.php @@ -3154,6 +3154,7 @@ class Calculation // Return Excel errors "as is" return $value; } + // Return strings wrapped in quotes return self::FORMULA_STRING_QUOTE . $value . self::FORMULA_STRING_QUOTE; } elseif ((is_float($value)) && ((is_nan($value)) || (is_infinite($value)))) { @@ -3794,13 +3795,13 @@ class Calculation $pCellParent = ($pCell !== null) ? $pCell->getWorksheet() : null; $regexpMatchString = '/^(' . self::CALCULATION_REGEXP_FUNCTION . - '|' . self::CALCULATION_REGEXP_CELLREF . - '|' . self::CALCULATION_REGEXP_NUMBER . - '|' . self::CALCULATION_REGEXP_STRING . - '|' . self::CALCULATION_REGEXP_OPENBRACE . - '|' . self::CALCULATION_REGEXP_DEFINEDNAME . - '|' . self::CALCULATION_REGEXP_ERROR . - ')/sui'; + '|' . self::CALCULATION_REGEXP_CELLREF . + '|' . self::CALCULATION_REGEXP_NUMBER . + '|' . self::CALCULATION_REGEXP_STRING . + '|' . self::CALCULATION_REGEXP_OPENBRACE . + '|' . self::CALCULATION_REGEXP_DEFINEDNAME . + '|' . self::CALCULATION_REGEXP_ERROR . + ')/sui'; // Start with initialisation $index = 0; @@ -3939,6 +3940,7 @@ class Calculation } // Check the argument count $argumentCountError = false; + $expectedArgumentCountString = null; if (is_numeric($expectedArgumentCount)) { if ($expectedArgumentCount < 0) { if ($argumentCount > abs($expectedArgumentCount)) { @@ -4203,7 +4205,7 @@ class Calculation ((preg_match('/^' . self::CALCULATION_REGEXP_CELLREF . '.*/Ui', substr($formula, $index), $match)) && ($output[count($output) - 1]['type'] == 'Cell Reference') || (preg_match('/^' . self::CALCULATION_REGEXP_DEFINEDNAME . '.*/miu', substr($formula, $index), $match)) && - ($output[count($output) - 1]['type'] == 'Defined Name' || $output[count($output) - 1]['type'] == 'Value') + ($output[count($output) - 1]['type'] == 'Defined Name' || $output[count($output) - 1]['type'] == 'Value') ) ) { while ( @@ -4645,6 +4647,9 @@ class Calculation $this->debugLog->writeDebugLog('Evaluating Function ', self::localeFunc($functionName), '() with ', (($argCount == 0) ? 'no' : $argCount), ' argument', (($argCount == 1) ? '' : 's')); } if ((isset(self::$phpSpreadsheetFunctions[$functionName])) || (isset(self::$controlFunctions[$functionName]))) { // function + $passByReference = false; + $passCellReference = false; + $functionCall = null; if (isset(self::$phpSpreadsheetFunctions[$functionName])) { $functionCall = self::$phpSpreadsheetFunctions[$functionName]['functionCall']; $passByReference = isset(self::$phpSpreadsheetFunctions[$functionName]['passByReference']); @@ -4945,6 +4950,9 @@ class Calculation } break; + + default: + throw new Exception('Unsupported binary comparison operation'); } // Log the result details @@ -5062,6 +5070,9 @@ class Calculation $result = $operand1 ** $operand2; break; + + default: + throw new Exception('Unsupported numeric binary operation'); } } } diff --git a/src/PhpSpreadsheet/Calculation/DateTime.php b/src/PhpSpreadsheet/Calculation/DateTime.php index 744d9589..e3580cde 100644 --- a/src/PhpSpreadsheet/Calculation/DateTime.php +++ b/src/PhpSpreadsheet/Calculation/DateTime.php @@ -651,7 +651,7 @@ class DateTime * * Returns the ISO 8601 week number of the year for a specified date. * - * @Deprecated 2.0.0 Use the funcIsoWeeknum method in the DateTimeExcel\Isoweeknum class instead + * @Deprecated 2.0.0 Use the funcIsoWeeknum method in the DateTimeExcel\IsoWeekNum class instead * * Excel Function: * ISOWEEKNUM(dateValue) @@ -663,7 +663,7 @@ class DateTime */ public static function ISOWEEKNUM($dateValue = 1) { - return DateTimeExcel\IsoweekNum::funcIsoWeekNum($dateValue); + return DateTimeExcel\IsoWeekNum::funcIsoWeekNum($dateValue); } /** diff --git a/src/PhpSpreadsheet/Calculation/Financial.php b/src/PhpSpreadsheet/Calculation/Financial.php index 11bbf7a6..547ad6b3 100644 --- a/src/PhpSpreadsheet/Calculation/Financial.php +++ b/src/PhpSpreadsheet/Calculation/Financial.php @@ -20,6 +20,8 @@ class Financial { $pmt = self::PMT($rate, $nper, $pv, $fv, $type); $capital = $pv; + $interest = 0; + $principal = 0; for ($i = 1; $i <= $per; ++$i) { $interest = ($type && $i == 1) ? 0 : -$capital * $rate; $principal = $pmt - $interest; diff --git a/src/PhpSpreadsheet/Chart/Renderer/JpGraph.php b/src/PhpSpreadsheet/Chart/Renderer/JpGraph.php index 02fbfed7..0ab70870 100644 --- a/src/PhpSpreadsheet/Chart/Renderer/JpGraph.php +++ b/src/PhpSpreadsheet/Chart/Renderer/JpGraph.php @@ -301,6 +301,8 @@ class JpGraph implements IRenderer $seriesPlots = []; if ($grouping == 'percentStacked') { $sumValues = $this->percentageSumCalculation($groupID, $seriesCount); + } else { + $sumValues = []; } // Loop through each data series in turn @@ -376,6 +378,8 @@ class JpGraph implements IRenderer $seriesPlots = []; if ($grouping == 'percentStacked') { $sumValues = $this->percentageSumCalculation($groupID, $seriesCount); + } else { + $sumValues = []; } // Loop through each data series in turn diff --git a/src/PhpSpreadsheet/IOFactory.php b/src/PhpSpreadsheet/IOFactory.php index ab04e969..06006edc 100644 --- a/src/PhpSpreadsheet/IOFactory.php +++ b/src/PhpSpreadsheet/IOFactory.php @@ -120,7 +120,7 @@ abstract class IOFactory $reader = self::createReader($guessedReader); // Let's see if we are lucky - if (isset($reader) && $reader->canRead($filename)) { + if ($reader->canRead($filename)) { return $reader; } } diff --git a/src/PhpSpreadsheet/Reader/Xls.php b/src/PhpSpreadsheet/Reader/Xls.php index 6d6b87fd..faa047da 100644 --- a/src/PhpSpreadsheet/Reader/Xls.php +++ b/src/PhpSpreadsheet/Reader/Xls.php @@ -801,9 +801,10 @@ class Xls extends BaseReader } // treat MSODRAWINGGROUP records, workbook-level Escher + $escherWorkbook = null; if (!$this->readDataOnly && $this->drawingGroupData) { - $escherWorkbook = new Escher(); - $reader = new Xls\Escher($escherWorkbook); + $escher = new Escher(); + $reader = new Xls\Escher($escher); $escherWorkbook = $reader->load($this->drawingGroupData); } @@ -1133,38 +1134,40 @@ class Xls extends BaseReader continue 2; } - $BSECollection = $escherWorkbook->getDggContainer()->getBstoreContainer()->getBSECollection(); - $BSE = $BSECollection[$BSEindex - 1]; - $blipType = $BSE->getBlipType(); + if ($escherWorkbook) { + $BSECollection = $escherWorkbook->getDggContainer()->getBstoreContainer()->getBSECollection(); + $BSE = $BSECollection[$BSEindex - 1]; + $blipType = $BSE->getBlipType(); - // need check because some blip types are not supported by Escher reader such as EMF - if ($blip = $BSE->getBlip()) { - $ih = imagecreatefromstring($blip->getData()); - $drawing = new MemoryDrawing(); - $drawing->setImageResource($ih); + // need check because some blip types are not supported by Escher reader such as EMF + if ($blip = $BSE->getBlip()) { + $ih = imagecreatefromstring($blip->getData()); + $drawing = new MemoryDrawing(); + $drawing->setImageResource($ih); - // width, height, offsetX, offsetY - $drawing->setResizeProportional(false); - $drawing->setWidth($width); - $drawing->setHeight($height); - $drawing->setOffsetX($offsetX); - $drawing->setOffsetY($offsetY); + // width, height, offsetX, offsetY + $drawing->setResizeProportional(false); + $drawing->setWidth($width); + $drawing->setHeight($height); + $drawing->setOffsetX($offsetX); + $drawing->setOffsetY($offsetY); - switch ($blipType) { - case BSE::BLIPTYPE_JPEG: - $drawing->setRenderingFunction(MemoryDrawing::RENDERING_JPEG); - $drawing->setMimeType(MemoryDrawing::MIMETYPE_JPEG); + switch ($blipType) { + case BSE::BLIPTYPE_JPEG: + $drawing->setRenderingFunction(MemoryDrawing::RENDERING_JPEG); + $drawing->setMimeType(MemoryDrawing::MIMETYPE_JPEG); - break; - case BSE::BLIPTYPE_PNG: - $drawing->setRenderingFunction(MemoryDrawing::RENDERING_PNG); - $drawing->setMimeType(MemoryDrawing::MIMETYPE_PNG); + break; + case BSE::BLIPTYPE_PNG: + $drawing->setRenderingFunction(MemoryDrawing::RENDERING_PNG); + $drawing->setMimeType(MemoryDrawing::MIMETYPE_PNG); - break; + break; + } + + $drawing->setWorksheet($this->phpSheet); + $drawing->setCoordinates($spContainer->getStartCoordinates()); } - - $drawing->setWorksheet($this->phpSheet); - $drawing->setCoordinates($spContainer->getStartCoordinates()); } break; @@ -2742,6 +2745,7 @@ class Xls extends BaseReader $sheetType = ord($recordData[5]); // offset: 6; size: var; sheet name + $rec_name = null; if ($this->version == self::XLS_BIFF8) { $string = self::readUnicodeStringShort(substr($recordData, 6)); $rec_name = $string['value']; @@ -3018,12 +3022,14 @@ class Xls extends BaseReader // bit: 3; mask: 0x03; 0 = ordinary; 1 = Rich-Text $hasRichText = (($optionFlags & 0x08) != 0); + $formattingRuns = 0; if ($hasRichText) { // number of Rich-Text formatting runs $formattingRuns = self::getUInt2d($recordData, $pos); $pos += 2; } + $extendedRunLength = 0; if ($hasAsian) { // size of Asian phonetic setting $extendedRunLength = self::getInt4d($recordData, $pos); @@ -3034,6 +3040,7 @@ class Xls extends BaseReader $len = ($isCompressed) ? $numChars : $numChars * 2; // look up limit position - Check it again to be sure that no error occurs when parsing SST structure + $limitpos = null; foreach ($spliceOffsets as $spliceOffset) { // it can happen that the string is empty, therefore we need // <= and not just < @@ -4385,6 +4392,8 @@ class Xls extends BaseReader // offset: 4; size: 2; index to first visible colum $firstVisibleColumn = self::getUInt2d($recordData, 4); + $zoomscaleInPageBreakPreview = 0; + $zoomscaleInNormalView = 0; if ($this->version === self::XLS_BIFF8) { // offset: 8; size: 2; not used // offset: 10; size: 2; cached magnification factor in page break preview (in percent); 0 = Default (60%) @@ -7636,6 +7645,8 @@ class Xls extends BaseReader $size = 9; break; + default: + throw new PhpSpreadsheetException('Unsupported BIFF8 constant'); } return [ diff --git a/src/PhpSpreadsheet/Reader/Xls/Color.php b/src/PhpSpreadsheet/Reader/Xls/Color.php index c45f88c7..06c2d0b9 100644 --- a/src/PhpSpreadsheet/Reader/Xls/Color.php +++ b/src/PhpSpreadsheet/Reader/Xls/Color.php @@ -20,7 +20,7 @@ class Color if ($color <= 0x07 || $color >= 0x40) { // special built-in color return Color\BuiltIn::lookup($color); - } elseif (isset($palette, $palette[$color - 8])) { + } elseif (isset($palette[$color - 8])) { // palette color, color index 0x08 maps to pallete index 0 return $palette[$color - 8]; } diff --git a/src/PhpSpreadsheet/Reader/Xlsx.php b/src/PhpSpreadsheet/Reader/Xlsx.php index 219a49fb..e47ad7b0 100644 --- a/src/PhpSpreadsheet/Reader/Xlsx.php +++ b/src/PhpSpreadsheet/Reader/Xlsx.php @@ -430,7 +430,7 @@ class Xlsx extends BaseReader 'SimpleXMLElement', Settings::getLibXmlLoaderOptions() ); - if (isset($xmlStrings, $xmlStrings->si)) { + if (isset($xmlStrings->si)) { foreach ($xmlStrings->si as $val) { if (isset($val->t)) { $sharedStrings[] = StringHelper::controlCharacterOOXML2PHP((string) $val->t); @@ -511,10 +511,7 @@ class Xlsx extends BaseReader $numFmt = NumberFormat::builtInFormatCode((int) $xf['numFmtId']); } } - $quotePrefix = false; - if (isset($xf['quotePrefix'])) { - $quotePrefix = (bool) $xf['quotePrefix']; - } + $quotePrefix = (bool) ($xf['quotePrefix'] ?? false); $style = (object) [ 'numFmt' => $numFmt ?? NumberFormat::FORMAT_GENERAL, @@ -544,6 +541,8 @@ class Xlsx extends BaseReader } } + $quotePrefix = (bool) ($xf['quotePrefix'] ?? false); + $cellStyle = (object) [ 'numFmt' => $numFmt, 'font' => $xmlStyles->fonts->font[(int) ($xf['fontId'])], @@ -1081,6 +1080,7 @@ class Xlsx extends BaseReader } if ($xmlSheet->drawing && !$this->readDataOnly) { $unparsedDrawings = []; + $fileDrawing = null; foreach ($xmlSheet->drawing as $drawing) { $drawingRelId = (string) self::getArrayItem($drawing->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships'), 'id'); $fileDrawing = $drawings[$drawingRelId]; diff --git a/src/PhpSpreadsheet/Reader/Xlsx/Chart.php b/src/PhpSpreadsheet/Reader/Xlsx/Chart.php index 5a3439f2..5e86c60a 100644 --- a/src/PhpSpreadsheet/Reader/Xlsx/Chart.php +++ b/src/PhpSpreadsheet/Reader/Xlsx/Chart.php @@ -61,7 +61,7 @@ class Chart $XaxisLabel = $YaxisLabel = $legend = $title = null; $dispBlanksAs = $plotVisOnly = null; - + $plotArea = null; foreach ($chartElementsC as $chartElementKey => $chartElement) { switch ($chartElementKey) { case 'chart': diff --git a/src/PhpSpreadsheet/Reader/Xml.php b/src/PhpSpreadsheet/Reader/Xml.php index a827d17a..58d38b0d 100644 --- a/src/PhpSpreadsheet/Reader/Xml.php +++ b/src/PhpSpreadsheet/Reader/Xml.php @@ -436,6 +436,7 @@ class Xml extends BaseReader // Create new Worksheet $spreadsheet->createSheet(); $spreadsheet->setActiveSheetIndex($worksheetID); + $worksheetName = ''; if (isset($worksheet_ss['Name'])) { $worksheetName = (string) $worksheet_ss['Name']; // Use false for $updateFormulaCellReferences to prevent adjustment of worksheet references in diff --git a/src/PhpSpreadsheet/Shared/Drawing.php b/src/PhpSpreadsheet/Shared/Drawing.php index f41fb695..67c015c4 100644 --- a/src/PhpSpreadsheet/Shared/Drawing.php +++ b/src/PhpSpreadsheet/Shared/Drawing.php @@ -171,6 +171,8 @@ class Drawing // 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); diff --git a/src/PhpSpreadsheet/Shared/Font.php b/src/PhpSpreadsheet/Shared/Font.php index 162e9730..4061b370 100644 --- a/src/PhpSpreadsheet/Shared/Font.php +++ b/src/PhpSpreadsheet/Shared/Font.php @@ -244,6 +244,7 @@ class Font // Try to get the exact text width in pixels $approximate = self::$autoSizeMethod == self::AUTOSIZE_METHOD_APPROX; + $columnWidth = 0; if (!$approximate) { $columnWidthAdjust = ceil(self::getTextWidthPixelsExact('n', $font, 0) * 1.07); diff --git a/src/PhpSpreadsheet/Shared/JAMA/EigenvalueDecomposition.php b/src/PhpSpreadsheet/Shared/JAMA/EigenvalueDecomposition.php index 4c67c3a9..5c6ccfd3 100644 --- a/src/PhpSpreadsheet/Shared/JAMA/EigenvalueDecomposition.php +++ b/src/PhpSpreadsheet/Shared/JAMA/EigenvalueDecomposition.php @@ -18,9 +18,9 @@ namespace PhpOffice\PhpSpreadsheet\Shared\JAMA; * conditioned, or even singular, so the validity of the equation * A = V*D*inverse(V) depends upon V.cond(). * - * @author Paul Meagher + * @author Paul Meagher * - * @version 1.1 + * @version 1.1 */ class EigenvalueDecomposition { @@ -70,6 +70,11 @@ class EigenvalueDecomposition private $cdivi; + /** + * @var array + */ + private $A; + /** * Symmetric Householder reduction to tridiagonal form. */ @@ -80,6 +85,7 @@ class EigenvalueDecomposition // Auto. Comp., Vol.ii-Linear Algebra, and the corresponding // Fortran subroutine in EISPACK. $this->d = $this->V[$this->n - 1]; + $j = 0; // Householder reduction to tridiagonal form. for ($i = $this->n - 1; $i > 0; --$i) { $i_ = $i - 1; @@ -781,9 +787,9 @@ class EigenvalueDecomposition /** * Constructor: Check for symmetry, then construct the eigenvalue decomposition. * - * @param mixed $Arg A Square matrix + * @param Matrix $Arg A Square matrix */ - public function __construct($Arg) + public function __construct(Matrix $Arg) { $this->A = $Arg->getArray(); $this->n = $Arg->getColumnDimension(); @@ -848,6 +854,7 @@ class EigenvalueDecomposition */ public function getD() { + $D = []; for ($i = 0; $i < $this->n; ++$i) { $D[$i] = array_fill(0, $this->n, 0.0); $D[$i][$i] = $this->d[$i]; diff --git a/src/PhpSpreadsheet/Shared/JAMA/LUDecomposition.php b/src/PhpSpreadsheet/Shared/JAMA/LUDecomposition.php index 6db17c28..e16d6a21 100644 --- a/src/PhpSpreadsheet/Shared/JAMA/LUDecomposition.php +++ b/src/PhpSpreadsheet/Shared/JAMA/LUDecomposition.php @@ -135,6 +135,7 @@ class LUDecomposition */ public function getL() { + $L = []; for ($i = 0; $i < $this->m; ++$i) { for ($j = 0; $j < $this->n; ++$j) { if ($i > $j) { @@ -159,6 +160,7 @@ class LUDecomposition */ public function getU() { + $U = []; for ($i = 0; $i < $this->n; ++$i) { for ($j = 0; $j < $this->n; ++$j) { if ($i <= $j) { diff --git a/src/PhpSpreadsheet/Shared/JAMA/SingularValueDecomposition.php b/src/PhpSpreadsheet/Shared/JAMA/SingularValueDecomposition.php index b997fb7c..afd9ed0f 100644 --- a/src/PhpSpreadsheet/Shared/JAMA/SingularValueDecomposition.php +++ b/src/PhpSpreadsheet/Shared/JAMA/SingularValueDecomposition.php @@ -476,6 +476,7 @@ class SingularValueDecomposition */ public function getS() { + $S = []; for ($i = 0; $i < $this->n; ++$i) { for ($j = 0; $j < $this->n; ++$j) { $S[$i][$j] = 0.0; diff --git a/src/PhpSpreadsheet/Shared/OLE.php b/src/PhpSpreadsheet/Shared/OLE.php index 1c745bdb..f65fbca7 100644 --- a/src/PhpSpreadsheet/Shared/OLE.php +++ b/src/PhpSpreadsheet/Shared/OLE.php @@ -21,6 +21,7 @@ namespace PhpOffice\PhpSpreadsheet\Shared; // +----------------------------------------------------------------------+ // +use PhpOffice\PhpSpreadsheet\Exception; use PhpOffice\PhpSpreadsheet\Reader\Exception as ReaderException; use PhpOffice\PhpSpreadsheet\Shared\OLE\ChainedBlockStream; use PhpOffice\PhpSpreadsheet\Shared\OLE\PPS\Root; @@ -317,7 +318,7 @@ class OLE break; default: - break; + throw new Exception('Unsupported PPS type'); } fseek($fh, 1, SEEK_CUR); $pps->Type = $type; @@ -496,7 +497,7 @@ class OLE */ public static function localDateToOLE($date) { - if (!isset($date)) { + if (!$date) { return "\x00\x00\x00\x00\x00\x00\x00\x00"; } diff --git a/src/PhpSpreadsheet/Shared/Trend/Trend.php b/src/PhpSpreadsheet/Shared/Trend/Trend.php index d0a117cb..24570d59 100644 --- a/src/PhpSpreadsheet/Shared/Trend/Trend.php +++ b/src/PhpSpreadsheet/Shared/Trend/Trend.php @@ -91,6 +91,8 @@ class Trend case self::TREND_BEST_FIT_NO_POLY: // If the request is to determine the best fit regression, then we test each Trend line in turn // Start by generating an instance of each available Trend method + $bestFit = []; + $bestFitValue = []; foreach (self::$trendTypes as $trendMethod) { $className = '\PhpOffice\PhpSpreadsheet\Shared\Trend\\' . $trendType . 'BestFit'; $bestFit[$trendMethod] = new $className($yValues, $xValues, $const); diff --git a/src/PhpSpreadsheet/Spreadsheet.php b/src/PhpSpreadsheet/Spreadsheet.php index 51f558a1..59304804 100644 --- a/src/PhpSpreadsheet/Spreadsheet.php +++ b/src/PhpSpreadsheet/Spreadsheet.php @@ -55,7 +55,7 @@ class Spreadsheet /** * Calculation Engine. * - * @var Calculation + * @var null|Calculation */ private $calculationEngine; @@ -505,8 +505,8 @@ class Spreadsheet */ public function __destruct() { - $this->calculationEngine = null; $this->disconnectWorksheets(); + $this->calculationEngine = null; } /** @@ -527,7 +527,7 @@ class Spreadsheet /** * Return the calculation engine for this worksheet. * - * @return Calculation + * @return null|Calculation */ public function getCalculationEngine() { @@ -1343,6 +1343,7 @@ class Spreadsheet // remove cellXfs without references and create mapping so we can update xfIndex // for all cells and columns $countNeededCellXfs = 0; + $map = []; foreach ($this->cellXfCollection as $index => $cellXf) { if ($countReferencesCellXf[$index] > 0 || $index == 0) { // we must never remove the first cellXf ++$countNeededCellXfs; diff --git a/src/PhpSpreadsheet/Style/Border.php b/src/PhpSpreadsheet/Style/Border.php index 1d3096f0..d11fa0ca 100644 --- a/src/PhpSpreadsheet/Style/Border.php +++ b/src/PhpSpreadsheet/Style/Border.php @@ -47,11 +47,8 @@ class Border extends Supervisor * @param bool $isSupervisor Flag indicating if this is a supervisor or not * Leave this value at default unless you understand exactly what * its ramifications are - * @param bool $isConditional Flag indicating if this is a conditional style or not - * Leave this value at default unless you understand exactly what - * its ramifications are */ - public function __construct($isSupervisor = false, $isConditional = false) + public function __construct($isSupervisor = false) { // Supervisor? parent::__construct($isSupervisor); diff --git a/src/PhpSpreadsheet/Style/Borders.php b/src/PhpSpreadsheet/Style/Borders.php index a1acfdd4..eeb4932a 100644 --- a/src/PhpSpreadsheet/Style/Borders.php +++ b/src/PhpSpreadsheet/Style/Borders.php @@ -95,21 +95,18 @@ class Borders extends Supervisor * @param bool $isSupervisor Flag indicating if this is a supervisor or not * Leave this value at default unless you understand exactly what * its ramifications are - * @param bool $isConditional Flag indicating if this is a conditional style or not - * Leave this value at default unless you understand exactly what - * its ramifications are */ - public function __construct($isSupervisor = false, $isConditional = false) + public function __construct($isSupervisor = false) { // Supervisor? parent::__construct($isSupervisor); // Initialise values - $this->left = new Border($isSupervisor, $isConditional); - $this->right = new Border($isSupervisor, $isConditional); - $this->top = new Border($isSupervisor, $isConditional); - $this->bottom = new Border($isSupervisor, $isConditional); - $this->diagonal = new Border($isSupervisor, $isConditional); + $this->left = new Border($isSupervisor); + $this->right = new Border($isSupervisor); + $this->top = new Border($isSupervisor); + $this->bottom = new Border($isSupervisor); + $this->diagonal = new Border($isSupervisor); $this->diagonalDirection = self::DIAGONAL_NONE; // Specially for supervisor diff --git a/src/PhpSpreadsheet/Style/NumberFormat/NumberFormatter.php b/src/PhpSpreadsheet/Style/NumberFormat/NumberFormatter.php index 36cdcf03..9a4f32ac 100644 --- a/src/PhpSpreadsheet/Style/NumberFormat/NumberFormatter.php +++ b/src/PhpSpreadsheet/Style/NumberFormat/NumberFormatter.php @@ -35,6 +35,7 @@ class NumberFormatter if ($maskingBlockCount > 1) { $maskingBlocks = array_reverse($maskingBlocks[0]); + $offset = 0; foreach ($maskingBlocks as $block) { $size = strlen($block[0]); $divisor = 10 ** $size; diff --git a/src/PhpSpreadsheet/Style/Style.php b/src/PhpSpreadsheet/Style/Style.php index 7fec9a00..d3653ed5 100644 --- a/src/PhpSpreadsheet/Style/Style.php +++ b/src/PhpSpreadsheet/Style/Style.php @@ -80,7 +80,7 @@ class Style extends Supervisor // Initialise values $this->font = new Font($isSupervisor, $isConditional); $this->fill = new Fill($isSupervisor, $isConditional); - $this->borders = new Borders($isSupervisor, $isConditional); + $this->borders = new Borders($isSupervisor); $this->alignment = new Alignment($isSupervisor, $isConditional); $this->numberFormat = new NumberFormat($isSupervisor, $isConditional); $this->protection = new Protection($isSupervisor, $isConditional); @@ -257,11 +257,11 @@ class Style extends Supervisor // start column index for region $colStart = ($x == 3) ? Coordinate::stringFromColumnIndex($rangeEnd[0]) - : Coordinate::stringFromColumnIndex($rangeStart[0] + $x - 1); + : Coordinate::stringFromColumnIndex($rangeStart[0] + $x - 1); // end column index for region $colEnd = ($x == 1) ? Coordinate::stringFromColumnIndex($rangeStart[0]) - : Coordinate::stringFromColumnIndex($rangeEnd[0] - $xMax + $x); + : Coordinate::stringFromColumnIndex($rangeEnd[0] - $xMax + $x); for ($y = 1; $y <= $yMax; ++$y) { // which edges are touching the region @@ -349,56 +349,11 @@ class Style extends Supervisor } // First loop through columns, rows, or cells to find out which styles are affected by this operation - switch ($selectionType) { - case 'COLUMN': - $oldXfIndexes = []; - for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { - $oldXfIndexes[$this->getActiveSheet()->getColumnDimensionByColumn($col)->getXfIndex()] = true; - } - foreach ($this->getActiveSheet()->getColumnIterator($rangeStart0, $rangeEnd0) as $columnIterator) { - $cellIterator = $columnIterator->getCellIterator(); - $cellIterator->setIterateOnlyExistingCells(true); - foreach ($cellIterator as $columnCell) { - if ($columnCell !== null) { - $columnCell->getStyle()->applyFromArray($pStyles); - } - } - } - - break; - case 'ROW': - $oldXfIndexes = []; - for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { - if ($this->getActiveSheet()->getRowDimension($row)->getXfIndex() === null) { - $oldXfIndexes[0] = true; // row without explicit style should be formatted based on default style - } else { - $oldXfIndexes[$this->getActiveSheet()->getRowDimension($row)->getXfIndex()] = true; - } - } - foreach ($this->getActiveSheet()->getRowIterator((int) $rangeStart[1], (int) $rangeEnd[1]) as $rowIterator) { - $cellIterator = $rowIterator->getCellIterator(); - $cellIterator->setIterateOnlyExistingCells(true); - foreach ($cellIterator as $rowCell) { - if ($rowCell !== null) { - $rowCell->getStyle()->applyFromArray($pStyles); - } - } - } - - break; - case 'CELL': - $oldXfIndexes = []; - for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { - for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { - $oldXfIndexes[$this->getActiveSheet()->getCellByColumnAndRow($col, $row)->getXfIndex()] = true; - } - } - - break; - } + $oldXfIndexes = $this->getOldXfIndexes($selectionType, $rangeStart, $rangeEnd, $rangeStart0, $rangeEnd0, $pStyles); // clone each of the affected styles, apply the style array, and add the new styles to the workbook $workbook = $this->getActiveSheet()->getParent(); + $newXfIndexes = []; foreach ($oldXfIndexes as $oldXfIndex => $dummy) { $style = $workbook->getCellXfByIndex($oldXfIndex); $newStyle = clone $style; @@ -472,6 +427,57 @@ class Style extends Supervisor return $this; } + private function getOldXfIndexes(string $selectionType, array $rangeStart, array $rangeEnd, string $rangeStart0, string $rangeEnd0, array $pStyles): array + { + $oldXfIndexes = []; + switch ($selectionType) { + case 'COLUMN': + for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { + $oldXfIndexes[$this->getActiveSheet()->getColumnDimensionByColumn($col)->getXfIndex()] = true; + } + foreach ($this->getActiveSheet()->getColumnIterator($rangeStart0, $rangeEnd0) as $columnIterator) { + $cellIterator = $columnIterator->getCellIterator(); + $cellIterator->setIterateOnlyExistingCells(true); + foreach ($cellIterator as $columnCell) { + if ($columnCell !== null) { + $columnCell->getStyle()->applyFromArray($pStyles); + } + } + } + + break; + case 'ROW': + for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { + if ($this->getActiveSheet()->getRowDimension($row)->getXfIndex() === null) { + $oldXfIndexes[0] = true; // row without explicit style should be formatted based on default style + } else { + $oldXfIndexes[$this->getActiveSheet()->getRowDimension($row)->getXfIndex()] = true; + } + } + foreach ($this->getActiveSheet()->getRowIterator((int) $rangeStart[1], (int) $rangeEnd[1]) as $rowIterator) { + $cellIterator = $rowIterator->getCellIterator(); + $cellIterator->setIterateOnlyExistingCells(true); + foreach ($cellIterator as $rowCell) { + if ($rowCell !== null) { + $rowCell->getStyle()->applyFromArray($pStyles); + } + } + } + + break; + case 'CELL': + for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { + for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { + $oldXfIndexes[$this->getActiveSheet()->getCellByColumnAndRow($col, $row)->getXfIndex()] = true; + } + } + + break; + } + + return $oldXfIndexes; + } + /** * Get Fill. * diff --git a/src/PhpSpreadsheet/Worksheet/AutoFilter.php b/src/PhpSpreadsheet/Worksheet/AutoFilter.php index 22fc775c..dc876ee9 100644 --- a/src/PhpSpreadsheet/Worksheet/AutoFilter.php +++ b/src/PhpSpreadsheet/Worksheet/AutoFilter.php @@ -779,6 +779,9 @@ class AutoFilter case AutoFilter\Column::AUTOFILTER_FILTERTYPE_TOPTENFILTER: $ruleValues = []; $dataRowCount = $rangeEnd[1] - $rangeStart[1]; + $toptenRuleType = null; + $ruleValue = null; + $ruleOperator = null; foreach ($rules as $rule) { // We should only ever have one Dynamic Filter Rule anyway $toptenRuleType = $rule->getGrouping(); diff --git a/src/PhpSpreadsheet/Writer/Xls.php b/src/PhpSpreadsheet/Writer/Xls.php index c7c2e7d6..d458fc74 100644 --- a/src/PhpSpreadsheet/Writer/Xls.php +++ b/src/PhpSpreadsheet/Writer/Xls.php @@ -420,6 +420,7 @@ class Xls extends BaseWriter private function processDrawing(BstoreContainer &$bstoreContainer, BaseDrawing $drawing): void { + $blipType = null; $blipData = ''; $filename = $drawing->getPath(); diff --git a/src/PhpSpreadsheet/Writer/Xls/Parser.php b/src/PhpSpreadsheet/Writer/Xls/Parser.php index f89957a4..98b2b5cc 100644 --- a/src/PhpSpreadsheet/Writer/Xls/Parser.php +++ b/src/PhpSpreadsheet/Writer/Xls/Parser.php @@ -747,7 +747,7 @@ class Parser return pack('C', 0xFF); } - private function convertDefinedName(string $name): void + private function convertDefinedName(string $name): string { if (strlen($name) > 255) { throw new WriterException('Defined Name is too long'); @@ -764,7 +764,8 @@ class Parser $ptgRef = pack('Cvxx', $this->ptg['ptgName'], $nameReference); throw new WriterException('Cannot yet write formulae with defined names to Xls'); -// return $ptgRef; + + return $ptgRef; } /** @@ -968,6 +969,7 @@ class Parser */ private function advance() { + $token = ''; $i = $this->currentCharacter; $formula_length = strlen($this->formula); // eat up white spaces diff --git a/src/PhpSpreadsheet/Writer/Xls/Worksheet.php b/src/PhpSpreadsheet/Writer/Xls/Worksheet.php index d2784d6d..8f6015de 100644 --- a/src/PhpSpreadsheet/Writer/Xls/Worksheet.php +++ b/src/PhpSpreadsheet/Writer/Xls/Worksheet.php @@ -1344,32 +1344,13 @@ class Worksheet extends BIFFwriter */ private function writeColinfo($col_array): void { - if (isset($col_array[0])) { - $colFirst = $col_array[0]; - } - if (isset($col_array[1])) { - $colLast = $col_array[1]; - } - if (isset($col_array[2])) { - $coldx = $col_array[2]; - } else { - $coldx = 8.43; - } - if (isset($col_array[3])) { - $xfIndex = $col_array[3]; - } else { - $xfIndex = 15; - } - if (isset($col_array[4])) { - $grbit = $col_array[4]; - } else { - $grbit = 0; - } - if (isset($col_array[5])) { - $level = $col_array[5]; - } else { - $level = 0; - } + $colFirst = $col_array[0] ?? null; + $colLast = $col_array[1] ?? null; + $coldx = $col_array[2] ?? 8.43; + $xfIndex = $col_array[3] ?? 15; + $grbit = $col_array[4] ?? 0; + $level = $col_array[5] ?? 0; + $record = 0x007D; // Record identifier $length = 0x000C; // Number of bytes to follow @@ -1425,13 +1406,6 @@ class Worksheet extends BIFFwriter $irefAct = 0; // Active cell ref $cref = 1; // Number of refs - if (!isset($rwLast)) { - $rwLast = $rwFirst; // Last row in reference - } - if (!isset($colLast)) { - $colLast = $colFirst; // Last col in reference - } - // Swap last row/col for first row/col as necessary if ($rwFirst > $rwLast) { [$rwFirst, $rwLast] = [$rwLast, $rwFirst]; @@ -1660,7 +1634,7 @@ class Worksheet extends BIFFwriter if (!isset($rwTop)) { $rwTop = $y; } - if (!isset($colLeft)) { + if (!$colLeft) { $colLeft = $x; } } else { @@ -1668,7 +1642,7 @@ class Worksheet extends BIFFwriter if (!isset($rwTop)) { $rwTop = 0; } - if (!isset($colLeft)) { + if (!$colLeft) { $colLeft = 0; } @@ -1684,7 +1658,7 @@ class Worksheet extends BIFFwriter // Determine which pane should be active. There is also the undocumented // option to override this should it be necessary: may be removed later. // - if (!isset($pnnAct)) { + if (!$pnnAct) { if ($x != 0 && $y != 0) { $pnnAct = 0; // Bottom right } @@ -2974,9 +2948,9 @@ class Worksheet extends BIFFwriter private function writeCFRule(Conditional $conditional): void { $record = 0x01B1; // Record identifier + $type = null; // Type of the CF + $operatorType = null; // Comparison operator - // $type : Type of the CF - // $operatorType : Comparison operator if ($conditional->getConditionType() == Conditional::CONDITION_EXPRESSION) { $type = 0x02; $operatorType = 0x00; @@ -3141,6 +3115,11 @@ class Worksheet extends BIFFwriter // Text direction $flags |= (1 == 0 ? 0x80000000 : 0); + $dataBlockFont = null; + $dataBlockAlign = null; + $dataBlockBorder = null; + $dataBlockFill = null; + // Data Blocks if ($bFormatFont == 1) { // Font Name @@ -4398,15 +4377,6 @@ class Worksheet extends BIFFwriter $dataBlockFill = pack('v', $blockFillPatternStyle); $dataBlockFill .= pack('v', $colorIdxFg | ($colorIdxBg << 7)); } - if ($bFormatProt == 1) { - $dataBlockProtection = 0; - if ($conditional->getStyle()->getProtection()->getLocked() == Protection::PROTECTION_PROTECTED) { - $dataBlockProtection = 1; - } - if ($conditional->getStyle()->getProtection()->getHidden() == Protection::PROTECTION_PROTECTED) { - $dataBlockProtection = 1 << 1; - } - } $data = pack('CCvvVv', $type, $operatorType, $szValue1, $szValue2, $flags, 0x0000); if ($bFormatFont == 1) { // Block Formatting : OK @@ -4422,7 +4392,7 @@ class Worksheet extends BIFFwriter $data .= $dataBlockFill; } if ($bFormatProt == 1) { - $data .= $dataBlockProtection; + $data .= $this->getDataBlockProtection($conditional); } if ($operand1 !== null) { $data .= $operand1; @@ -4486,4 +4456,17 @@ class Worksheet extends BIFFwriter $data .= $cellRange; $this->append($header . $data); } + + private function getDataBlockProtection(Conditional $conditional): int + { + $dataBlockProtection = 0; + if ($conditional->getStyle()->getProtection()->getLocked() == Protection::PROTECTION_PROTECTED) { + $dataBlockProtection = 1; + } + if ($conditional->getStyle()->getProtection()->getHidden() == Protection::PROTECTION_PROTECTED) { + $dataBlockProtection = 1 << 1; + } + + return $dataBlockProtection; + } } diff --git a/src/PhpSpreadsheet/Writer/Xls/Xf.php b/src/PhpSpreadsheet/Writer/Xls/Xf.php index 90d21bcf..eca3d8e0 100644 --- a/src/PhpSpreadsheet/Writer/Xls/Xf.php +++ b/src/PhpSpreadsheet/Writer/Xls/Xf.php @@ -115,6 +115,21 @@ class Xf */ private $rightBorderColor; + /** + * @var int + */ + private $diag; + + /** + * @var int + */ + private $diagColor; + + /** + * @var Style + */ + private $style; + /** * Constructor. * @@ -132,14 +147,14 @@ class Xf $this->foregroundColor = 0x40; $this->backgroundColor = 0x41; - $this->_diag = 0; + $this->diag = 0; $this->bottomBorderColor = 0x40; $this->topBorderColor = 0x40; $this->leftBorderColor = 0x40; $this->rightBorderColor = 0x40; - $this->_diag_color = 0x40; - $this->_style = $style; + $this->diagColor = 0x40; + $this->style = $style; } /** @@ -153,39 +168,39 @@ class Xf if ($this->isStyleXf) { $style = 0xFFF5; } else { - $style = self::mapLocked($this->_style->getProtection()->getLocked()); - $style |= self::mapHidden($this->_style->getProtection()->getHidden()) << 1; + $style = self::mapLocked($this->style->getProtection()->getLocked()); + $style |= self::mapHidden($this->style->getProtection()->getHidden()) << 1; } // Flags to indicate if attributes have been set. $atr_num = ($this->numberFormatIndex != 0) ? 1 : 0; $atr_fnt = ($this->fontIndex != 0) ? 1 : 0; - $atr_alc = ((int) $this->_style->getAlignment()->getWrapText()) ? 1 : 0; - $atr_bdr = (self::mapBorderStyle($this->_style->getBorders()->getBottom()->getBorderStyle()) || - self::mapBorderStyle($this->_style->getBorders()->getTop()->getBorderStyle()) || - self::mapBorderStyle($this->_style->getBorders()->getLeft()->getBorderStyle()) || - self::mapBorderStyle($this->_style->getBorders()->getRight()->getBorderStyle())) ? 1 : 0; + $atr_alc = ((int) $this->style->getAlignment()->getWrapText()) ? 1 : 0; + $atr_bdr = (self::mapBorderStyle($this->style->getBorders()->getBottom()->getBorderStyle()) || + self::mapBorderStyle($this->style->getBorders()->getTop()->getBorderStyle()) || + self::mapBorderStyle($this->style->getBorders()->getLeft()->getBorderStyle()) || + self::mapBorderStyle($this->style->getBorders()->getRight()->getBorderStyle())) ? 1 : 0; $atr_pat = ($this->foregroundColor != 0x40) ? 1 : 0; $atr_pat = ($this->backgroundColor != 0x41) ? 1 : $atr_pat; - $atr_pat = self::mapFillType($this->_style->getFill()->getFillType()) ? 1 : $atr_pat; - $atr_prot = self::mapLocked($this->_style->getProtection()->getLocked()) - | self::mapHidden($this->_style->getProtection()->getHidden()); + $atr_pat = self::mapFillType($this->style->getFill()->getFillType()) ? 1 : $atr_pat; + $atr_prot = self::mapLocked($this->style->getProtection()->getLocked()) + | self::mapHidden($this->style->getProtection()->getHidden()); // Zero the default border colour if the border has not been set. - if (self::mapBorderStyle($this->_style->getBorders()->getBottom()->getBorderStyle()) == 0) { + if (self::mapBorderStyle($this->style->getBorders()->getBottom()->getBorderStyle()) == 0) { $this->bottomBorderColor = 0; } - if (self::mapBorderStyle($this->_style->getBorders()->getTop()->getBorderStyle()) == 0) { + if (self::mapBorderStyle($this->style->getBorders()->getTop()->getBorderStyle()) == 0) { $this->topBorderColor = 0; } - if (self::mapBorderStyle($this->_style->getBorders()->getRight()->getBorderStyle()) == 0) { + if (self::mapBorderStyle($this->style->getBorders()->getRight()->getBorderStyle()) == 0) { $this->rightBorderColor = 0; } - if (self::mapBorderStyle($this->_style->getBorders()->getLeft()->getBorderStyle()) == 0) { + if (self::mapBorderStyle($this->style->getBorders()->getLeft()->getBorderStyle()) == 0) { $this->leftBorderColor = 0; } - if (self::mapBorderStyle($this->_style->getBorders()->getDiagonal()->getBorderStyle()) == 0) { - $this->_diag_color = 0; + if (self::mapBorderStyle($this->style->getBorders()->getDiagonal()->getBorderStyle()) == 0) { + $this->diagColor = 0; } $record = 0x00E0; // Record identifier @@ -194,9 +209,9 @@ class Xf $ifnt = $this->fontIndex; // Index to FONT record $ifmt = $this->numberFormatIndex; // Index to FORMAT record - $align = $this->mapHAlign($this->_style->getAlignment()->getHorizontal()); // Alignment - $align |= (int) $this->_style->getAlignment()->getWrapText() << 3; - $align |= self::mapVAlign($this->_style->getAlignment()->getVertical()) << 4; + $align = $this->mapHAlign($this->style->getAlignment()->getHorizontal()); // Alignment + $align |= (int) $this->style->getAlignment()->getWrapText() << 3; + $align |= self::mapVAlign($this->style->getAlignment()->getVertical()) << 4; $align |= $this->textJustLast << 7; $used_attrib = $atr_num << 2; @@ -209,35 +224,35 @@ class Xf $icv = $this->foregroundColor; // fg and bg pattern colors $icv |= $this->backgroundColor << 7; - $border1 = self::mapBorderStyle($this->_style->getBorders()->getLeft()->getBorderStyle()); // Border line style and color - $border1 |= self::mapBorderStyle($this->_style->getBorders()->getRight()->getBorderStyle()) << 4; - $border1 |= self::mapBorderStyle($this->_style->getBorders()->getTop()->getBorderStyle()) << 8; - $border1 |= self::mapBorderStyle($this->_style->getBorders()->getBottom()->getBorderStyle()) << 12; + $border1 = self::mapBorderStyle($this->style->getBorders()->getLeft()->getBorderStyle()); // Border line style and color + $border1 |= self::mapBorderStyle($this->style->getBorders()->getRight()->getBorderStyle()) << 4; + $border1 |= self::mapBorderStyle($this->style->getBorders()->getTop()->getBorderStyle()) << 8; + $border1 |= self::mapBorderStyle($this->style->getBorders()->getBottom()->getBorderStyle()) << 12; $border1 |= $this->leftBorderColor << 16; $border1 |= $this->rightBorderColor << 23; - $diagonalDirection = $this->_style->getBorders()->getDiagonalDirection(); + $diagonalDirection = $this->style->getBorders()->getDiagonalDirection(); $diag_tl_to_rb = $diagonalDirection == Borders::DIAGONAL_BOTH - || $diagonalDirection == Borders::DIAGONAL_DOWN; + || $diagonalDirection == Borders::DIAGONAL_DOWN; $diag_tr_to_lb = $diagonalDirection == Borders::DIAGONAL_BOTH - || $diagonalDirection == Borders::DIAGONAL_UP; + || $diagonalDirection == Borders::DIAGONAL_UP; $border1 |= $diag_tl_to_rb << 30; $border1 |= $diag_tr_to_lb << 31; $border2 = $this->topBorderColor; // Border color $border2 |= $this->bottomBorderColor << 7; - $border2 |= $this->_diag_color << 14; - $border2 |= self::mapBorderStyle($this->_style->getBorders()->getDiagonal()->getBorderStyle()) << 21; - $border2 |= self::mapFillType($this->_style->getFill()->getFillType()) << 26; + $border2 |= $this->diagColor << 14; + $border2 |= self::mapBorderStyle($this->style->getBorders()->getDiagonal()->getBorderStyle()) << 21; + $border2 |= self::mapFillType($this->style->getFill()->getFillType()) << 26; $header = pack('vv', $record, $length); //BIFF8 options: identation, shrinkToFit and text direction - $biff8_options = $this->_style->getAlignment()->getIndent(); - $biff8_options |= (int) $this->_style->getAlignment()->getShrinkToFit() << 4; + $biff8_options = $this->style->getAlignment()->getIndent(); + $biff8_options |= (int) $this->style->getAlignment()->getShrinkToFit() << 4; $data = pack('vvvC', $ifnt, $ifmt, $style, $align); - $data .= pack('CCC', self::mapTextRotation($this->_style->getAlignment()->getTextRotation()), $biff8_options, $used_attrib); + $data .= pack('CCC', self::mapTextRotation($this->style->getAlignment()->getTextRotation()), $biff8_options, $used_attrib); $data .= pack('VVv', $border1, $border2, $icv); return $header . $data; @@ -300,7 +315,7 @@ class Xf */ public function setDiagColor($colorIndex): void { - $this->_diag_color = $colorIndex; + $this->diagColor = $colorIndex; } /** diff --git a/src/PhpSpreadsheet/Writer/Xlsx/Chart.php b/src/PhpSpreadsheet/Writer/Xlsx/Chart.php index 583b262c..19da32c4 100644 --- a/src/PhpSpreadsheet/Writer/Xlsx/Chart.php +++ b/src/PhpSpreadsheet/Writer/Xlsx/Chart.php @@ -219,10 +219,12 @@ class Chart extends WriterPart $chartTypes = self::getChartType($plotArea); $catIsMultiLevelSeries = $valIsMultiLevelSeries = false; $plotGroupingType = ''; + $chartType = null; foreach ($chartTypes as $chartType) { $objWriter->startElement('c:' . $chartType); $groupCount = $plotArea->getPlotGroupCount(); + $plotGroup = null; for ($i = 0; $i < $groupCount; ++$i) { $plotGroup = $plotArea->getPlotGroupByIndex($i); $groupType = $plotGroup->getPlotType(); @@ -244,7 +246,7 @@ class Chart extends WriterPart $this->writeDataLabels($objWriter, $layout); - if ($chartType === DataSeries::TYPE_LINECHART) { + if ($chartType === DataSeries::TYPE_LINECHART && $plotGroup) { // Line only, Line3D can't be smoothed $objWriter->startElement('c:smooth'); $objWriter->writeAttribute('val', (int) $plotGroup->getSmoothLine()); @@ -1079,6 +1081,7 @@ class Chart extends WriterPart } } + $plotSeriesIdx = 0; foreach ($plotSeriesOrder as $plotSeriesIdx => $plotSeriesRef) { $objWriter->startElement('c:ser'); diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/WeekDayTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/WeekDayTest.php index f1bc51f3..2e52a5d7 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/WeekDayTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/WeekDayTest.php @@ -2,7 +2,7 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\DateTime; -use PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Weekday; +use PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\WeekDay; class WeekDayTest extends AllSetupTeardown { @@ -28,8 +28,8 @@ class WeekDayTest extends AllSetupTeardown public function testWEEKDAYwith1904Calendar(): void { self::setMac1904(); - self::assertEquals(7, Weekday::funcWeekDay('1904-01-02')); - self::assertEquals(6, Weekday::funcWeekDay('1904-01-01')); - self::assertEquals(6, Weekday::funcWeekDay(null)); + self::assertEquals(7, WeekDay::funcWeekDay('1904-01-02')); + self::assertEquals(6, WeekDay::funcWeekDay('1904-01-01')); + self::assertEquals(6, WeekDay::funcWeekDay(null)); } } diff --git a/tests/PhpSpreadsheetTests/Reader/Security/XmlScannerTest.php b/tests/PhpSpreadsheetTests/Reader/Security/XmlScannerTest.php index f98ff7e1..c32c5743 100644 --- a/tests/PhpSpreadsheetTests/Reader/Security/XmlScannerTest.php +++ b/tests/PhpSpreadsheetTests/Reader/Security/XmlScannerTest.php @@ -37,7 +37,7 @@ class XmlScannerTest extends TestCase self::assertEquals($expectedResult, $result); // php 8.+ deprecated libxml_disable_entity_loader() - It's on by default - if (\PHP_VERSION_ID < 80000) { + if (isset($oldDisableEntityLoaderState)) { libxml_disable_entity_loader($oldDisableEntityLoaderState); } }