From 4ed02df336c008e6cfdf0e304966ebab0cfd568c Mon Sep 17 00:00:00 2001 From: Jo Franz Date: Wed, 14 Feb 2024 19:22:19 +0100 Subject: [PATCH] composer update with php 8.0 --- composer.lock | 94 +- vendor/autoload.php | 20 +- vendor/composer/ClassLoader.php | 137 +- vendor/composer/InstalledVersions.php | 33 +- vendor/composer/autoload_classmap.php | 2 +- vendor/composer/autoload_files.php | 2 +- vendor/composer/autoload_namespaces.php | 2 +- vendor/composer/autoload_psr4.php | 2 +- vendor/composer/autoload_real.php | 60 +- vendor/composer/autoload_static.php | 10 +- vendor/composer/installed.json | 96 +- vendor/composer/installed.php | 56 +- vendor/ezyang/htmlpurifier/CHANGELOG.md | 6 - vendor/ezyang/htmlpurifier/VERSION | 2 +- vendor/ezyang/htmlpurifier/composer.json | 5 +- .../library/HTMLPurifier.includes.php | 2 +- .../htmlpurifier/library/HTMLPurifier.php | 6 +- .../HTMLPurifier/AttrDef/CSS/FontFamily.php | 32 +- .../library/HTMLPurifier/AttrDef/URI/Host.php | 2 +- .../AttrTransform/TargetBlank.php | 6 +- .../library/HTMLPurifier/Bootstrap.php | 41 +- .../library/HTMLPurifier/CSSDefinition.php | 199 +- .../library/HTMLPurifier/Config.php | 2 +- .../DefinitionCache/Serializer.php | 11 +- .../HTMLPurifier/DefinitionCacheFactory.php | 2 +- .../Filter/ExtractStyleBlocks.php | 306 +-- .../library/HTMLPurifier/HTMLModule/Tidy.php | 1 + .../library/HTMLPurifier/LanguageFactory.php | 2 +- .../library/HTMLPurifier/Lexer.php | 2 +- .../library/HTMLPurifier/Lexer/DOMLex.php | 1 - .../HTMLPurifier/Printer/ConfigForm.php | 5 + .../library/HTMLPurifier/URIScheme/tel.php | 6 +- .../library/HTMLPurifier/UnitConverter.php | 6 +- .../phpspreadsheet/.php-cs-fixer.dist.php | 1 + vendor/phpoffice/phpspreadsheet/CHANGELOG.md | 168 +- .../phpoffice/phpspreadsheet/CONTRIBUTING.md | 39 +- vendor/phpoffice/phpspreadsheet/README.md | 50 +- vendor/phpoffice/phpspreadsheet/composer.json | 20 +- .../phpspreadsheet/phpstan-baseline.neon | 2105 ----------------- .../phpspreadsheet/phpstan-conditional.php | 7 +- .../phpspreadsheet/phpstan.neon.dist | 4 + .../phpspreadsheet/phpunit10.xml.dist | 15 + .../Calculation/Calculation.php | 370 +-- .../Calculation/DateTimeExcel/DateValue.php | 7 +- .../Calculation/DateTimeExcel/Month.php | 2 + .../Calculation/DateTimeExcel/TimeValue.php | 7 +- .../Calculation/Engine/FormattedNumber.php | 39 +- .../Engine/Operands/StructuredReference.php | 295 +++ .../Calculation/Engineering.php | 22 - .../Calculation/Engineering/BesselJ.php | 4 +- .../Calculation/Engineering/Complex.php | 2 +- .../Calculation/Engineering/ConvertBase.php | 2 + .../Calculation/Engineering/ConvertBinary.php | 6 +- .../Calculation/Engineering/ConvertUOM.php | 4 +- .../Calculation/Engineering/Erf.php | 15 +- .../Calculation/Engineering/ErfC.php | 15 +- .../PhpSpreadsheet/Calculation/Exception.php | 2 + .../PhpSpreadsheet/Calculation/Financial.php | 22 +- .../Calculation/Financial/Amortization.php | 5 +- .../CashFlow/Constant/Periodic/Interest.php | 3 +- .../Periodic/InterestAndPrincipal.php | 4 +- .../CashFlow/Variable/NonPeriodic.php | 80 +- .../Financial/CashFlow/Variable/Periodic.php | 1 + .../Calculation/Financial/Coupons.php | 2 +- .../Calculation/Financial/Depreciation.php | 6 + .../Financial/Securities/Price.php | 12 +- .../Financial/Securities/Yields.php | 4 +- .../PhpSpreadsheet/Calculation/Functions.php | 19 +- .../Calculation/Information/Value.php | 6 +- .../Calculation/Internal/MakeMatrix.php | 1 + .../Calculation/Logical/Operations.php | 81 +- .../PhpSpreadsheet/Calculation/LookupRef.php | 4 +- .../Calculation/LookupRef/Address.php | 2 +- .../Calculation/LookupRef/Formula.php | 2 +- .../Calculation/LookupRef/HLookup.php | 2 +- .../Calculation/LookupRef/Helpers.php | 2 +- .../Calculation/LookupRef/Lookup.php | 8 +- .../Calculation/LookupRef/LookupBase.php | 1 + .../Calculation/LookupRef/Matrix.php | 1 + .../Calculation/LookupRef/Offset.php | 18 +- .../Calculation/LookupRef/VLookup.php | 2 +- .../PhpSpreadsheet/Calculation/MathTrig.php | 2 +- .../Calculation/MathTrig/Combinations.php | 4 +- .../Calculation/MathTrig/Factorial.php | 3 +- .../Calculation/MathTrig/IntClass.php | 2 +- .../Calculation/MathTrig/Sum.php | 2 +- .../Calculation/Statistical.php | 8 +- .../Calculation/Statistical/Averages.php | 14 +- .../Calculation/Statistical/Conditional.php | 8 +- .../Statistical/Distributions/Beta.php | 3 + .../Statistical/Distributions/ChiSquared.php | 12 +- .../Statistical/Distributions/GammaBase.php | 18 +- .../Distributions/NewtonRaphson.php | 2 + .../Statistical/Distributions/Normal.php | 2 +- .../Distributions/StandardNormal.php | 4 +- .../Statistical/Distributions/StudentT.php | 2 - .../Calculation/Statistical/MaxMinBase.php | 5 + .../Calculation/Statistical/Maximum.php | 11 + .../Calculation/Statistical/Minimum.php | 11 + .../Calculation/Statistical/Percentiles.php | 6 +- .../Calculation/Statistical/Permutations.php | 11 +- .../Calculation/Statistical/Trends.php | 8 +- .../Calculation/Statistical/VarianceBase.php | 10 + .../PhpSpreadsheet/Calculation/TextData.php | 2 + .../Calculation/TextData/Extract.php | 10 +- .../Calculation/TextData/Format.php | 21 +- .../Calculation/TextData/Text.php | 6 +- .../src/PhpSpreadsheet/Cell/AddressRange.php | 2 + .../Cell/AdvancedValueBinder.php | 51 +- .../src/PhpSpreadsheet/Cell/Cell.php | 29 +- .../src/PhpSpreadsheet/Cell/Coordinate.php | 7 +- .../src/PhpSpreadsheet/Cell/DataValidator.php | 54 +- .../src/PhpSpreadsheet/Cell/IgnoredErrors.php | 66 + .../PhpSpreadsheet/CellReferenceHelper.php | 7 +- .../src/PhpSpreadsheet/Chart/Axis.php | 38 + .../src/PhpSpreadsheet/Chart/AxisText.php | 56 + .../src/PhpSpreadsheet/Chart/Chart.php | 25 + .../src/PhpSpreadsheet/Chart/Layout.php | 44 +- .../src/PhpSpreadsheet/Chart/Legend.php | 41 + .../src/PhpSpreadsheet/Chart/PlotArea.php | 45 + .../Chart/Renderer/JpGraphRendererBase.php | 29 +- .../Chart/Renderer/MtJpGraphRenderer.php | 6 +- .../src/PhpSpreadsheet/Chart/Title.php | 32 +- .../src/PhpSpreadsheet/DefinedName.php | 20 +- .../PhpSpreadsheet/Document/Properties.php | 16 +- .../src/PhpSpreadsheet/Helper/Downloader.php | 89 + .../src/PhpSpreadsheet/Helper/Handler.php | 46 + .../src/PhpSpreadsheet/Helper/Html.php | 35 +- .../src/PhpSpreadsheet/Helper/Sample.php | 47 +- .../src/PhpSpreadsheet/Helper/TextGrid.php | 16 +- .../src/PhpSpreadsheet/IOFactory.php | 8 +- .../src/PhpSpreadsheet/Reader/BaseReader.php | 16 +- .../src/PhpSpreadsheet/Reader/Csv.php | 5 +- .../src/PhpSpreadsheet/Reader/Gnumeric.php | 51 +- .../Reader/Gnumeric/PageSetup.php | 31 +- .../src/PhpSpreadsheet/Reader/Html.php | 168 +- .../src/PhpSpreadsheet/Reader/IReader.php | 19 +- .../src/PhpSpreadsheet/Reader/Ods.php | 106 +- .../Reader/Ods/PageSettings.php | 28 +- .../PhpSpreadsheet/Reader/Ods/Properties.php | 11 +- .../Reader/Security/XmlScanner.php | 37 +- .../src/PhpSpreadsheet/Reader/Xls.php | 65 +- .../src/PhpSpreadsheet/Reader/Xlsx.php | 223 +- .../src/PhpSpreadsheet/Reader/Xlsx/Chart.php | 166 +- .../Reader/Xlsx/ConditionalStyles.php | 5 +- .../Reader/Xlsx/DataValidations.php | 12 + .../PhpSpreadsheet/Reader/Xlsx/PageSetup.php | 3 +- .../PhpSpreadsheet/Reader/Xlsx/Properties.php | 3 + .../Reader/Xlsx/SharedFormula.php | 26 + .../src/PhpSpreadsheet/Reader/Xlsx/Styles.php | 38 +- .../src/PhpSpreadsheet/Reader/Xml.php | 167 +- .../Reader/Xml/DataValidations.php | 177 ++ .../Reader/Xml/PageSettings.php | 49 +- .../PhpSpreadsheet/Reader/Xml/Properties.php | 25 +- .../src/PhpSpreadsheet/Reader/Xml/Style.php | 40 +- .../PhpSpreadsheet/Reader/Xml/Style/Font.php | 4 +- .../Reader/Xml/Style/StyleBase.php | 4 +- .../src/PhpSpreadsheet/ReferenceHelper.php | 97 +- .../src/PhpSpreadsheet/RichText/Run.php | 4 +- .../PhpSpreadsheet/RichText/TextElement.php | 2 +- .../src/PhpSpreadsheet/Settings.php | 2 +- .../src/PhpSpreadsheet/Shared/Date.php | 35 +- .../src/PhpSpreadsheet/Shared/Escher.php | 8 +- .../Shared/Escher/DgContainer.php | 29 +- .../Escher/DgContainer/SpgrContainer.php | 2 +- .../Shared/Escher/DggContainer.php | 4 +- .../DggContainer/BstoreContainer/BSE.php | 7 +- .../src/PhpSpreadsheet/Shared/File.php | 16 +- .../src/PhpSpreadsheet/Shared/Font.php | 100 +- .../PhpSpreadsheet/Shared/JAMA/CHANGELOG.TXT | 16 - .../Shared/JAMA/LUDecomposition.php | 286 --- .../src/PhpSpreadsheet/Shared/JAMA/Matrix.php | 1167 --------- .../Shared/JAMA/QRDecomposition.php | 245 -- .../Shared/JAMA/utils/Maths.php | 31 - .../src/PhpSpreadsheet/Shared/OLE.php | 39 +- .../Shared/OLE/ChainedBlockStream.php | 9 +- .../src/PhpSpreadsheet/Shared/OLE/PPS.php | 44 +- .../PhpSpreadsheet/Shared/OLE/PPS/Root.php | 4 +- .../src/PhpSpreadsheet/Shared/OLERead.php | 10 +- .../PhpSpreadsheet/Shared/StringHelper.php | 12 + .../PhpSpreadsheet/Shared/Trend/BestFit.php | 27 + .../Shared/Trend/PolynomialBestFit.php | 14 +- .../src/PhpSpreadsheet/Shared/Trend/Trend.php | 10 +- .../src/PhpSpreadsheet/Shared/XMLWriter.php | 9 + .../src/PhpSpreadsheet/Shared/Xls.php | 4 +- .../src/PhpSpreadsheet/Spreadsheet.php | 35 +- .../src/PhpSpreadsheet/Style/Border.php | 6 +- .../src/PhpSpreadsheet/Style/Borders.php | 22 +- .../src/PhpSpreadsheet/Style/Color.php | 17 +- .../src/PhpSpreadsheet/Style/Conditional.php | 17 +- .../ConditionalFormatting/CellMatcher.php | 2 +- .../ConditionalDataBar.php | 8 +- .../ConditionalDataBarExtension.php | 8 +- .../ConditionalFormatValueObject.php | 11 +- .../ConditionalFormattingRuleExtension.php | 31 +- .../src/PhpSpreadsheet/Style/Font.php | 49 +- .../src/PhpSpreadsheet/Style/NumberFormat.php | 21 +- .../Style/NumberFormat/Formatter.php | 121 +- .../Style/NumberFormat/FractionFormatter.php | 23 +- .../Style/NumberFormat/NumberFormatter.php | 110 +- .../NumberFormat/PercentageFormatter.php | 1 + .../Style/NumberFormat/Wizard/Accounting.php | 102 + .../Style/NumberFormat/Wizard/Currency.php | 112 + .../Style/NumberFormat/Wizard/Date.php | 125 + .../Style/NumberFormat/Wizard/DateTime.php | 50 + .../NumberFormat/Wizard/DateTimeWizard.php | 44 + .../Style/NumberFormat/Wizard/Duration.php | 153 ++ .../Style/NumberFormat/Wizard/Locale.php | 37 + .../Style/NumberFormat/Wizard/Number.php | 57 + .../Style/NumberFormat/Wizard/NumberBase.php | 80 + .../Style/NumberFormat/Wizard/Percentage.php | 40 + .../Style/NumberFormat/Wizard/Scientific.php | 33 + .../Style/NumberFormat/Wizard/Time.php | 105 + .../Style/NumberFormat/Wizard/Wizard.php | 8 + .../src/PhpSpreadsheet/Style/RgbTint.php | 175 ++ .../src/PhpSpreadsheet/Style/Style.php | 22 +- .../src/PhpSpreadsheet/Theme.php | 269 +++ .../PhpSpreadsheet/Worksheet/AutoFilter.php | 8 +- .../src/PhpSpreadsheet/Worksheet/AutoFit.php | 51 + .../PhpSpreadsheet/Worksheet/CellIterator.php | 26 +- .../src/PhpSpreadsheet/Worksheet/Column.php | 21 +- .../Worksheet/ColumnCellIterator.php | 6 +- .../Worksheet/ColumnDimension.php | 8 +- .../Worksheet/Drawing/Shadow.php | 2 +- .../PhpSpreadsheet/Worksheet/PageBreak.php | 58 + .../PhpSpreadsheet/Worksheet/PageMargins.php | 15 - .../PhpSpreadsheet/Worksheet/PageSetup.php | 17 +- .../src/PhpSpreadsheet/Worksheet/Row.php | 21 +- .../Worksheet/RowCellIterator.php | 6 +- .../PhpSpreadsheet/Worksheet/RowDimension.php | 6 +- .../PhpSpreadsheet/Worksheet/RowIterator.php | 5 + .../PhpSpreadsheet/Worksheet/SheetView.php | 15 - .../src/PhpSpreadsheet/Worksheet/Table.php | 14 +- .../PhpSpreadsheet/Worksheet/Table/Column.php | 10 +- .../PhpSpreadsheet/Worksheet/Validations.php | 7 +- .../PhpSpreadsheet/Worksheet/Worksheet.php | 406 ++-- .../src/PhpSpreadsheet/Writer/Html.php | 74 +- .../src/PhpSpreadsheet/Writer/Ods.php | 17 +- .../PhpSpreadsheet/Writer/Ods/Cell/Style.php | 9 +- .../src/PhpSpreadsheet/Writer/Ods/Content.php | 18 +- .../src/PhpSpreadsheet/Writer/Ods/Formula.php | 1 + .../src/PhpSpreadsheet/Writer/Xls.php | 50 +- .../PhpSpreadsheet/Writer/Xls/BIFFwriter.php | 4 +- .../src/PhpSpreadsheet/Writer/Xls/Escher.php | 72 +- .../src/PhpSpreadsheet/Writer/Xls/Parser.php | 215 +- .../Writer/Xls/Style/CellBorder.php | 1 + .../PhpSpreadsheet/Writer/Xls/Workbook.php | 33 +- .../PhpSpreadsheet/Writer/Xls/Worksheet.php | 138 +- .../src/PhpSpreadsheet/Writer/Xls/Xf.php | 9 +- .../src/PhpSpreadsheet/Writer/Xlsx.php | 22 +- .../src/PhpSpreadsheet/Writer/Xlsx/Chart.php | 192 +- .../Writer/Xlsx/DefinedNames.php | 2 +- .../PhpSpreadsheet/Writer/Xlsx/DocProps.php | 3 + .../PhpSpreadsheet/Writer/Xlsx/Drawing.php | 2 +- .../Writer/Xlsx/FunctionPrefix.php | 2 +- .../src/PhpSpreadsheet/Writer/Xlsx/Rels.php | 8 +- .../Writer/Xlsx/StringTable.php | 9 +- .../src/PhpSpreadsheet/Writer/Xlsx/Style.php | 145 +- .../src/PhpSpreadsheet/Writer/Xlsx/Theme.php | 189 +- .../PhpSpreadsheet/Writer/Xlsx/Worksheet.php | 98 +- .../src/PhpSpreadsheet/Writer/ZipStream0.php | 17 + .../src/PhpSpreadsheet/Writer/ZipStream2.php | 21 + .../src/PhpSpreadsheet/Writer/ZipStream3.php | 22 + vendor/psr/http-client/CHANGELOG.md | 8 + vendor/psr/http-client/README.md | 2 +- vendor/psr/http-client/composer.json | 7 +- vendor/psr/http-factory/.gitignore | 2 - vendor/psr/http-factory/.pullapprove.yml | 7 - vendor/psr/http-factory/README.md | 12 +- vendor/psr/http-factory/composer.json | 4 +- vendor/psr/http-message/README.md | 5 +- vendor/psr/http-message/composer.json | 4 +- .../psr/http-message/docs/PSR7-Interfaces.md | 130 + vendor/psr/http-message/docs/PSR7-Usage.md | 159 ++ .../psr/http-message/src/MessageInterface.php | 16 +- .../psr/http-message/src/RequestInterface.php | 10 +- .../http-message/src/ResponseInterface.php | 4 +- .../src/ServerRequestInterface.php | 8 +- .../psr/http-message/src/StreamInterface.php | 12 +- .../src/UploadedFileInterface.php | 4 +- vendor/psr/http-message/src/UriInterface.php | 17 +- 281 files changed, 7344 insertions(+), 6392 deletions(-) delete mode 100644 vendor/ezyang/htmlpurifier/CHANGELOG.md create mode 100644 vendor/phpoffice/phpspreadsheet/phpunit10.xml.dist create mode 100644 vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/IgnoredErrors.php create mode 100644 vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/AxisText.php create mode 100644 vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Downloader.php create mode 100644 vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Handler.php create mode 100644 vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/SharedFormula.php create mode 100644 vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/DataValidations.php delete mode 100644 vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/JAMA/CHANGELOG.TXT delete mode 100644 vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/JAMA/LUDecomposition.php delete mode 100644 vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/JAMA/Matrix.php delete mode 100644 vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/JAMA/QRDecomposition.php delete mode 100644 vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/JAMA/utils/Maths.php create mode 100644 vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Accounting.php create mode 100644 vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Currency.php create mode 100644 vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Date.php create mode 100644 vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/DateTime.php create mode 100644 vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/DateTimeWizard.php create mode 100644 vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Duration.php create mode 100644 vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Locale.php create mode 100644 vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Number.php create mode 100644 vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/NumberBase.php create mode 100644 vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Percentage.php create mode 100644 vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Scientific.php create mode 100644 vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Time.php create mode 100644 vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Wizard.php create mode 100644 vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/RgbTint.php create mode 100644 vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Theme.php create mode 100644 vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/AutoFit.php create mode 100644 vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/PageBreak.php create mode 100644 vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/ZipStream0.php create mode 100644 vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/ZipStream2.php create mode 100644 vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/ZipStream3.php delete mode 100644 vendor/psr/http-factory/.gitignore delete mode 100644 vendor/psr/http-factory/.pullapprove.yml create mode 100644 vendor/psr/http-message/docs/PSR7-Interfaces.md create mode 100644 vendor/psr/http-message/docs/PSR7-Usage.md diff --git a/composer.lock b/composer.lock index 4b13b1a..9b9c570 100644 --- a/composer.lock +++ b/composer.lock @@ -4,24 +4,24 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "c6edb5b6f39ffb6ac1b73a023a9d7213", + "content-hash": "c5be71de5b45f8bed2c0b7198ef28808", "packages": [ { "name": "ezyang/htmlpurifier", - "version": "v4.16.0", + "version": "v4.17.0", "source": { "type": "git", "url": "https://github.com/ezyang/htmlpurifier.git", - "reference": "523407fb06eb9e5f3d59889b3978d5bfe94299c8" + "reference": "bbc513d79acf6691fa9cf10f192c90dd2957f18c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/523407fb06eb9e5f3d59889b3978d5bfe94299c8", - "reference": "523407fb06eb9e5f3d59889b3978d5bfe94299c8", + "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/bbc513d79acf6691fa9cf10f192c90dd2957f18c", + "reference": "bbc513d79acf6691fa9cf10f192c90dd2957f18c", "shasum": "" }, "require": { - "php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0" + "php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0" }, "require-dev": { "cerdic/css-tidy": "^1.7 || ^2.0", @@ -63,13 +63,13 @@ ], "support": { "issues": "https://github.com/ezyang/htmlpurifier/issues", - "source": "https://github.com/ezyang/htmlpurifier/tree/v4.16.0" + "source": "https://github.com/ezyang/htmlpurifier/tree/v4.17.0" }, - "time": "2022-09-18T07:06:19+00:00" + "time": "2023-11-17T15:01:25+00:00" }, { "name": "maennchen/zipstream-php", - "version": "v2.4.0", + "version": "2.4.0", "source": { "type": "git", "url": "https://github.com/maennchen/ZipStream-PHP.git", @@ -131,7 +131,7 @@ ], "support": { "issues": "https://github.com/maennchen/ZipStream-PHP/issues", - "source": "https://github.com/maennchen/ZipStream-PHP/tree/v2.4.0" + "source": "https://github.com/maennchen/ZipStream-PHP/tree/2.4.0" }, "funding": [ { @@ -317,16 +317,16 @@ }, { "name": "phpoffice/phpspreadsheet", - "version": "1.26.0", + "version": "1.29.0", "source": { "type": "git", "url": "https://github.com/PHPOffice/PhpSpreadsheet.git", - "reference": "5b6ceea9705b068f993e268e4debc566c2637063" + "reference": "fde2ccf55eaef7e86021ff1acce26479160a0fa0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/5b6ceea9705b068f993e268e4debc566c2637063", - "reference": "5b6ceea9705b068f993e268e4debc566c2637063", + "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/fde2ccf55eaef7e86021ff1acce26479160a0fa0", + "reference": "fde2ccf55eaef7e86021ff1acce26479160a0fa0", "shasum": "" }, "require": { @@ -344,7 +344,7 @@ "ext-zip": "*", "ext-zlib": "*", "ezyang/htmlpurifier": "^4.15", - "maennchen/zipstream-php": "^2.1", + "maennchen/zipstream-php": "^2.1 || ^3.0", "markbaker/complex": "^3.0", "markbaker/matrix": "^3.0", "php": "^7.4 || ^8.0", @@ -353,15 +353,15 @@ "psr/simple-cache": "^1.0 || ^2.0 || ^3.0" }, "require-dev": { - "dealerdirect/phpcodesniffer-composer-installer": "dev-master", + "dealerdirect/phpcodesniffer-composer-installer": "dev-main", "dompdf/dompdf": "^1.0 || ^2.0", "friendsofphp/php-cs-fixer": "^3.2", - "mitoteam/jpgraph": "^10.2.4", + "mitoteam/jpgraph": "^10.3", "mpdf/mpdf": "^8.1.1", "phpcompatibility/php-compatibility": "^9.3", "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^8.5 || ^9.0", + "phpunit/phpunit": "^8.5 || ^9.0 || ^10.0", "squizlabs/php_codesniffer": "^3.7", "tecnickcom/tcpdf": "^6.5" }, @@ -416,27 +416,27 @@ ], "support": { "issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues", - "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.26.0" + "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.29.0" }, - "time": "2022-12-21T12:22:06+00:00" + "time": "2023-06-14T22:48:31+00:00" }, { "name": "psr/http-client", - "version": "1.0.1", + "version": "1.0.3", "source": { "type": "git", "url": "https://github.com/php-fig/http-client.git", - "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", - "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", "shasum": "" }, "require": { "php": "^7.0 || ^8.0", - "psr/http-message": "^1.0" + "psr/http-message": "^1.0 || ^2.0" }, "type": "library", "extra": { @@ -456,7 +456,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for HTTP clients", @@ -468,27 +468,27 @@ "psr-18" ], "support": { - "source": "https://github.com/php-fig/http-client/tree/master" + "source": "https://github.com/php-fig/http-client" }, - "time": "2020-06-29T06:28:15+00:00" + "time": "2023-09-23T14:17:50+00:00" }, { "name": "psr/http-factory", - "version": "1.0.1", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/http-factory.git", - "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" + "reference": "e616d01114759c4c489f93b099585439f795fe35" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", - "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", + "reference": "e616d01114759c4c489f93b099585439f795fe35", "shasum": "" }, "require": { "php": ">=7.0.0", - "psr/http-message": "^1.0" + "psr/http-message": "^1.0 || ^2.0" }, "type": "library", "extra": { @@ -508,7 +508,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interfaces for PSR-7 HTTP message factories", @@ -523,31 +523,31 @@ "response" ], "support": { - "source": "https://github.com/php-fig/http-factory/tree/master" + "source": "https://github.com/php-fig/http-factory/tree/1.0.2" }, - "time": "2019-04-30T12:38:16+00:00" + "time": "2023-04-10T20:10:41+00:00" }, { "name": "psr/http-message", - "version": "1.0.1", + "version": "1.1", "source": { "type": "git", "url": "https://github.com/php-fig/http-message.git", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": "^7.2 || ^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.1.x-dev" } }, "autoload": { @@ -576,9 +576,9 @@ "response" ], "support": { - "source": "https://github.com/php-fig/http-message/tree/master" + "source": "https://github.com/php-fig/http-message/tree/1.1" }, - "time": "2016-08-06T14:39:51+00:00" + "time": "2023-04-04T09:50:52+00:00" }, { "name": "psr/simple-cache", @@ -638,7 +638,9 @@ "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, - "platform": [], + "platform": { + "php": "^8.0" + }, "platform-dev": [], - "plugin-api-version": "2.2.0" + "plugin-api-version": "2.6.0" } diff --git a/vendor/autoload.php b/vendor/autoload.php index 32d164d..92658e8 100644 --- a/vendor/autoload.php +++ b/vendor/autoload.php @@ -2,6 +2,24 @@ // autoload.php @generated by Composer +if (PHP_VERSION_ID < 50600) { + if (!headers_sent()) { + header('HTTP/1.1 500 Internal Server Error'); + } + $err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL; + if (!ini_get('display_errors')) { + if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { + fwrite(STDERR, $err); + } elseif (!headers_sent()) { + echo $err; + } + } + trigger_error( + $err, + E_USER_ERROR + ); +} + require_once __DIR__ . '/composer/autoload_real.php'; -return ComposerAutoloaderInitb73d891c2dbe91bf5725c7f0b1ea313b::getLoader(); +return ComposerAutoloaderInitcaeaff9f66c8e810b89bf44fd928a226::getLoader(); diff --git a/vendor/composer/ClassLoader.php b/vendor/composer/ClassLoader.php index afef3fa..7824d8f 100644 --- a/vendor/composer/ClassLoader.php +++ b/vendor/composer/ClassLoader.php @@ -42,35 +42,37 @@ */ class ClassLoader { - /** @var ?string */ + /** @var \Closure(string):void */ + private static $includeFile; + + /** @var string|null */ private $vendorDir; // PSR-4 /** - * @var array[] - * @psalm-var array> + * @var array> */ private $prefixLengthsPsr4 = array(); /** - * @var array[] - * @psalm-var array> + * @var array> */ private $prefixDirsPsr4 = array(); /** - * @var array[] - * @psalm-var array + * @var list */ private $fallbackDirsPsr4 = array(); // PSR-0 /** - * @var array[] - * @psalm-var array> + * List of PSR-0 prefixes + * + * Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2'))) + * + * @var array>> */ private $prefixesPsr0 = array(); /** - * @var array[] - * @psalm-var array + * @var list */ private $fallbackDirsPsr0 = array(); @@ -78,8 +80,7 @@ class ClassLoader private $useIncludePath = false; /** - * @var string[] - * @psalm-var array + * @var array */ private $classMap = array(); @@ -87,29 +88,29 @@ class ClassLoader private $classMapAuthoritative = false; /** - * @var bool[] - * @psalm-var array + * @var array */ private $missingClasses = array(); - /** @var ?string */ + /** @var string|null */ private $apcuPrefix; /** - * @var self[] + * @var array */ private static $registeredLoaders = array(); /** - * @param ?string $vendorDir + * @param string|null $vendorDir */ public function __construct($vendorDir = null) { $this->vendorDir = $vendorDir; + self::initializeIncludeClosure(); } /** - * @return string[] + * @return array> */ public function getPrefixes() { @@ -121,8 +122,7 @@ public function getPrefixes() } /** - * @return array[] - * @psalm-return array> + * @return array> */ public function getPrefixesPsr4() { @@ -130,8 +130,7 @@ public function getPrefixesPsr4() } /** - * @return array[] - * @psalm-return array + * @return list */ public function getFallbackDirs() { @@ -139,8 +138,7 @@ public function getFallbackDirs() } /** - * @return array[] - * @psalm-return array + * @return list */ public function getFallbackDirsPsr4() { @@ -148,8 +146,7 @@ public function getFallbackDirsPsr4() } /** - * @return string[] Array of classname => path - * @psalm-return array + * @return array Array of classname => path */ public function getClassMap() { @@ -157,8 +154,7 @@ public function getClassMap() } /** - * @param string[] $classMap Class to filename map - * @psalm-param array $classMap + * @param array $classMap Class to filename map * * @return void */ @@ -175,24 +171,25 @@ public function addClassMap(array $classMap) * Registers a set of PSR-0 directories for a given prefix, either * appending or prepending to the ones previously set for this prefix. * - * @param string $prefix The prefix - * @param string[]|string $paths The PSR-0 root directories - * @param bool $prepend Whether to prepend the directories + * @param string $prefix The prefix + * @param list|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories * * @return void */ public function add($prefix, $paths, $prepend = false) { + $paths = (array) $paths; if (!$prefix) { if ($prepend) { $this->fallbackDirsPsr0 = array_merge( - (array) $paths, + $paths, $this->fallbackDirsPsr0 ); } else { $this->fallbackDirsPsr0 = array_merge( $this->fallbackDirsPsr0, - (array) $paths + $paths ); } @@ -201,19 +198,19 @@ public function add($prefix, $paths, $prepend = false) $first = $prefix[0]; if (!isset($this->prefixesPsr0[$first][$prefix])) { - $this->prefixesPsr0[$first][$prefix] = (array) $paths; + $this->prefixesPsr0[$first][$prefix] = $paths; return; } if ($prepend) { $this->prefixesPsr0[$first][$prefix] = array_merge( - (array) $paths, + $paths, $this->prefixesPsr0[$first][$prefix] ); } else { $this->prefixesPsr0[$first][$prefix] = array_merge( $this->prefixesPsr0[$first][$prefix], - (array) $paths + $paths ); } } @@ -222,9 +219,9 @@ public function add($prefix, $paths, $prepend = false) * Registers a set of PSR-4 directories for a given namespace, either * appending or prepending to the ones previously set for this namespace. * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param string[]|string $paths The PSR-4 base directories - * @param bool $prepend Whether to prepend the directories + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param list|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories * * @throws \InvalidArgumentException * @@ -232,17 +229,18 @@ public function add($prefix, $paths, $prepend = false) */ public function addPsr4($prefix, $paths, $prepend = false) { + $paths = (array) $paths; if (!$prefix) { // Register directories for the root namespace. if ($prepend) { $this->fallbackDirsPsr4 = array_merge( - (array) $paths, + $paths, $this->fallbackDirsPsr4 ); } else { $this->fallbackDirsPsr4 = array_merge( $this->fallbackDirsPsr4, - (array) $paths + $paths ); } } elseif (!isset($this->prefixDirsPsr4[$prefix])) { @@ -252,18 +250,18 @@ public function addPsr4($prefix, $paths, $prepend = false) throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); } $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; - $this->prefixDirsPsr4[$prefix] = (array) $paths; + $this->prefixDirsPsr4[$prefix] = $paths; } elseif ($prepend) { // Prepend directories for an already registered namespace. $this->prefixDirsPsr4[$prefix] = array_merge( - (array) $paths, + $paths, $this->prefixDirsPsr4[$prefix] ); } else { // Append directories for an already registered namespace. $this->prefixDirsPsr4[$prefix] = array_merge( $this->prefixDirsPsr4[$prefix], - (array) $paths + $paths ); } } @@ -272,8 +270,8 @@ public function addPsr4($prefix, $paths, $prepend = false) * Registers a set of PSR-0 directories for a given prefix, * replacing any others previously set for this prefix. * - * @param string $prefix The prefix - * @param string[]|string $paths The PSR-0 base directories + * @param string $prefix The prefix + * @param list|string $paths The PSR-0 base directories * * @return void */ @@ -290,8 +288,8 @@ public function set($prefix, $paths) * Registers a set of PSR-4 directories for a given namespace, * replacing any others previously set for this namespace. * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param string[]|string $paths The PSR-4 base directories + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param list|string $paths The PSR-4 base directories * * @throws \InvalidArgumentException * @@ -425,7 +423,8 @@ public function unregister() public function loadClass($class) { if ($file = $this->findFile($class)) { - includeFile($file); + $includeFile = self::$includeFile; + $includeFile($file); return true; } @@ -476,9 +475,9 @@ public function findFile($class) } /** - * Returns the currently registered loaders indexed by their corresponding vendor directories. + * Returns the currently registered loaders keyed by their corresponding vendor directories. * - * @return self[] + * @return array */ public static function getRegisteredLoaders() { @@ -555,18 +554,26 @@ private function findFileWithExtension($class, $ext) return false; } -} -/** - * Scope isolated include. - * - * Prevents access to $this/self from included files. - * - * @param string $file - * @return void - * @private - */ -function includeFile($file) -{ - include $file; + /** + * @return void + */ + private static function initializeIncludeClosure() + { + if (self::$includeFile !== null) { + return; + } + + /** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + * + * @param string $file + * @return void + */ + self::$includeFile = \Closure::bind(static function($file) { + include $file; + }, null, null); + } } diff --git a/vendor/composer/InstalledVersions.php b/vendor/composer/InstalledVersions.php index d50e0c9..51e734a 100644 --- a/vendor/composer/InstalledVersions.php +++ b/vendor/composer/InstalledVersions.php @@ -21,12 +21,14 @@ * See also https://getcomposer.org/doc/07-runtime.md#installed-versions * * To require its presence, you can require `composer-runtime-api ^2.0` + * + * @final */ class InstalledVersions { /** * @var mixed[]|null - * @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array}|array{}|null + * @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array}|array{}|null */ private static $installed; @@ -37,7 +39,7 @@ class InstalledVersions /** * @var array[] - * @psalm-var array}> + * @psalm-var array}> */ private static $installedByVendor = array(); @@ -96,7 +98,7 @@ public static function isInstalled($packageName, $includeDevRequirements = true) { foreach (self::getInstalled() as $installed) { if (isset($installed['versions'][$packageName])) { - return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']); + return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false; } } @@ -117,7 +119,7 @@ public static function isInstalled($packageName, $includeDevRequirements = true) */ public static function satisfies(VersionParser $parser, $packageName, $constraint) { - $constraint = $parser->parseConstraints($constraint); + $constraint = $parser->parseConstraints((string) $constraint); $provided = $parser->parseConstraints(self::getVersionRanges($packageName)); return $provided->matches($constraint); @@ -241,7 +243,7 @@ public static function getInstallPath($packageName) /** * @return array - * @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string} + * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool} */ public static function getRootPackage() { @@ -255,7 +257,7 @@ public static function getRootPackage() * * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect. * @return array[] - * @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array} + * @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} */ public static function getRawData() { @@ -278,7 +280,7 @@ public static function getRawData() * Returns the raw data of all installed.php which are currently loaded for custom implementations * * @return array[] - * @psalm-return list}> + * @psalm-return list}> */ public static function getAllRawData() { @@ -301,7 +303,7 @@ public static function getAllRawData() * @param array[] $data A vendor/composer/installed.php data set * @return void * - * @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array} $data + * @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $data */ public static function reload($data) { @@ -311,7 +313,7 @@ public static function reload($data) /** * @return array[] - * @psalm-return list}> + * @psalm-return list}> */ private static function getInstalled() { @@ -326,7 +328,9 @@ private static function getInstalled() if (isset(self::$installedByVendor[$vendorDir])) { $installed[] = self::$installedByVendor[$vendorDir]; } elseif (is_file($vendorDir.'/composer/installed.php')) { - $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php'; + /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */ + $required = require $vendorDir.'/composer/installed.php'; + $installed[] = self::$installedByVendor[$vendorDir] = $required; if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) { self::$installed = $installed[count($installed) - 1]; } @@ -338,12 +342,17 @@ private static function getInstalled() // only require the installed.php file if this file is loaded from its dumped location, // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 if (substr(__DIR__, -8, 1) !== 'C') { - self::$installed = require __DIR__ . '/installed.php'; + /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */ + $required = require __DIR__ . '/installed.php'; + self::$installed = $required; } else { self::$installed = array(); } } - $installed[] = self::$installed; + + if (self::$installed !== array()) { + $installed[] = self::$installed; + } return $installed; } diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index bb58823..18e0a0b 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -2,7 +2,7 @@ // autoload_classmap.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php index c25686b..0a2315f 100644 --- a/vendor/composer/autoload_files.php +++ b/vendor/composer/autoload_files.php @@ -2,7 +2,7 @@ // autoload_files.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php index 1ee7a39..e60f352 100644 --- a/vendor/composer/autoload_namespaces.php +++ b/vendor/composer/autoload_namespaces.php @@ -2,7 +2,7 @@ // autoload_namespaces.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php index 33165a6..564c539 100644 --- a/vendor/composer/autoload_psr4.php +++ b/vendor/composer/autoload_psr4.php @@ -2,7 +2,7 @@ // autoload_psr4.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index 9326f51..7f09d54 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInitb73d891c2dbe91bf5725c7f0b1ea313b +class ComposerAutoloaderInitcaeaff9f66c8e810b89bf44fd928a226 { private static $loader; @@ -24,57 +24,27 @@ public static function getLoader() require __DIR__ . '/platform_check.php'; - spl_autoload_register(array('ComposerAutoloaderInitb73d891c2dbe91bf5725c7f0b1ea313b', 'loadClassLoader'), true, true); - self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__))); - spl_autoload_unregister(array('ComposerAutoloaderInitb73d891c2dbe91bf5725c7f0b1ea313b', 'loadClassLoader')); + spl_autoload_register(array('ComposerAutoloaderInitcaeaff9f66c8e810b89bf44fd928a226', 'loadClassLoader'), true, true); + self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__)); + spl_autoload_unregister(array('ComposerAutoloaderInitcaeaff9f66c8e810b89bf44fd928a226', 'loadClassLoader')); - $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); - if ($useStaticLoader) { - require __DIR__ . '/autoload_static.php'; + require __DIR__ . '/autoload_static.php'; + call_user_func(\Composer\Autoload\ComposerStaticInitcaeaff9f66c8e810b89bf44fd928a226::getInitializer($loader)); - call_user_func(\Composer\Autoload\ComposerStaticInitb73d891c2dbe91bf5725c7f0b1ea313b::getInitializer($loader)); - } else { - $map = require __DIR__ . '/autoload_namespaces.php'; - foreach ($map as $namespace => $path) { - $loader->set($namespace, $path); - } + $loader->register(true); - $map = require __DIR__ . '/autoload_psr4.php'; - foreach ($map as $namespace => $path) { - $loader->setPsr4($namespace, $path); - } + $filesToLoad = \Composer\Autoload\ComposerStaticInitcaeaff9f66c8e810b89bf44fd928a226::$files; + $requireFile = \Closure::bind(static function ($fileIdentifier, $file) { + if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { + $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; - $classMap = require __DIR__ . '/autoload_classmap.php'; - if ($classMap) { - $loader->addClassMap($classMap); + require $file; } - } - - $loader->register(true); - - if ($useStaticLoader) { - $includeFiles = Composer\Autoload\ComposerStaticInitb73d891c2dbe91bf5725c7f0b1ea313b::$files; - } else { - $includeFiles = require __DIR__ . '/autoload_files.php'; - } - foreach ($includeFiles as $fileIdentifier => $file) { - composerRequireb73d891c2dbe91bf5725c7f0b1ea313b($fileIdentifier, $file); + }, null, null); + foreach ($filesToLoad as $fileIdentifier => $file) { + $requireFile($fileIdentifier, $file); } return $loader; } } - -/** - * @param string $fileIdentifier - * @param string $file - * @return void - */ -function composerRequireb73d891c2dbe91bf5725c7f0b1ea313b($fileIdentifier, $file) -{ - if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { - $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; - - require $file; - } -} diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 2884ab7..662c8a9 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -4,7 +4,7 @@ namespace Composer\Autoload; -class ComposerStaticInitb73d891c2dbe91bf5725c7f0b1ea313b +class ComposerStaticInitcaeaff9f66c8e810b89bf44fd928a226 { public static $files = array ( '2cffec82183ee1cea088009cef9a6fc3' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php', @@ -87,10 +87,10 @@ class ComposerStaticInitb73d891c2dbe91bf5725c7f0b1ea313b public static function getInitializer(ClassLoader $loader) { return \Closure::bind(function () use ($loader) { - $loader->prefixLengthsPsr4 = ComposerStaticInitb73d891c2dbe91bf5725c7f0b1ea313b::$prefixLengthsPsr4; - $loader->prefixDirsPsr4 = ComposerStaticInitb73d891c2dbe91bf5725c7f0b1ea313b::$prefixDirsPsr4; - $loader->prefixesPsr0 = ComposerStaticInitb73d891c2dbe91bf5725c7f0b1ea313b::$prefixesPsr0; - $loader->classMap = ComposerStaticInitb73d891c2dbe91bf5725c7f0b1ea313b::$classMap; + $loader->prefixLengthsPsr4 = ComposerStaticInitcaeaff9f66c8e810b89bf44fd928a226::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInitcaeaff9f66c8e810b89bf44fd928a226::$prefixDirsPsr4; + $loader->prefixesPsr0 = ComposerStaticInitcaeaff9f66c8e810b89bf44fd928a226::$prefixesPsr0; + $loader->classMap = ComposerStaticInitcaeaff9f66c8e810b89bf44fd928a226::$classMap; }, null, ClassLoader::class); } diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 4a05444..265f665 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -2,21 +2,21 @@ "packages": [ { "name": "ezyang/htmlpurifier", - "version": "v4.16.0", - "version_normalized": "4.16.0.0", + "version": "v4.17.0", + "version_normalized": "4.17.0.0", "source": { "type": "git", "url": "https://github.com/ezyang/htmlpurifier.git", - "reference": "523407fb06eb9e5f3d59889b3978d5bfe94299c8" + "reference": "bbc513d79acf6691fa9cf10f192c90dd2957f18c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/523407fb06eb9e5f3d59889b3978d5bfe94299c8", - "reference": "523407fb06eb9e5f3d59889b3978d5bfe94299c8", + "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/bbc513d79acf6691fa9cf10f192c90dd2957f18c", + "reference": "bbc513d79acf6691fa9cf10f192c90dd2957f18c", "shasum": "" }, "require": { - "php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0" + "php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0" }, "require-dev": { "cerdic/css-tidy": "^1.7 || ^2.0", @@ -28,7 +28,7 @@ "ext-iconv": "Converts text to and from non-UTF-8 encodings", "ext-tidy": "Used for pretty-printing HTML" }, - "time": "2022-09-18T07:06:19+00:00", + "time": "2023-11-17T15:01:25+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -60,13 +60,13 @@ ], "support": { "issues": "https://github.com/ezyang/htmlpurifier/issues", - "source": "https://github.com/ezyang/htmlpurifier/tree/v4.16.0" + "source": "https://github.com/ezyang/htmlpurifier/tree/v4.17.0" }, "install-path": "../ezyang/htmlpurifier" }, { "name": "maennchen/zipstream-php", - "version": "v2.4.0", + "version": "2.4.0", "version_normalized": "2.4.0.0", "source": { "type": "git", @@ -131,7 +131,7 @@ ], "support": { "issues": "https://github.com/maennchen/ZipStream-PHP/issues", - "source": "https://github.com/maennchen/ZipStream-PHP/tree/v2.4.0" + "source": "https://github.com/maennchen/ZipStream-PHP/tree/2.4.0" }, "funding": [ { @@ -326,17 +326,17 @@ }, { "name": "phpoffice/phpspreadsheet", - "version": "1.26.0", - "version_normalized": "1.26.0.0", + "version": "1.29.0", + "version_normalized": "1.29.0.0", "source": { "type": "git", "url": "https://github.com/PHPOffice/PhpSpreadsheet.git", - "reference": "5b6ceea9705b068f993e268e4debc566c2637063" + "reference": "fde2ccf55eaef7e86021ff1acce26479160a0fa0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/5b6ceea9705b068f993e268e4debc566c2637063", - "reference": "5b6ceea9705b068f993e268e4debc566c2637063", + "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/fde2ccf55eaef7e86021ff1acce26479160a0fa0", + "reference": "fde2ccf55eaef7e86021ff1acce26479160a0fa0", "shasum": "" }, "require": { @@ -354,7 +354,7 @@ "ext-zip": "*", "ext-zlib": "*", "ezyang/htmlpurifier": "^4.15", - "maennchen/zipstream-php": "^2.1", + "maennchen/zipstream-php": "^2.1 || ^3.0", "markbaker/complex": "^3.0", "markbaker/matrix": "^3.0", "php": "^7.4 || ^8.0", @@ -363,15 +363,15 @@ "psr/simple-cache": "^1.0 || ^2.0 || ^3.0" }, "require-dev": { - "dealerdirect/phpcodesniffer-composer-installer": "dev-master", + "dealerdirect/phpcodesniffer-composer-installer": "dev-main", "dompdf/dompdf": "^1.0 || ^2.0", "friendsofphp/php-cs-fixer": "^3.2", - "mitoteam/jpgraph": "^10.2.4", + "mitoteam/jpgraph": "^10.3", "mpdf/mpdf": "^8.1.1", "phpcompatibility/php-compatibility": "^9.3", "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^8.5 || ^9.0", + "phpunit/phpunit": "^8.5 || ^9.0 || ^10.0", "squizlabs/php_codesniffer": "^3.7", "tecnickcom/tcpdf": "^6.5" }, @@ -382,7 +382,7 @@ "mpdf/mpdf": "Option for rendering PDF with PDF Writer", "tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer" }, - "time": "2022-12-21T12:22:06+00:00", + "time": "2023-06-14T22:48:31+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -428,30 +428,30 @@ ], "support": { "issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues", - "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.26.0" + "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.29.0" }, "install-path": "../phpoffice/phpspreadsheet" }, { "name": "psr/http-client", - "version": "1.0.1", - "version_normalized": "1.0.1.0", + "version": "1.0.3", + "version_normalized": "1.0.3.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-client.git", - "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", - "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", "shasum": "" }, "require": { "php": "^7.0 || ^8.0", - "psr/http-message": "^1.0" + "psr/http-message": "^1.0 || ^2.0" }, - "time": "2020-06-29T06:28:15+00:00", + "time": "2023-09-23T14:17:50+00:00", "type": "library", "extra": { "branch-alias": { @@ -471,7 +471,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for HTTP clients", @@ -483,30 +483,30 @@ "psr-18" ], "support": { - "source": "https://github.com/php-fig/http-client/tree/master" + "source": "https://github.com/php-fig/http-client" }, "install-path": "../psr/http-client" }, { "name": "psr/http-factory", - "version": "1.0.1", - "version_normalized": "1.0.1.0", + "version": "1.0.2", + "version_normalized": "1.0.2.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-factory.git", - "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" + "reference": "e616d01114759c4c489f93b099585439f795fe35" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", - "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", + "reference": "e616d01114759c4c489f93b099585439f795fe35", "shasum": "" }, "require": { "php": ">=7.0.0", - "psr/http-message": "^1.0" + "psr/http-message": "^1.0 || ^2.0" }, - "time": "2019-04-30T12:38:16+00:00", + "time": "2023-04-10T20:10:41+00:00", "type": "library", "extra": { "branch-alias": { @@ -526,7 +526,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interfaces for PSR-7 HTTP message factories", @@ -541,33 +541,33 @@ "response" ], "support": { - "source": "https://github.com/php-fig/http-factory/tree/master" + "source": "https://github.com/php-fig/http-factory/tree/1.0.2" }, "install-path": "../psr/http-factory" }, { "name": "psr/http-message", - "version": "1.0.1", - "version_normalized": "1.0.1.0", + "version": "1.1", + "version_normalized": "1.1.0.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-message.git", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": "^7.2 || ^8.0" }, - "time": "2016-08-06T14:39:51+00:00", + "time": "2023-04-04T09:50:52+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.1.x-dev" } }, "installation-source": "dist", @@ -597,7 +597,7 @@ "response" ], "support": { - "source": "https://github.com/php-fig/http-message/tree/master" + "source": "https://github.com/php-fig/http-message/tree/1.1" }, "install-path": "../psr/http-message" }, diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index 057fa67..e2c04cb 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -1,112 +1,112 @@ array( - 'pretty_version' => '1.2', - 'version' => '1.2.0.0', + 'name' => 'project60/org.project60.bic', + 'pretty_version' => '1.8.0-alpha1', + 'version' => '1.8.0.0-alpha1', + 'reference' => NULL, 'type' => 'civicrm-module', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), - 'reference' => NULL, - 'name' => 'project60/org.project60.bic', 'dev' => true, ), 'versions' => array( 'ezyang/htmlpurifier' => array( - 'pretty_version' => 'v4.16.0', - 'version' => '4.16.0.0', + 'pretty_version' => 'v4.17.0', + 'version' => '4.17.0.0', + 'reference' => 'bbc513d79acf6691fa9cf10f192c90dd2957f18c', 'type' => 'library', 'install_path' => __DIR__ . '/../ezyang/htmlpurifier', 'aliases' => array(), - 'reference' => '523407fb06eb9e5f3d59889b3978d5bfe94299c8', 'dev_requirement' => false, ), 'maennchen/zipstream-php' => array( - 'pretty_version' => 'v2.4.0', + 'pretty_version' => '2.4.0', 'version' => '2.4.0.0', + 'reference' => '3fa72e4c71a43f9e9118752a5c90e476a8dc9eb3', 'type' => 'library', 'install_path' => __DIR__ . '/../maennchen/zipstream-php', 'aliases' => array(), - 'reference' => '3fa72e4c71a43f9e9118752a5c90e476a8dc9eb3', 'dev_requirement' => false, ), 'markbaker/complex' => array( 'pretty_version' => '3.0.2', 'version' => '3.0.2.0', + 'reference' => '95c56caa1cf5c766ad6d65b6344b807c1e8405b9', 'type' => 'library', 'install_path' => __DIR__ . '/../markbaker/complex', 'aliases' => array(), - 'reference' => '95c56caa1cf5c766ad6d65b6344b807c1e8405b9', 'dev_requirement' => false, ), 'markbaker/matrix' => array( 'pretty_version' => '3.0.1', 'version' => '3.0.1.0', + 'reference' => '728434227fe21be27ff6d86621a1b13107a2562c', 'type' => 'library', 'install_path' => __DIR__ . '/../markbaker/matrix', 'aliases' => array(), - 'reference' => '728434227fe21be27ff6d86621a1b13107a2562c', 'dev_requirement' => false, ), 'myclabs/php-enum' => array( 'pretty_version' => '1.8.4', 'version' => '1.8.4.0', + 'reference' => 'a867478eae49c9f59ece437ae7f9506bfaa27483', 'type' => 'library', 'install_path' => __DIR__ . '/../myclabs/php-enum', 'aliases' => array(), - 'reference' => 'a867478eae49c9f59ece437ae7f9506bfaa27483', 'dev_requirement' => false, ), 'phpoffice/phpspreadsheet' => array( - 'pretty_version' => '1.26.0', - 'version' => '1.26.0.0', + 'pretty_version' => '1.29.0', + 'version' => '1.29.0.0', + 'reference' => 'fde2ccf55eaef7e86021ff1acce26479160a0fa0', 'type' => 'library', 'install_path' => __DIR__ . '/../phpoffice/phpspreadsheet', 'aliases' => array(), - 'reference' => '5b6ceea9705b068f993e268e4debc566c2637063', 'dev_requirement' => false, ), 'project60/org.project60.bic' => array( - 'pretty_version' => '1.2', - 'version' => '1.2.0.0', + 'pretty_version' => '1.8.0-alpha1', + 'version' => '1.8.0.0-alpha1', + 'reference' => NULL, 'type' => 'civicrm-module', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), - 'reference' => NULL, 'dev_requirement' => false, ), 'psr/http-client' => array( - 'pretty_version' => '1.0.1', - 'version' => '1.0.1.0', + 'pretty_version' => '1.0.3', + 'version' => '1.0.3.0', + 'reference' => 'bb5906edc1c324c9a05aa0873d40117941e5fa90', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/http-client', 'aliases' => array(), - 'reference' => '2dfb5f6c5eff0e91e20e913f8c5452ed95b86621', 'dev_requirement' => false, ), 'psr/http-factory' => array( - 'pretty_version' => '1.0.1', - 'version' => '1.0.1.0', + 'pretty_version' => '1.0.2', + 'version' => '1.0.2.0', + 'reference' => 'e616d01114759c4c489f93b099585439f795fe35', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/http-factory', 'aliases' => array(), - 'reference' => '12ac7fcd07e5b077433f5f2bee95b3a771bf61be', 'dev_requirement' => false, ), 'psr/http-message' => array( - 'pretty_version' => '1.0.1', - 'version' => '1.0.1.0', + 'pretty_version' => '1.1', + 'version' => '1.1.0.0', + 'reference' => 'cb6ce4845ce34a8ad9e68117c10ee90a29919eba', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/http-message', 'aliases' => array(), - 'reference' => 'f6561bf28d520154e4b0ec72be95418abe6d9363', 'dev_requirement' => false, ), 'psr/simple-cache' => array( 'pretty_version' => '3.0.0', 'version' => '3.0.0.0', + 'reference' => '764e0b3939f5ca87cb904f570ef9be2d78a07865', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/simple-cache', 'aliases' => array(), - 'reference' => '764e0b3939f5ca87cb904f570ef9be2d78a07865', 'dev_requirement' => false, ), ), diff --git a/vendor/ezyang/htmlpurifier/CHANGELOG.md b/vendor/ezyang/htmlpurifier/CHANGELOG.md deleted file mode 100644 index 55cb902..0000000 --- a/vendor/ezyang/htmlpurifier/CHANGELOG.md +++ /dev/null @@ -1,6 +0,0 @@ -# [4.16.0](https://github.com/ezyang/htmlpurifier/compare/v4.15.0...v4.16.0) (2022-09-18) - - -### Features - -* add semantic release ([#307](https://github.com/ezyang/htmlpurifier/issues/307)) ([db31243](https://github.com/ezyang/htmlpurifier/commit/db312435cb9d8d73395f75f9642a43ba6de5e903)), closes [#322](https://github.com/ezyang/htmlpurifier/issues/322) [#323](https://github.com/ezyang/htmlpurifier/issues/323) [#326](https://github.com/ezyang/htmlpurifier/issues/326) [#327](https://github.com/ezyang/htmlpurifier/issues/327) [#328](https://github.com/ezyang/htmlpurifier/issues/328) [#329](https://github.com/ezyang/htmlpurifier/issues/329) [#330](https://github.com/ezyang/htmlpurifier/issues/330) [#331](https://github.com/ezyang/htmlpurifier/issues/331) [#332](https://github.com/ezyang/htmlpurifier/issues/332) [#333](https://github.com/ezyang/htmlpurifier/issues/333) [#337](https://github.com/ezyang/htmlpurifier/issues/337) [#335](https://github.com/ezyang/htmlpurifier/issues/335) [ezyang/htmlpurifier#334](https://github.com/ezyang/htmlpurifier/issues/334) [#336](https://github.com/ezyang/htmlpurifier/issues/336) [#338](https://github.com/ezyang/htmlpurifier/issues/338) diff --git a/vendor/ezyang/htmlpurifier/VERSION b/vendor/ezyang/htmlpurifier/VERSION index f029ee5..8643e72 100644 --- a/vendor/ezyang/htmlpurifier/VERSION +++ b/vendor/ezyang/htmlpurifier/VERSION @@ -1 +1 @@ -4.15.0 \ No newline at end of file +4.17.0 \ No newline at end of file diff --git a/vendor/ezyang/htmlpurifier/composer.json b/vendor/ezyang/htmlpurifier/composer.json index d755829..ed46bd5 100644 --- a/vendor/ezyang/htmlpurifier/composer.json +++ b/vendor/ezyang/htmlpurifier/composer.json @@ -13,7 +13,7 @@ } ], "require": { - "php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0" + "php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0" }, "require-dev": { "cerdic/css-tidy": "^1.7 || ^2.0", @@ -38,7 +38,8 @@ "repositories": [ { "type": "vcs", - "url": "https://github.com/ezyang/simpletest.git" + "url": "https://github.com/ezyang/simpletest.git", + "no-api": true } ] } diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier.includes.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier.includes.php index 47ee013..77ebf2d 100644 --- a/vendor/ezyang/htmlpurifier/library/HTMLPurifier.includes.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier.includes.php @@ -7,7 +7,7 @@ * primary concern and you are using an opcode cache. PLEASE DO NOT EDIT THIS * FILE, changes will be overwritten the next time the script is run. * - * @version 4.15.0 + * @version 4.17.0 * * @warning * You must *not* include any other HTML Purifier files before this file, diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier.php index 26f0612..5c14a33 100644 --- a/vendor/ezyang/htmlpurifier/library/HTMLPurifier.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier.php @@ -19,7 +19,7 @@ */ /* - HTML Purifier 4.15.0 - Standards Compliant HTML Filtering + HTML Purifier 4.17.0 - Standards Compliant HTML Filtering Copyright (C) 2006-2008 Edward Z. Yang This library is free software; you can redistribute it and/or @@ -58,12 +58,12 @@ class HTMLPurifier * Version of HTML Purifier. * @type string */ - public $version = '4.15.0'; + public $version = '4.17.0'; /** * Constant with version of HTML Purifier. */ - const VERSION = '4.15.0'; + const VERSION = '4.17.0'; /** * Global configuration object. diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/FontFamily.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/FontFamily.php index 74e24c8..f1ff116 100644 --- a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/FontFamily.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/FontFamily.php @@ -10,23 +10,21 @@ class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef public function __construct() { - $this->mask = '_- '; - for ($c = 'a'; $c <= 'z'; $c++) { - $this->mask .= $c; - } - for ($c = 'A'; $c <= 'Z'; $c++) { - $this->mask .= $c; - } - for ($c = '0'; $c <= '9'; $c++) { - $this->mask .= $c; - } // cast-y, but should be fine - // special bytes used by UTF-8 - for ($i = 0x80; $i <= 0xFF; $i++) { - // We don't bother excluding invalid bytes in this range, - // because the our restriction of well-formed UTF-8 will - // prevent these from ever occurring. - $this->mask .= chr($i); - } + // Lowercase letters + $l = range('a', 'z'); + // Uppercase letters + $u = range('A', 'Z'); + // Digits + $d = range('0', '9'); + // Special bytes used by UTF-8 + $b = array_map('chr', range(0x80, 0xFF)); + // All valid characters for the mask + $c = array_merge($l, $u, $d, $b); + // Concatenate all valid characters into a string + // Use '_- ' as an initial value + $this->mask = array_reduce($c, function ($carry, $value) { + return $carry . $value; + }, '_- '); /* PHP's internal strcspn implementation is diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Host.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Host.php index 1beeaa5..ddc5dfb 100644 --- a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Host.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Host.php @@ -106,7 +106,7 @@ public function validate($string, $config, $context) // If we have Net_IDNA2 support, we can support IRIs by // punycoding them. (This is the most portable thing to do, // since otherwise we have to assume browsers support - } elseif ($config->get('Core.EnableIDNA')) { + } elseif ($config->get('Core.EnableIDNA') && class_exists('Net_IDNA2')) { $idna = new Net_IDNA2(array('encoding' => 'utf8', 'overlong' => false, 'strict' => true)); // we need to encode each period separately $parts = explode('.', $string); diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetBlank.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetBlank.php index dd63ea8..cc30ab8 100644 --- a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetBlank.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetBlank.php @@ -33,7 +33,11 @@ public function transform($attr, $config, $context) // XXX Kind of inefficient $url = $this->parser->parse($attr['href']); - $scheme = $url->getSchemeObj($config, $context); + + // Ignore invalid schemes (e.g. `javascript:`) + if (!($scheme = $url->getSchemeObj($config, $context))) { + return $attr; + } if ($scheme->browsable && !$url->isBenign($config, $context)) { $attr['target'] = '_blank'; diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Bootstrap.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Bootstrap.php index 707122b..bd8f998 100644 --- a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Bootstrap.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Bootstrap.php @@ -79,44 +79,11 @@ public static function getPath($class) public static function registerAutoload() { $autoload = array('HTMLPurifier_Bootstrap', 'autoload'); - if (($funcs = spl_autoload_functions()) === false) { + if (spl_autoload_functions() === false) { spl_autoload_register($autoload); - } elseif (function_exists('spl_autoload_unregister')) { - if (version_compare(PHP_VERSION, '5.3.0', '>=')) { - // prepend flag exists, no need for shenanigans - spl_autoload_register($autoload, true, true); - } else { - $buggy = version_compare(PHP_VERSION, '5.2.11', '<'); - $compat = version_compare(PHP_VERSION, '5.1.2', '<=') && - version_compare(PHP_VERSION, '5.1.0', '>='); - foreach ($funcs as $func) { - if ($buggy && is_array($func)) { - // :TRICKY: There are some compatibility issues and some - // places where we need to error out - $reflector = new ReflectionMethod($func[0], $func[1]); - if (!$reflector->isStatic()) { - throw new Exception( - 'HTML Purifier autoloader registrar is not compatible - with non-static object methods due to PHP Bug #44144; - Please do not use HTMLPurifier.autoload.php (or any - file that includes this file); instead, place the code: - spl_autoload_register(array(\'HTMLPurifier_Bootstrap\', \'autoload\')) - after your own autoloaders.' - ); - } - // Suprisingly, spl_autoload_register supports the - // Class::staticMethod callback format, although call_user_func doesn't - if ($compat) { - $func = implode('::', $func); - } - } - spl_autoload_unregister($func); - } - spl_autoload_register($autoload); - foreach ($funcs as $func) { - spl_autoload_register($func); - } - } + } else { + // prepend flag exists, no need for shenanigans + spl_autoload_register($autoload, true, true); } } } diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/CSSDefinition.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/CSSDefinition.php index 3f08b81..1bc419c 100644 --- a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/CSSDefinition.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/CSSDefinition.php @@ -13,7 +13,7 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition * Assoc array of attribute name to definition object. * @type HTMLPurifier_AttrDef[] */ - public $info = array(); + public $info = []; /** * Constructs the info array. The meat of this class. @@ -22,7 +22,7 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition protected function doSetup($config) { $this->info['text-align'] = new HTMLPurifier_AttrDef_Enum( - array('left', 'right', 'center', 'justify'), + ['left', 'right', 'center', 'justify'], false ); @@ -31,7 +31,7 @@ protected function doSetup($config) $this->info['border-right-style'] = $this->info['border-left-style'] = $this->info['border-top-style'] = new HTMLPurifier_AttrDef_Enum( - array( + [ 'none', 'hidden', 'dotted', @@ -42,42 +42,42 @@ protected function doSetup($config) 'ridge', 'inset', 'outset' - ), + ], false ); $this->info['border-style'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_style); $this->info['clear'] = new HTMLPurifier_AttrDef_Enum( - array('none', 'left', 'right', 'both'), + ['none', 'left', 'right', 'both'], false ); $this->info['float'] = new HTMLPurifier_AttrDef_Enum( - array('none', 'left', 'right'), + ['none', 'left', 'right'], false ); $this->info['font-style'] = new HTMLPurifier_AttrDef_Enum( - array('normal', 'italic', 'oblique'), + ['normal', 'italic', 'oblique'], false ); $this->info['font-variant'] = new HTMLPurifier_AttrDef_Enum( - array('normal', 'small-caps'), + ['normal', 'small-caps'], false ); $uri_or_none = new HTMLPurifier_AttrDef_CSS_Composite( - array( - new HTMLPurifier_AttrDef_Enum(array('none')), + [ + new HTMLPurifier_AttrDef_Enum(['none']), new HTMLPurifier_AttrDef_CSS_URI() - ) + ] ); $this->info['list-style-position'] = new HTMLPurifier_AttrDef_Enum( - array('inside', 'outside'), + ['inside', 'outside'], false ); $this->info['list-style-type'] = new HTMLPurifier_AttrDef_Enum( - array( + [ 'disc', 'circle', 'square', @@ -87,7 +87,7 @@ protected function doSetup($config) 'lower-alpha', 'upper-alpha', 'none' - ), + ], false ); $this->info['list-style-image'] = $uri_or_none; @@ -95,34 +95,34 @@ protected function doSetup($config) $this->info['list-style'] = new HTMLPurifier_AttrDef_CSS_ListStyle($config); $this->info['text-transform'] = new HTMLPurifier_AttrDef_Enum( - array('capitalize', 'uppercase', 'lowercase', 'none'), + ['capitalize', 'uppercase', 'lowercase', 'none'], false ); $this->info['color'] = new HTMLPurifier_AttrDef_CSS_Color(); $this->info['background-image'] = $uri_or_none; $this->info['background-repeat'] = new HTMLPurifier_AttrDef_Enum( - array('repeat', 'repeat-x', 'repeat-y', 'no-repeat') + ['repeat', 'repeat-x', 'repeat-y', 'no-repeat'] ); $this->info['background-attachment'] = new HTMLPurifier_AttrDef_Enum( - array('scroll', 'fixed') + ['scroll', 'fixed'] ); $this->info['background-position'] = new HTMLPurifier_AttrDef_CSS_BackgroundPosition(); $this->info['background-size'] = new HTMLPurifier_AttrDef_CSS_Composite( - array( + [ new HTMLPurifier_AttrDef_Enum( - array( + [ 'auto', 'cover', 'contain', 'initial', 'inherit', - ) + ] ), new HTMLPurifier_AttrDef_CSS_Percentage(), new HTMLPurifier_AttrDef_CSS_Length() - ) + ] ); $border_color = @@ -131,10 +131,10 @@ protected function doSetup($config) $this->info['border-left-color'] = $this->info['border-right-color'] = $this->info['background-color'] = new HTMLPurifier_AttrDef_CSS_Composite( - array( - new HTMLPurifier_AttrDef_Enum(array('transparent')), + [ + new HTMLPurifier_AttrDef_Enum(['transparent']), new HTMLPurifier_AttrDef_CSS_Color() - ) + ] ); $this->info['background'] = new HTMLPurifier_AttrDef_CSS_Background($config); @@ -146,32 +146,32 @@ protected function doSetup($config) $this->info['border-bottom-width'] = $this->info['border-left-width'] = $this->info['border-right-width'] = new HTMLPurifier_AttrDef_CSS_Composite( - array( - new HTMLPurifier_AttrDef_Enum(array('thin', 'medium', 'thick')), + [ + new HTMLPurifier_AttrDef_Enum(['thin', 'medium', 'thick']), new HTMLPurifier_AttrDef_CSS_Length('0') //disallow negative - ) + ] ); $this->info['border-width'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_width); $this->info['letter-spacing'] = new HTMLPurifier_AttrDef_CSS_Composite( - array( - new HTMLPurifier_AttrDef_Enum(array('normal')), + [ + new HTMLPurifier_AttrDef_Enum(['normal']), new HTMLPurifier_AttrDef_CSS_Length() - ) + ] ); $this->info['word-spacing'] = new HTMLPurifier_AttrDef_CSS_Composite( - array( - new HTMLPurifier_AttrDef_Enum(array('normal')), + [ + new HTMLPurifier_AttrDef_Enum(['normal']), new HTMLPurifier_AttrDef_CSS_Length() - ) + ] ); $this->info['font-size'] = new HTMLPurifier_AttrDef_CSS_Composite( - array( + [ new HTMLPurifier_AttrDef_Enum( - array( + [ 'xx-small', 'x-small', 'small', @@ -181,20 +181,20 @@ protected function doSetup($config) 'xx-large', 'larger', 'smaller' - ) + ] ), new HTMLPurifier_AttrDef_CSS_Percentage(), new HTMLPurifier_AttrDef_CSS_Length() - ) + ] ); $this->info['line-height'] = new HTMLPurifier_AttrDef_CSS_Composite( - array( - new HTMLPurifier_AttrDef_Enum(array('normal')), + [ + new HTMLPurifier_AttrDef_Enum(['normal']), new HTMLPurifier_AttrDef_CSS_Number(true), // no negatives new HTMLPurifier_AttrDef_CSS_Length('0'), new HTMLPurifier_AttrDef_CSS_Percentage(true) - ) + ] ); $margin = @@ -202,11 +202,11 @@ protected function doSetup($config) $this->info['margin-bottom'] = $this->info['margin-left'] = $this->info['margin-right'] = new HTMLPurifier_AttrDef_CSS_Composite( - array( + [ new HTMLPurifier_AttrDef_CSS_Length(), new HTMLPurifier_AttrDef_CSS_Percentage(), - new HTMLPurifier_AttrDef_Enum(array('auto')) - ) + new HTMLPurifier_AttrDef_Enum(['auto']) + ] ); $this->info['margin'] = new HTMLPurifier_AttrDef_CSS_Multiple($margin); @@ -217,41 +217,41 @@ protected function doSetup($config) $this->info['padding-bottom'] = $this->info['padding-left'] = $this->info['padding-right'] = new HTMLPurifier_AttrDef_CSS_Composite( - array( + [ new HTMLPurifier_AttrDef_CSS_Length('0'), new HTMLPurifier_AttrDef_CSS_Percentage(true) - ) + ] ); $this->info['padding'] = new HTMLPurifier_AttrDef_CSS_Multiple($padding); $this->info['text-indent'] = new HTMLPurifier_AttrDef_CSS_Composite( - array( + [ new HTMLPurifier_AttrDef_CSS_Length(), new HTMLPurifier_AttrDef_CSS_Percentage() - ) + ] ); $trusted_wh = new HTMLPurifier_AttrDef_CSS_Composite( - array( + [ new HTMLPurifier_AttrDef_CSS_Length('0'), new HTMLPurifier_AttrDef_CSS_Percentage(true), - new HTMLPurifier_AttrDef_Enum(array('auto', 'initial', 'inherit')) - ) + new HTMLPurifier_AttrDef_Enum(['auto', 'initial', 'inherit']) + ] ); $trusted_min_wh = new HTMLPurifier_AttrDef_CSS_Composite( - array( + [ new HTMLPurifier_AttrDef_CSS_Length('0'), new HTMLPurifier_AttrDef_CSS_Percentage(true), - new HTMLPurifier_AttrDef_Enum(array('initial', 'inherit')) - ) + new HTMLPurifier_AttrDef_Enum(['initial', 'inherit']) + ] ); $trusted_max_wh = new HTMLPurifier_AttrDef_CSS_Composite( - array( + [ new HTMLPurifier_AttrDef_CSS_Length('0'), new HTMLPurifier_AttrDef_CSS_Percentage(true), - new HTMLPurifier_AttrDef_Enum(array('none', 'initial', 'inherit')) - ) + new HTMLPurifier_AttrDef_Enum(['none', 'initial', 'inherit']) + ] ); $max = $config->get('CSS.MaxImgLength'); @@ -263,10 +263,10 @@ protected function doSetup($config) 'img', // For img tags: new HTMLPurifier_AttrDef_CSS_Composite( - array( + [ new HTMLPurifier_AttrDef_CSS_Length('0', $max), - new HTMLPurifier_AttrDef_Enum(array('auto')) - ) + new HTMLPurifier_AttrDef_Enum(['auto']) + ] ), // For everyone else: $trusted_wh @@ -279,10 +279,10 @@ protected function doSetup($config) 'img', // For img tags: new HTMLPurifier_AttrDef_CSS_Composite( - array( + [ new HTMLPurifier_AttrDef_CSS_Length('0', $max), - new HTMLPurifier_AttrDef_Enum(array('initial', 'inherit')) - ) + new HTMLPurifier_AttrDef_Enum(['initial', 'inherit']) + ] ), // For everyone else: $trusted_min_wh @@ -295,22 +295,39 @@ protected function doSetup($config) 'img', // For img tags: new HTMLPurifier_AttrDef_CSS_Composite( - array( + [ new HTMLPurifier_AttrDef_CSS_Length('0', $max), - new HTMLPurifier_AttrDef_Enum(array('none', 'initial', 'inherit')) - ) + new HTMLPurifier_AttrDef_Enum(['none', 'initial', 'inherit']) + ] ), // For everyone else: $trusted_max_wh ); + // text-decoration and related shorthands $this->info['text-decoration'] = new HTMLPurifier_AttrDef_CSS_TextDecoration(); + $this->info['text-decoration-line'] = new HTMLPurifier_AttrDef_Enum( + ['none', 'underline', 'overline', 'line-through', 'initial', 'inherit'] + ); + + $this->info['text-decoration-style'] = new HTMLPurifier_AttrDef_Enum( + ['solid', 'double', 'dotted', 'dashed', 'wavy', 'initial', 'inherit'] + ); + + $this->info['text-decoration-color'] = new HTMLPurifier_AttrDef_CSS_Color(); + + $this->info['text-decoration-thickness'] = new HTMLPurifier_AttrDef_CSS_Composite([ + new HTMLPurifier_AttrDef_CSS_Length(), + new HTMLPurifier_AttrDef_CSS_Percentage(), + new HTMLPurifier_AttrDef_Enum(['auto', 'from-font', 'initial', 'inherit']) + ]); + $this->info['font-family'] = new HTMLPurifier_AttrDef_CSS_FontFamily(); // this could use specialized code $this->info['font-weight'] = new HTMLPurifier_AttrDef_Enum( - array( + [ 'normal', 'bold', 'bolder', @@ -324,7 +341,7 @@ protected function doSetup($config) '700', '800', '900' - ), + ], false ); @@ -340,21 +357,21 @@ protected function doSetup($config) $this->info['border-right'] = new HTMLPurifier_AttrDef_CSS_Border($config); $this->info['border-collapse'] = new HTMLPurifier_AttrDef_Enum( - array('collapse', 'separate') + ['collapse', 'separate'] ); $this->info['caption-side'] = new HTMLPurifier_AttrDef_Enum( - array('top', 'bottom') + ['top', 'bottom'] ); $this->info['table-layout'] = new HTMLPurifier_AttrDef_Enum( - array('auto', 'fixed') + ['auto', 'fixed'] ); $this->info['vertical-align'] = new HTMLPurifier_AttrDef_CSS_Composite( - array( + [ new HTMLPurifier_AttrDef_Enum( - array( + [ 'baseline', 'sub', 'super', @@ -363,11 +380,11 @@ protected function doSetup($config) 'middle', 'bottom', 'text-bottom' - ) + ] ), new HTMLPurifier_AttrDef_CSS_Length(), new HTMLPurifier_AttrDef_CSS_Percentage() - ) + ] ); $this->info['border-spacing'] = new HTMLPurifier_AttrDef_CSS_Multiple(new HTMLPurifier_AttrDef_CSS_Length(), 2); @@ -375,7 +392,7 @@ protected function doSetup($config) // These CSS properties don't work on many browsers, but we live // in THE FUTURE! $this->info['white-space'] = new HTMLPurifier_AttrDef_Enum( - array('nowrap', 'normal', 'pre', 'pre-wrap', 'pre-line') + ['nowrap', 'normal', 'pre', 'pre-wrap', 'pre-line'] ); if ($config->get('CSS.Proprietary')) { @@ -422,21 +439,21 @@ protected function doSetupProprietary($config) // more CSS3 $this->info['page-break-after'] = $this->info['page-break-before'] = new HTMLPurifier_AttrDef_Enum( - array( + [ 'auto', 'always', 'avoid', 'left', 'right' - ) + ] ); - $this->info['page-break-inside'] = new HTMLPurifier_AttrDef_Enum(array('auto', 'avoid')); + $this->info['page-break-inside'] = new HTMLPurifier_AttrDef_Enum(['auto', 'avoid']); $border_radius = new HTMLPurifier_AttrDef_CSS_Composite( - array( + [ new HTMLPurifier_AttrDef_CSS_Percentage(true), // disallow negative new HTMLPurifier_AttrDef_CSS_Length('0') // disallow negative - )); + ]); $this->info['border-top-left-radius'] = $this->info['border-top-right-radius'] = @@ -453,7 +470,7 @@ protected function doSetupProprietary($config) protected function doSetupTricky($config) { $this->info['display'] = new HTMLPurifier_AttrDef_Enum( - array( + [ 'inline', 'block', 'list-item', @@ -472,12 +489,12 @@ protected function doSetupTricky($config) 'table-cell', 'table-caption', 'none' - ) + ] ); $this->info['visibility'] = new HTMLPurifier_AttrDef_Enum( - array('visible', 'hidden', 'collapse') + ['visible', 'hidden', 'collapse'] ); - $this->info['overflow'] = new HTMLPurifier_AttrDef_Enum(array('visible', 'hidden', 'auto', 'scroll')); + $this->info['overflow'] = new HTMLPurifier_AttrDef_Enum(['visible', 'hidden', 'auto', 'scroll']); $this->info['opacity'] = new HTMLPurifier_AttrDef_CSS_AlphaValue(); } @@ -487,23 +504,23 @@ protected function doSetupTricky($config) protected function doSetupTrusted($config) { $this->info['position'] = new HTMLPurifier_AttrDef_Enum( - array('static', 'relative', 'absolute', 'fixed') + ['static', 'relative', 'absolute', 'fixed'] ); $this->info['top'] = $this->info['left'] = $this->info['right'] = $this->info['bottom'] = new HTMLPurifier_AttrDef_CSS_Composite( - array( + [ new HTMLPurifier_AttrDef_CSS_Length(), new HTMLPurifier_AttrDef_CSS_Percentage(), - new HTMLPurifier_AttrDef_Enum(array('auto')), - ) + new HTMLPurifier_AttrDef_Enum(['auto']), + ] ); $this->info['z-index'] = new HTMLPurifier_AttrDef_CSS_Composite( - array( + [ new HTMLPurifier_AttrDef_Integer(), - new HTMLPurifier_AttrDef_Enum(array('auto')), - ) + new HTMLPurifier_AttrDef_Enum(['auto']), + ] ); } diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Config.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Config.php index 797d268..f7511ca 100644 --- a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Config.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Config.php @@ -21,7 +21,7 @@ class HTMLPurifier_Config * HTML Purifier's version * @type string */ - public $version = '4.15.0'; + public $version = '4.17.0'; /** * Whether or not to automatically finalize diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer.php index b82c6bb..bfad967 100644 --- a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer.php @@ -287,13 +287,14 @@ private function _testPermissions($dir, $chmod) } elseif (filegroup($dir) === posix_getgid()) { $chmod = $chmod | 0070; } else { - // PHP's probably running as nobody, so we'll - // need to give global permissions - $chmod = $chmod | 0777; + // PHP's probably running as nobody, it is + // not obvious how to fix this (777 is probably + // bad if you are multi-user), let the user figure it out + $chmod = null; } trigger_error( - 'Directory ' . $dir . ' not writable, ' . - 'please chmod to ' . decoct($chmod), + 'Directory ' . $dir . ' not writable. ' . + ($chmod === null ? '' : 'Please chmod to ' . decoct($chmod)), E_USER_WARNING ); } else { diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCacheFactory.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCacheFactory.php index fd1cc9b..3a0f461 100644 --- a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCacheFactory.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCacheFactory.php @@ -71,7 +71,7 @@ public function create($type, $config) return $this->caches[$method][$type]; } if (isset($this->implementations[$method]) && - class_exists($class = $this->implementations[$method], false)) { + class_exists($class = $this->implementations[$method])) { $cache = new $class($type); } else { if ($method != 'Serializer') { diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Filter/ExtractStyleBlocks.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Filter/ExtractStyleBlocks.php index 66f70b0..6f8e779 100644 --- a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Filter/ExtractStyleBlocks.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Filter/ExtractStyleBlocks.php @@ -146,175 +146,179 @@ public function cleanCSS($css, $config, $context) foreach ($this->_tidy->css as $k => $decls) { // $decls are all CSS declarations inside an @ selector $new_decls = array(); - foreach ($decls as $selector => $style) { - $selector = trim($selector); - if ($selector === '') { - continue; - } // should not happen - // Parse the selector - // Here is the relevant part of the CSS grammar: - // - // ruleset - // : selector [ ',' S* selector ]* '{' ... - // selector - // : simple_selector [ combinator selector | S+ [ combinator? selector ]? ]? - // combinator - // : '+' S* - // : '>' S* - // simple_selector - // : element_name [ HASH | class | attrib | pseudo ]* - // | [ HASH | class | attrib | pseudo ]+ - // element_name - // : IDENT | '*' - // ; - // class - // : '.' IDENT - // ; - // attrib - // : '[' S* IDENT S* [ [ '=' | INCLUDES | DASHMATCH ] S* - // [ IDENT | STRING ] S* ]? ']' - // ; - // pseudo - // : ':' [ IDENT | FUNCTION S* [IDENT S*]? ')' ] - // ; - // - // For reference, here are the relevant tokens: - // - // HASH #{name} - // IDENT {ident} - // INCLUDES == - // DASHMATCH |= - // STRING {string} - // FUNCTION {ident}\( - // - // And the lexical scanner tokens - // - // name {nmchar}+ - // nmchar [_a-z0-9-]|{nonascii}|{escape} - // nonascii [\240-\377] - // escape {unicode}|\\[^\r\n\f0-9a-f] - // unicode \\{h}}{1,6}(\r\n|[ \t\r\n\f])? - // ident -?{nmstart}{nmchar*} - // nmstart [_a-z]|{nonascii}|{escape} - // string {string1}|{string2} - // string1 \"([^\n\r\f\\"]|\\{nl}|{escape})*\" - // string2 \'([^\n\r\f\\"]|\\{nl}|{escape})*\' - // - // We'll implement a subset (in order to reduce attack - // surface); in particular: - // - // - No Unicode support - // - No escapes support - // - No string support (by proxy no attrib support) - // - element_name is matched against allowed - // elements (some people might find this - // annoying...) - // - Pseudo-elements one of :first-child, :link, - // :visited, :active, :hover, :focus + if (is_array($decls)) { + foreach ($decls as $selector => $style) { + $selector = trim($selector); + if ($selector === '') { + continue; + } // should not happen + // Parse the selector + // Here is the relevant part of the CSS grammar: + // + // ruleset + // : selector [ ',' S* selector ]* '{' ... + // selector + // : simple_selector [ combinator selector | S+ [ combinator? selector ]? ]? + // combinator + // : '+' S* + // : '>' S* + // simple_selector + // : element_name [ HASH | class | attrib | pseudo ]* + // | [ HASH | class | attrib | pseudo ]+ + // element_name + // : IDENT | '*' + // ; + // class + // : '.' IDENT + // ; + // attrib + // : '[' S* IDENT S* [ [ '=' | INCLUDES | DASHMATCH ] S* + // [ IDENT | STRING ] S* ]? ']' + // ; + // pseudo + // : ':' [ IDENT | FUNCTION S* [IDENT S*]? ')' ] + // ; + // + // For reference, here are the relevant tokens: + // + // HASH #{name} + // IDENT {ident} + // INCLUDES == + // DASHMATCH |= + // STRING {string} + // FUNCTION {ident}\( + // + // And the lexical scanner tokens + // + // name {nmchar}+ + // nmchar [_a-z0-9-]|{nonascii}|{escape} + // nonascii [\240-\377] + // escape {unicode}|\\[^\r\n\f0-9a-f] + // unicode \\{h}}{1,6}(\r\n|[ \t\r\n\f])? + // ident -?{nmstart}{nmchar*} + // nmstart [_a-z]|{nonascii}|{escape} + // string {string1}|{string2} + // string1 \"([^\n\r\f\\"]|\\{nl}|{escape})*\" + // string2 \'([^\n\r\f\\"]|\\{nl}|{escape})*\' + // + // We'll implement a subset (in order to reduce attack + // surface); in particular: + // + // - No Unicode support + // - No escapes support + // - No string support (by proxy no attrib support) + // - element_name is matched against allowed + // elements (some people might find this + // annoying...) + // - Pseudo-elements one of :first-child, :link, + // :visited, :active, :hover, :focus - // handle ruleset - $selectors = array_map('trim', explode(',', $selector)); - $new_selectors = array(); - foreach ($selectors as $sel) { - // split on +, > and spaces - $basic_selectors = preg_split('/\s*([+> ])\s*/', $sel, -1, PREG_SPLIT_DELIM_CAPTURE); - // even indices are chunks, odd indices are - // delimiters - $nsel = null; - $delim = null; // guaranteed to be non-null after - // two loop iterations - for ($i = 0, $c = count($basic_selectors); $i < $c; $i++) { - $x = $basic_selectors[$i]; - if ($i % 2) { - // delimiter - if ($x === ' ') { - $delim = ' '; - } else { - $delim = ' ' . $x . ' '; - } - } else { - // simple selector - $components = preg_split('/([#.:])/', $x, -1, PREG_SPLIT_DELIM_CAPTURE); - $sdelim = null; - $nx = null; - for ($j = 0, $cc = count($components); $j < $cc; $j++) { - $y = $components[$j]; - if ($j === 0) { - if ($y === '*' || isset($html_definition->info[$y = strtolower($y)])) { - $nx = $y; - } else { - // $nx stays null; this matters - // if we don't manage to find - // any valid selector content, - // in which case we ignore the - // outer $delim - } - } elseif ($j % 2) { - // set delimiter - $sdelim = $y; + // handle ruleset + $selectors = array_map('trim', explode(',', $selector)); + $new_selectors = array(); + foreach ($selectors as $sel) { + // split on +, > and spaces + $basic_selectors = preg_split('/\s*([+> ])\s*/', $sel, -1, PREG_SPLIT_DELIM_CAPTURE); + // even indices are chunks, odd indices are + // delimiters + $nsel = null; + $delim = null; // guaranteed to be non-null after + // two loop iterations + for ($i = 0, $c = count($basic_selectors); $i < $c; $i++) { + $x = $basic_selectors[$i]; + if ($i % 2) { + // delimiter + if ($x === ' ') { + $delim = ' '; } else { - $attrdef = null; - if ($sdelim === '#') { - $attrdef = $this->_id_attrdef; - } elseif ($sdelim === '.') { - $attrdef = $this->_class_attrdef; - } elseif ($sdelim === ':') { - $attrdef = $this->_enum_attrdef; + $delim = ' ' . $x . ' '; + } + } else { + // simple selector + $components = preg_split('/([#.:])/', $x, -1, PREG_SPLIT_DELIM_CAPTURE); + $sdelim = null; + $nx = null; + for ($j = 0, $cc = count($components); $j < $cc; $j++) { + $y = $components[$j]; + if ($j === 0) { + if ($y === '*' || isset($html_definition->info[$y = strtolower($y)])) { + $nx = $y; + } else { + // $nx stays null; this matters + // if we don't manage to find + // any valid selector content, + // in which case we ignore the + // outer $delim + } + } elseif ($j % 2) { + // set delimiter + $sdelim = $y; } else { - throw new HTMLPurifier_Exception('broken invariant sdelim and preg_split'); - } - $r = $attrdef->validate($y, $config, $context); - if ($r !== false) { - if ($r !== true) { - $y = $r; + $attrdef = null; + if ($sdelim === '#') { + $attrdef = $this->_id_attrdef; + } elseif ($sdelim === '.') { + $attrdef = $this->_class_attrdef; + } elseif ($sdelim === ':') { + $attrdef = $this->_enum_attrdef; + } else { + throw new HTMLPurifier_Exception('broken invariant sdelim and preg_split'); } - if ($nx === null) { - $nx = ''; + $r = $attrdef->validate($y, $config, $context); + if ($r !== false) { + if ($r !== true) { + $y = $r; + } + if ($nx === null) { + $nx = ''; + } + $nx .= $sdelim . $y; } - $nx .= $sdelim . $y; } } - } - if ($nx !== null) { - if ($nsel === null) { - $nsel = $nx; + if ($nx !== null) { + if ($nsel === null) { + $nsel = $nx; + } else { + $nsel .= $delim . $nx; + } } else { - $nsel .= $delim . $nx; + // delimiters to the left of invalid + // basic selector ignored } - } else { - // delimiters to the left of invalid - // basic selector ignored } } - } - if ($nsel !== null) { - if (!empty($scopes)) { - foreach ($scopes as $s) { - $new_selectors[] = "$s $nsel"; + if ($nsel !== null) { + if (!empty($scopes)) { + foreach ($scopes as $s) { + $new_selectors[] = "$s $nsel"; + } + } else { + $new_selectors[] = $nsel; } - } else { - $new_selectors[] = $nsel; } } - } - if (empty($new_selectors)) { - continue; - } - $selector = implode(', ', $new_selectors); - foreach ($style as $name => $value) { - if (!isset($css_definition->info[$name])) { - unset($style[$name]); + if (empty($new_selectors)) { continue; } - $def = $css_definition->info[$name]; - $ret = $def->validate($value, $config, $context); - if ($ret === false) { - unset($style[$name]); - } else { - $style[$name] = $ret; + $selector = implode(', ', $new_selectors); + foreach ($style as $name => $value) { + if (!isset($css_definition->info[$name])) { + unset($style[$name]); + continue; + } + $def = $css_definition->info[$name]; + $ret = $def->validate($value, $config, $context); + if ($ret === false) { + unset($style[$name]); + } else { + $style[$name] = $ret; + } } + $new_decls[$selector] = $style; } - $new_decls[$selector] = $style; + } else { + continue; } $new_css[$k] = $new_decls; } diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy.php index 12173ba..76fd93a 100644 --- a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy.php @@ -221,6 +221,7 @@ public function getFixType($name) */ public function makeFixes() { + return array(); } } diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/LanguageFactory.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/LanguageFactory.php index 4e35272..16a4f69 100644 --- a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/LanguageFactory.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/LanguageFactory.php @@ -109,7 +109,7 @@ public function create($config, $context, $code = false) } else { $class = 'HTMLPurifier_Language_' . $pcode; $file = $this->dir . '/Language/classes/' . $code . '.php'; - if (file_exists($file) || class_exists($class, false)) { + if (file_exists($file) || class_exists($class)) { $lang = new $class($config, $context); } else { // Go fallback diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Lexer.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Lexer.php index c21f364..1f552a1 100644 --- a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Lexer.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Lexer.php @@ -101,7 +101,7 @@ public static function create($config) break; } - if (class_exists('DOMDocument', false) && + if (class_exists('DOMDocument') && method_exists('DOMDocument', 'loadHTML') && !extension_loaded('domxml') ) { diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/DOMLex.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/DOMLex.php index ca5f25b..5e8104b 100644 --- a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/DOMLex.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/DOMLex.php @@ -104,7 +104,6 @@ public function tokenizeHTML($html, $config, $context) * To iterate is human, to recurse divine - L. Peter Deutsch * @param DOMNode $node DOMNode to be tokenized. * @param HTMLPurifier_Token[] $tokens Array-list of already tokenized tokens. - * @return HTMLPurifier_Token of node appended to previously passed tokens. */ protected function tokenizeDOM($node, &$tokens, $config) { diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.php index 33ae113..4c3ce17 100644 --- a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.php @@ -32,6 +32,11 @@ class HTMLPurifier_Printer_ConfigForm extends HTMLPurifier_Printer */ protected $compress = false; + /** + * @var HTMLPurifier_Config + */ + protected $genConfig; + /** * @param string $name Form element name for directives to be stuffed into * @param string $doc_url String documentation URL, will have fragment tagged on diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/tel.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/tel.php index 8cd1933..dfad8ef 100644 --- a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/tel.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/tel.php @@ -33,11 +33,11 @@ public function doValidate(&$uri, $config, $context) $uri->host = null; $uri->port = null; - // Delete all non-numeric characters, non-x characters + // Delete all non-numeric characters, commas, and non-x characters // from phone number, EXCEPT for a leading plus sign. - $uri->path = preg_replace('/(?!^\+)[^\dx]/', '', + $uri->path = preg_replace('/(?!^\+)[^\dx,]/', '', // Normalize e(x)tension to lower-case - str_replace('X', 'x', $uri->path)); + str_replace('X', 'x', rawurldecode($uri->path))); return true; } diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/UnitConverter.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/UnitConverter.php index 166f3bf..b5a1eab 100644 --- a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/UnitConverter.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/UnitConverter.php @@ -261,7 +261,7 @@ private function div($s1, $s2, $scale) */ private function round($n, $sigfigs) { - $new_log = (int)floor(log(abs($n), 10)); // Number of digits left of decimal - 1 + $new_log = (int)floor(log(abs((float)$n), 10)); // Number of digits left of decimal - 1 $rp = $sigfigs - $new_log - 1; // Number of decimal places needed $neg = $n < 0 ? '-' : ''; // Negative sign if ($this->bcmath) { @@ -276,7 +276,7 @@ private function round($n, $sigfigs) } return $n; } else { - return $this->scale(round($n, $sigfigs - $new_log - 1), $rp + 1); + return $this->scale(round((float)$n, $sigfigs - $new_log - 1), $rp + 1); } } @@ -300,7 +300,7 @@ private function scale($r, $scale) // Now we return it, truncating the zero that was rounded off. return substr($precise, 0, -1) . str_repeat('0', -$scale + 1); } - return sprintf('%.' . $scale . 'f', (float)$r); + return number_format((float)$r, $scale, '.', ''); } } diff --git a/vendor/phpoffice/phpspreadsheet/.php-cs-fixer.dist.php b/vendor/phpoffice/phpspreadsheet/.php-cs-fixer.dist.php index 4179c67..db70727 100644 --- a/vendor/phpoffice/phpspreadsheet/.php-cs-fixer.dist.php +++ b/vendor/phpoffice/phpspreadsheet/.php-cs-fixer.dist.php @@ -2,6 +2,7 @@ $finder = PhpCsFixer\Finder::create() ->exclude('vendor') + ->notPath('src/PhpSpreadsheet/Writer/ZipStream3.php') ->in(__DIR__); $config = new PhpCsFixer\Config(); diff --git a/vendor/phpoffice/phpspreadsheet/CHANGELOG.md b/vendor/phpoffice/phpspreadsheet/CHANGELOG.md index 9ce94a6..3883621 100644 --- a/vendor/phpoffice/phpspreadsheet/CHANGELOG.md +++ b/vendor/phpoffice/phpspreadsheet/CHANGELOG.md @@ -5,6 +5,158 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com) and this project adheres to [Semantic Versioning](https://semver.org). +## 1.29.0 - 2023-06-15 + +### Added + +- Wizards for defining Number Format masks for Dates and Times, including Durations/Intervals. [PR #3458](https://github.com/PHPOffice/PhpSpreadsheet/pull/3458) +- Specify data type in html tags. [Issue #3444](https://github.com/PHPOffice/PhpSpreadsheet/issues/3444) [PR #3445](https://github.com/PHPOffice/PhpSpreadsheet/pull/3445) +- Provide option to ignore hidden rows/columns in `toArray()` methods. [PR #3494](https://github.com/PHPOffice/PhpSpreadsheet/pull/3494) +- Font/Effects/Theme support for Chart Data Labels and Axis. [PR #3476](https://github.com/PHPOffice/PhpSpreadsheet/pull/3476) +- Font Themes support. [PR #3486](https://github.com/PHPOffice/PhpSpreadsheet/pull/3486) +- Ability to Ignore Cell Errors in Excel. [Issue #1141](https://github.com/PHPOffice/PhpSpreadsheet/issues/1141) [PR #3508](https://github.com/PHPOffice/PhpSpreadsheet/pull/3508) +- Unzipped Gnumeric file [PR #3591](https://github.com/PHPOffice/PhpSpreadsheet/pull/3591) + +### Changed + +- Xlsx Color schemes read in will be written out (previously Excel 2007-2010 Color scheme was always written); manipulation of those schemes before write, including restoring prior behavior, is provided [PR #3476](https://github.com/PHPOffice/PhpSpreadsheet/pull/3476) +- Memory and speed optimisations for Read Filters with Xlsx Files and Shared Formulae. [PR #3474](https://github.com/PHPOffice/PhpSpreadsheet/pull/3474) +- Allow `CellRange` and `CellAddress` objects for the `range` argument in the `rangeToArray()` method. [PR #3494](https://github.com/PHPOffice/PhpSpreadsheet/pull/3494) +- Stock charts will now read and reproduce `upDownBars` and subsidiary tags; these were previously ignored on read and hard-coded on write. [PR #3515](https://github.com/PHPOffice/PhpSpreadsheet/pull/3515) + +### Deprecated + +- Nothing + +### Removed + +- Nothing + +### Fixed + +- Updates Cell formula absolute ranges/references, and Defined Name absolute ranges/references when inserting/deleting rows/columns. [Issue #3368](https://github.com/PHPOffice/PhpSpreadsheet/issues/3368) [PR #3402](https://github.com/PHPOffice/PhpSpreadsheet/pull/3402) +- EOMONTH() and EDATE() Functions should round date value before evaluation. [Issue #3436](https://github.com/PHPOffice/PhpSpreadsheet/issues/3436) [PR #3437](https://github.com/PHPOffice/PhpSpreadsheet/pull/3437) +- NETWORKDAYS function erroneously being converted to NETWORK_xlfn.DAYS in Xlsx Writer. [Issue #3461](https://github.com/PHPOffice/PhpSpreadsheet/issues/3461) [PR #3463](https://github.com/PHPOffice/PhpSpreadsheet/pull/3463) +- Getting a style for a CellAddress instance fails if the worksheet is set in the CellAddress instance. [Issue #3439](https://github.com/PHPOffice/PhpSpreadsheet/issues/3439) [PR #3469](https://github.com/PHPOffice/PhpSpreadsheet/pull/3469) +- Shared Formulae outside the filter range when reading with a filter are not always being identified. [Issue #3473](https://github.com/PHPOffice/PhpSpreadsheet/issues/3473) [PR #3474](https://github.com/PHPOffice/PhpSpreadsheet/pull/3474) +- Xls Reader Conditional Styles. [PR #3400](https://github.com/PHPOffice/PhpSpreadsheet/pull/3400) +- Allow use of # and 0 digit placeholders in fraction masks. [PR #3401](https://github.com/PHPOffice/PhpSpreadsheet/pull/3401) +- Modify Date/Time check in the NumberFormatter for decimal/fractional times. [PR #3413](https://github.com/PHPOffice/PhpSpreadsheet/pull/3413) +- Misplaced Xml Writing Chart Label FillColor. [Issue #3397](https://github.com/PHPOffice/PhpSpreadsheet/issues/3397) [PR #3404](https://github.com/PHPOffice/PhpSpreadsheet/pull/3404) +- TEXT function ignores Time in DateTimeStamp. [Issue #3409](https://github.com/PHPOffice/PhpSpreadsheet/issues/3409) [PR #3411](https://github.com/PHPOffice/PhpSpreadsheet/pull/3411) +- Xlsx Column Autosize Approximate for CJK. [Issue #3405](https://github.com/PHPOffice/PhpSpreadsheet/issues/3405) [PR #3416](https://github.com/PHPOffice/PhpSpreadsheet/pull/3416) +- Correct Xlsx Parsing of quotePrefix="0". [Issue #3435](https://github.com/PHPOffice/PhpSpreadsheet/issues/3435) [PR #3438](https://github.com/PHPOffice/PhpSpreadsheet/pull/3438) +- More Display Options for Chart Axis and Legend. [Issue #3414](https://github.com/PHPOffice/PhpSpreadsheet/issues/3414) [PR #3434](https://github.com/PHPOffice/PhpSpreadsheet/pull/3434) +- Apply strict type checking to Complex suffix. [PR #3452](https://github.com/PHPOffice/PhpSpreadsheet/pull/3452) +- Incorrect Font Color Read Xlsx Rich Text Indexed Color Custom Palette. [Issue #3464](https://github.com/PHPOffice/PhpSpreadsheet/issues/3464) [PR #3465](https://github.com/PHPOffice/PhpSpreadsheet/pull/3465) +- Xlsx Writer Honor Alignment in Default Font. [Issue #3443](https://github.com/PHPOffice/PhpSpreadsheet/issues/3443) [PR #3459](https://github.com/PHPOffice/PhpSpreadsheet/pull/3459) +- Support Border for Charts. [PR #3462](https://github.com/PHPOffice/PhpSpreadsheet/pull/3462) +- Error in "this row" structured reference calculation (cached result from first row when using a range) [Issue #3504](https://github.com/PHPOffice/PhpSpreadsheet/issues/3504) [PR #3505](https://github.com/PHPOffice/PhpSpreadsheet/pull/3505) +- Allow colour palette index references in Number Format masks [Issue #3511](https://github.com/PHPOffice/PhpSpreadsheet/issues/3511) [PR #3512](https://github.com/PHPOffice/PhpSpreadsheet/pull/3512) +- Xlsx Reader formula with quotePrefix [Issue #3495](https://github.com/PHPOffice/PhpSpreadsheet/issues/3495) [PR #3497](https://github.com/PHPOffice/PhpSpreadsheet/pull/3497) +- Handle REF error as part of range [Issue #3453](https://github.com/PHPOffice/PhpSpreadsheet/issues/3453) [PR #3467](https://github.com/PHPOffice/PhpSpreadsheet/pull/3467) +- Handle Absolute Pathnames in Rels File [Issue #3553](https://github.com/PHPOffice/PhpSpreadsheet/issues/3553) [PR #3554](https://github.com/PHPOffice/PhpSpreadsheet/pull/3554) +- Return Page Breaks in Order [Issue #3552](https://github.com/PHPOffice/PhpSpreadsheet/issues/3552) [PR #3555](https://github.com/PHPOffice/PhpSpreadsheet/pull/3555) +- Add position attribute for MemoryDrawing in Html [Issue #3529](https://github.com/PHPOffice/PhpSpreadsheet/issues/3529 [PR #3535](https://github.com/PHPOffice/PhpSpreadsheet/pull/3535) +- Allow Index_number as Array for VLOOKUP/HLOOKUP [Issue #3561](https://github.com/PHPOffice/PhpSpreadsheet/issues/3561 [PR #3570](https://github.com/PHPOffice/PhpSpreadsheet/pull/3570) +- Add Unsupported Options in Xml Spreadsheet [Issue #3566](https://github.com/PHPOffice/PhpSpreadsheet/issues/3566 [Issue #3568](https://github.com/PHPOffice/PhpSpreadsheet/issues/3568 [Issue #3569](https://github.com/PHPOffice/PhpSpreadsheet/issues/3569 [PR #3567](https://github.com/PHPOffice/PhpSpreadsheet/pull/3567) +- Changes to NUMBERVALUE, VALUE, DATEVALUE, TIMEVALUE [Issue #3574](https://github.com/PHPOffice/PhpSpreadsheet/issues/3574 [PR #3575](https://github.com/PHPOffice/PhpSpreadsheet/pull/3575) +- Redo calculation of color tinting [Issue #3550](https://github.com/PHPOffice/PhpSpreadsheet/issues/3550) [PR #3580](https://github.com/PHPOffice/PhpSpreadsheet/pull/3580) +- Accommodate Slash with preg_quote [PR #3582](https://github.com/PHPOffice/PhpSpreadsheet/pull/3582) [PR #3583](https://github.com/PHPOffice/PhpSpreadsheet/pull/3583) [PR #3584](https://github.com/PHPOffice/PhpSpreadsheet/pull/3584) +- HyperlinkBase Property and Html Handling of Properties [Issue #3573](https://github.com/PHPOffice/PhpSpreadsheet/issues/3573) [PR #3589](https://github.com/PHPOffice/PhpSpreadsheet/pull/3589) +- Improvements for Data Validation [Issue #3592](https://github.com/PHPOffice/PhpSpreadsheet/issues/3592) [Issue #3594](https://github.com/PHPOffice/PhpSpreadsheet/issues/3594) [PR #3605](https://github.com/PHPOffice/PhpSpreadsheet/pull/3605) + +## 1.28.0 - 2023-02-25 + +### Added + +- Support for configuring a Chart Title's overlay [PR #3325](https://github.com/PHPOffice/PhpSpreadsheet/pull/3325) +- Wizards for defining Number Format masks for Numbers, Percentages, Scientific, Currency and Accounting [PR #3334](https://github.com/PHPOffice/PhpSpreadsheet/pull/3334) +- Support for fixed value divisor in fractional Number Format Masks [PR #3339](https://github.com/PHPOffice/PhpSpreadsheet/pull/3339) +- Allow More Fonts/Fontnames for Exact Width Calculation [PR #3326](https://github.com/PHPOffice/PhpSpreadsheet/pull/3326) [Issue #3190](https://github.com/PHPOffice/PhpSpreadsheet/issues/3190) +- Allow override of the Value Binder when setting a Cell value [PR #3361](https://github.com/PHPOffice/PhpSpreadsheet/pull/3361) + +### Changed + +- Improved handling for @ placeholder in Number Format Masks [PR #3344](https://github.com/PHPOffice/PhpSpreadsheet/pull/3344) +- Improved handling for ? placeholder in Number Format Masks [PR #3394](https://github.com/PHPOffice/PhpSpreadsheet/pull/3394) +- Improved support for locale settings and currency codes when matching formatted strings to numerics in the Calculation Engine [PR #3373](https://github.com/PHPOffice/PhpSpreadsheet/pull/3373) and [PR #3374](https://github.com/PHPOffice/PhpSpreadsheet/pull/3374) +- Improved support for locale settings and matching in the Advanced Value Binder [PR #3376](https://github.com/PHPOffice/PhpSpreadsheet/pull/3376) + +### Deprecated + +- Rationalisation of Pre-defined Currency Format Masks + +### Removed + +- Nothing + +### Fixed + +- Calculation Engine doesn't evaluate Defined Name when default cell A1 is quote-prefixed [Issue #3335](https://github.com/PHPOffice/PhpSpreadsheet/issues/3335) [PR #3336](https://github.com/PHPOffice/PhpSpreadsheet/pull/3336) +- XLSX Writer - Array Formulas do not include function prefix [Issue #3337](https://github.com/PHPOffice/PhpSpreadsheet/issues/3337) [PR #3338](https://github.com/PHPOffice/PhpSpreadsheet/pull/3338) +- Permit Max Column for Row Breaks [Issue #3143](https://github.com/PHPOffice/PhpSpreadsheet/issues/3143) [PR #3345](https://github.com/PHPOffice/PhpSpreadsheet/pull/3345) +- AutoSize Columns should allow for dropdown icon when AutoFilter is for a Table [Issue #3356](https://github.com/PHPOffice/PhpSpreadsheet/issues/3356) [PR #3358](https://github.com/PHPOffice/PhpSpreadsheet/pull/3358) and for Center Alignment of Headers [Issue #3395](https://github.com/PHPOffice/PhpSpreadsheet/issues/3395) [PR #3399](https://github.com/PHPOffice/PhpSpreadsheet/pull/3399) +- Decimal Precision for Scientific Number Format Mask [Issue #3381](https://github.com/PHPOffice/PhpSpreadsheet/issues/3381) [PR #3382](https://github.com/PHPOffice/PhpSpreadsheet/pull/3382) +- Xls Writer Parser Handle Boolean Literals as Function Arguments [Issue #3369](https://github.com/PHPOffice/PhpSpreadsheet/issues/3369) [PR #3391](https://github.com/PHPOffice/PhpSpreadsheet/pull/3391) +- Conditional Formatting Improvements for Xlsx [Issue #3370](https://github.com/PHPOffice/PhpSpreadsheet/issues/3370) [Issue #3202](https://github.com/PHPOffice/PhpSpreadsheet/issues/3302) [PR #3372](https://github.com/PHPOffice/PhpSpreadsheet/pull/3372) +- Coerce Bool to Int for Mathematical Operations on Arrays [Issue #3389](https://github.com/PHPOffice/PhpSpreadsheet/issues/3389) [Issue #3396](https://github.com/PHPOffice/PhpSpreadsheet/issues/3396) [PR #3392](https://github.com/PHPOffice/PhpSpreadsheet/pull/3392) + +## 1.27.1 - 2023-02-08 + +### Added + +- Nothing + +### Changed + +- Nothing + +### Deprecated + +- Nothing + +### Removed + +- Nothing + +### Fixed + +- Fix Composer --dev dependency issue with dealerdirect/phpcodesniffer-composer-installer renaming their `master` branch to `main` + + +## 1.27.0 - 2023-01-24 + +### Added + +- Option to specify a range of columns/rows for the Row/Column `isEmpty()` methods [PR #3315](https://github.com/PHPOffice/PhpSpreadsheet/pull/3315) +- Option for Cell Iterator to return a null value or create and return a new cell when accessing a cell that doesn't exist [PR #3314](https://github.com/PHPOffice/PhpSpreadsheet/pull/3314) +- Support for Structured References in the Calculation Engine [PR #3261](https://github.com/PHPOffice/PhpSpreadsheet/pull/3261) +- Limited Support for Form Controls [PR #3130](https://github.com/PHPOffice/PhpSpreadsheet/pull/3130) [Issue #2396](https://github.com/PHPOffice/PhpSpreadsheet/issues/2396) [Issue #1770](https://github.com/PHPOffice/PhpSpreadsheet/issues/1770) [Issue #2388](https://github.com/PHPOffice/PhpSpreadsheet/issues/2388) [Issue #2904](https://github.com/PHPOffice/PhpSpreadsheet/issues/2904) [Issue #2661](https://github.com/PHPOffice/PhpSpreadsheet/issues/2661) + +### Changed + +- `toFormattedString` will now always return a string. This can affect the results of `toArray`, `namedRangeToArray`, and `rangeToArray`. [PR #3304](https://github.com/PHPOffice/PhpSpreadsheet/pull/3304) + +### Deprecated + +- Nothing + +### Removed + +- Shared/JAMA is removed. [PR #3260](https://github.com/PHPOffice/PhpSpreadsheet/pull/3260) + +### Fixed + +- Namespace-Aware Code for SheetViewOptions, SheetProtection [PR #3230](https://github.com/PHPOffice/PhpSpreadsheet/pull/3230) +- Additional Method for XIRR if Newton-Raphson Doesn't Converge [Issue #689](https://github.com/PHPOffice/PhpSpreadsheet/issues/689) [PR #3262](https://github.com/PHPOffice/PhpSpreadsheet/pull/3262) +- Better Handling of Composite Charts [Issue #2333](https://github.com/PHPOffice/PhpSpreadsheet/issues/2333) [PR #3265](https://github.com/PHPOffice/PhpSpreadsheet/pull/3265) +- Update Column Reference for Columns Beginning with Y and Z [Issue #3263](https://github.com/PHPOffice/PhpSpreadsheet/issues/3263) [PR #3264](https://github.com/PHPOffice/PhpSpreadsheet/pull/3264) +- Honor Fit to 1-Page Height Html/Pdf [Issue #3266](https://github.com/PHPOffice/PhpSpreadsheet/issues/3266) [PR #3279](https://github.com/PHPOffice/PhpSpreadsheet/pull/3279) +- AND/OR/XOR Handling of Literal Strings [PR #3287](https://github.com/PHPOffice/PhpSpreadsheet/pull/3287) +- Xls Reader Vertical Break and Writer Page Order [Issue #3305](https://github.com/PHPOffice/PhpSpreadsheet/issues/3305) [PR #3306](https://github.com/PHPOffice/PhpSpreadsheet/pull/3306) + + ## 1.26.0 - 2022-12-21 ### Added @@ -112,7 +264,7 @@ and this project adheres to [Semantic Versioning](https://semver.org). ### Fixed -- Fix update to defined names when inserting/deleting rows/columns [Issue #3076](https://github.com/PHPOffice/PhpSpreadsheet/issues/3076) [PR #3077](https://github.com/PHPOffice/PhpSpreadsheet/pull/3077) +- Fix update to defined names when inserting/deleting rows/columns [Issue #3076](https://github.com/PHPOffice/PhpSpreadsheet/issues/3076) [PR #3077](https://github.com/PHPOffice/PhpSpreadsheet/pull/3077) - Fix DataValidation sqRef when inserting/deleting rows/columns [Issue #3056](https://github.com/PHPOffice/PhpSpreadsheet/issues/3056) [PR #3074](https://github.com/PHPOffice/PhpSpreadsheet/pull/3074) - Named ranges not usable as anchors in OFFSET function [Issue #3013](https://github.com/PHPOffice/PhpSpreadsheet/issues/3013) - Fully flatten an array [Issue #2955](https://github.com/PHPOffice/PhpSpreadsheet/issues/2955) [PR #2956](https://github.com/PHPOffice/PhpSpreadsheet/pull/2956) @@ -302,7 +454,7 @@ Note that this will be the last 1.x branch release before the 2.x release. We wi - Use color palette if supplied [Issue #2499](https://github.com/PHPOffice/PhpSpreadsheet/issues/2499) [PR #2595](https://github.com/PHPOffice/PhpSpreadsheet/pull/2595) - Xls reader treat drawing offsets as int rather than float [PR #2648](https://github.com/PHPOffice/PhpSpreadsheet/pull/2648) - Handle booleans in conditional styles properly [PR #2654](https://github.com/PHPOffice/PhpSpreadsheet/pull/2654) -- Fix for reading files in the root directory of a ZipFile, which should not be prefixed by relative paths ("./") as dirname($filename) does by default. +- Fix for reading files in the root directory of a ZipFile, which should not be prefixed by relative paths ("./") as dirname($filename) does by default. - Fix invalid style of cells in empty columns with columnDimensions and rows with rowDimensions in added external sheet. [PR #2739](https://github.com/PHPOffice/PhpSpreadsheet/pull/2739) - Time Interval Formatting [Issue #2768](https://github.com/PHPOffice/PhpSpreadsheet/issues/2768) [PR #2772](https://github.com/PHPOffice/PhpSpreadsheet/pull/2772) @@ -315,9 +467,9 @@ Note that this will be the last 1.x branch release before the 2.x release. We wi - Improved support for passing of array arguments to Excel function implementations to return array results (where appropriate). [Issue #2551](https://github.com/PHPOffice/PhpSpreadsheet/issues/2551) - This is the first stage in an ongoing process of adding array support to all appropriate function implementations, + This is the first stage in an ongoing process of adding array support to all appropriate function implementations, - Support for the Excel365 Math/Trig SEQUENCE() function [PR #2536](https://github.com/PHPOffice/PhpSpreadsheet/pull/2536) -- Support for the Excel365 Math/Trig RANDARRAY() function [PR #2540](https://github.com/PHPOffice/PhpSpreadsheet/pull/2540) +- Support for the Excel365 Math/Trig RANDARRAY() function [PR #2540](https://github.com/PHPOffice/PhpSpreadsheet/pull/2540) Note that the Spill Operator is not yet supported in the Calculation Engine; but this can still be useful for defining array constants. - Improved support for Conditional Formatting Rules [PR #2491](https://github.com/PHPOffice/PhpSpreadsheet/pull/2491) @@ -331,7 +483,7 @@ Note that this will be the last 1.x branch release before the 2.x release. We wi - Expression - Provision of CF Wizards (for all the above listed rule types) to help create/modify CF Rules without having to manage all the combinations of types/operators, and the complexities of formula expressions, or the text/timePeriod attributes. - See [documentation](https://phpspreadsheet.readthedocs.io/en/latest/topics/conditional-formatting/) for details + See [documentation](https://phpspreadsheet.readthedocs.io/en/latest/topics/conditional-formatting/) for details - Full support of the above CF Rules for the Xlsx Reader and Writer; even when the file being loaded has CF rules listed in the `` element for the worksheet rather than the `` element. - Provision of a CellMatcher to identify if rules are matched for a cell, and which matching style will be applied. @@ -521,7 +673,7 @@ Note that this will be the last 1.x branch release before the 2.x release. We wi - Xls Reader changing grey background to black in Excel template [Issue #2147](https://github.com/PHPOffice/PhpSpreadsheet/issues/2147) [PR #2156](https://github.com/PHPOffice/PhpSpreadsheet/pull/2156) - Column width and Row height styles in the Html Reader when the value includes a unit of measure [Issue #2145](https://github.com/PHPOffice/PhpSpreadsheet/issues/2145). - Data Validation flags not set correctly when reading XLSX files [Issue #2224](https://github.com/PHPOffice/PhpSpreadsheet/issues/2224) [PR #2225](https://github.com/PHPOffice/PhpSpreadsheet/pull/2225) -- Reading XLSX files without styles.xml throws an exception [Issue #2246](https://github.com/PHPOffice/PhpSpreadsheet/issues/2246) +- Reading XLSX files without styles.xml throws an exception [Issue #2246](https://github.com/PHPOffice/PhpSpreadsheet/issues/2246) - Improved performance of `Style::applyFromArray()` when applied to several cells [PR #1785](https://github.com/PHPOffice/PhpSpreadsheet/issues/1785). - Improve XLSX parsing speed if no readFilter is applied (again) - [#772](https://github.com/PHPOffice/PhpSpreadsheet/issues/772) @@ -586,7 +738,7 @@ Note that this will be the last 1.x branch release before the 2.x release. We wi `ABS()`, `ACOS()`, `ACOSH()`, `ASIN()`, `ASINH()`, `ATAN()`, `ATANH()`, `COS()`, `COSH()`, `DEGREES()` (rad2deg), `EXP()`, `LN()` (log), `LOG10()`, `RADIANS()` (deg2rad), `SIN()`, `SINH()`, `SQRT()`, `TAN()`, `TANH()`. - + One TextData function is also affected: `REPT()` (str_repeat). - `formatAsDate` correctly matches language metadata, reverting c55272e - Formulae that previously crashed on sub function call returning excel error value now return said value. @@ -1216,7 +1368,7 @@ Note that this will be the last 1.x branch release before the 2.x release. We wi - Ignore inlineStr type if formula element exists - @ncrypthic [#570](https://github.com/PHPOffice/PHPExcel/issues/570) - Excel 2007 Reader freezes because of conditional formatting - @rentalhost [#575](https://github.com/PHPOffice/PHPExcel/issues/575) - Readers will now parse files containing worksheet titles over 31 characters [#176](https://github.com/PHPOffice/PhpSpreadsheet/pull/176) -- Fixed PHP8 deprecation warning for libxml_disable_entity_loader() [#1625](https://github.com/phpoffice/phpspreadsheet/pull/1625) +- Fixed PHP8 deprecation warning for libxml_disable_entity_loader() [#1625](https://github.com/phpoffice/phpspreadsheet/pull/1625) ### General diff --git a/vendor/phpoffice/phpspreadsheet/CONTRIBUTING.md b/vendor/phpoffice/phpspreadsheet/CONTRIBUTING.md index f595353..09794b5 100644 --- a/vendor/phpoffice/phpspreadsheet/CONTRIBUTING.md +++ b/vendor/phpoffice/phpspreadsheet/CONTRIBUTING.md @@ -2,19 +2,44 @@ If you would like to contribute, here are some notes and guidelines: - - All new development happens on feature/fix branches, and are then merged to the `master` branch once stable; so the `master` branch is always the most up-to-date, working code - - Tagged releases are made from the `master` branch - - If you are going to be submitting a pull request, please fork from `master`, and submit your pull request back as a fix/feature branch referencing the GitHub issue number - - Code style might be automatically fixed by `composer fix` - - All code changes must be validated by `composer check` + - All new development should be on feature/fix branches, which are then merged to the `master` branch once stable and approved; so the `master` branch is always the most up-to-date, working code + - If you are going to submit a pull request, please fork from `master`, and submit your pull request back as a fix/feature branch referencing the GitHub issue number + - The code must work with all PHP versions that we support (currently PHP 7.4 to PHP 8.2). + - You can call `composer versions` to test version compatibility. + - Code style should be maintained. + - `composer style` will identify any issues with Coding Style`. + - `composer fix` will fix most issues with Coding Style. + - All code changes must be validated by `composer check`. + - Please include Unit Tests to verify that a bug exists, and that this PR fixes it. + - Please include Unit Tests to show that a new Feature works as expected. + - Please don't "bundle" several changes into a single PR; submit a PR for each discrete change/fix. + - Remember to update documentation if necessary. + - [Helpful article about forking](https://help.github.com/articles/fork-a-repo/ "Forking a GitHub repository") - [Helpful article about pull requests](https://help.github.com/articles/using-pull-requests/ "Pull Requests") +## Unit Tests + +When writing Unit Tests, please + - Always try to write Unit Tests for both the happy and unhappy paths. + - Put all assertions in the Test itself, not in an abstract class that the Test extends (even if this means code duplication between tests). + - Include any necessary `setup()` and `tearDown()` in the Test itself. + - If you change any global settings (such as system locale, or Compatibility Mode for Excel Function tests), make sure that you reset to the default in the `tearDown()`. + - Use the `ExcelError` functions in assertions for Excel Error values in Excel Function implementations. +
Not only does it reduce the risk of typos; but at some point in the future, ExcelError values will be an object rather than a string, and we won't then need to update all the tests. + - Don't over-complicate test code by testing happy and unhappy paths in the same test. + +This makes it easier to see exactly what is being tested when reviewing the PR. I want to be able to see it in the PR, not have to hunt in other unchanged classes to see what the test is doing. + ## How to release 1. Complete CHANGELOG.md and commit 2. Create an annotated tag 1. `git tag -a 1.2.3` 2. Tag subject must be the version number, eg: `1.2.3` - 3. Tag body must be a copy-paste of the changelog entries -3. Push tag with `git push --tags`, GitHub Actions will create a GitHub release automatically + 3. Tag body must be a copy-paste of the changelog entries. +3. Push the tag with `git push --tags`, GitHub Actions will create a GitHub release automatically, and the release details will automatically be sent to packagist. +4. Github seems to remove markdown headings in the Release Notes, so you should edit to restore these. + +> **Note:** Tagged releases are made from the `master` branch. Only in an emergency should a tagged release be made from the `release` branch. (i.e. cherry-picked hot-fixes.) + diff --git a/vendor/phpoffice/phpspreadsheet/README.md b/vendor/phpoffice/phpspreadsheet/README.md index 8ea5956..a69c3af 100644 --- a/vendor/phpoffice/phpspreadsheet/README.md +++ b/vendor/phpoffice/phpspreadsheet/README.md @@ -32,7 +32,7 @@ If you are building your installation on a development machine that is on a diff ```json { "require": { - "phpoffice/phpspreadsheet": "^1.23" + "phpoffice/phpspreadsheet": "^1.28" }, "config": { "platform": { @@ -74,16 +74,20 @@ or the appropriate PDF Writer wrapper for the library that you have chosen to in For Chart export, we support following packages, which you will also need to install yourself using `composer require` - [jpgraph/jpgraph](https://packagist.org/packages/jpgraph/jpgraph) (this package was abandoned at version 4.0. You can manually download the latest version that supports PHP 8 and above from [jpgraph.net](https://jpgraph.net/)) - - [mitoteam/jpgraph](https://packagist.org/packages/mitoteam/jpgraph) (fork with php 8.1 support) + - [mitoteam/jpgraph](https://packagist.org/packages/mitoteam/jpgraph) - up to date fork with modern PHP versions support and some bugs fixed. and then configure PhpSpreadsheet using: ```php -Settings::setChartRenderer(\PhpOffice\PhpSpreadsheet\Chart\Renderer\JpGraph::class); // to use jpgraph/jpgraph +// to use jpgraph/jpgraph +Settings::setChartRenderer(\PhpOffice\PhpSpreadsheet\Chart\Renderer\JpGraph::class); //or -Settings::setChartRenderer(\PhpOffice\PhpSpreadsheet\Chart\Renderer\MtJpGraphRenderer::class); // to use mitoteam/jpgraph +// to use mitoteam/jpgraph +Settings::setChartRenderer(\PhpOffice\PhpSpreadsheet\Chart\Renderer\MtJpGraphRenderer::class); ``` -One or the other of these libraries is necessary if you want to generate HTML or PDF files that include charts. +One or the other of these libraries is necessary if you want to generate HTML or PDF files that include charts; or to render a Chart to an Image format from within your code. +They are not necessary to define charts for writing to `Xlsx` files. +Other file formats don't support writing Charts. ## Documentation @@ -91,6 +95,42 @@ Read more about it, including install instructions, in the [official documentati Please ask your support questions on [StackOverflow](https://stackoverflow.com/questions/tagged/phpspreadsheet), or have a quick chat on [Gitter](https://gitter.im/PHPOffice/PhpSpreadsheet). +## Patreon + +I am now running a [Patreon](https://www.patreon.com/MarkBaker) to support the work that I do on PhpSpreadsheet. + +Supporters will receive access to articles about working with PhpSpreadsheet, and how to use some of its more advanced features. + +Posts already available to Patreon supporters: + - The Dating Game + - A look at how MS Excel (and PhpSpreadsheet) handle date and time values. +- Looping the Loop + - Advice on Iterating through the rows and cells in a worksheet. + +And for Patrons at levels actively using PhpSpreadsheet: + - Behind the Mask + - A look at Number Format Masks. + +The Next Article (currently Work in Progress): + - Formula for Success + - How to debug formulae that don't produce the expected result. + + +My aim is to post at least one article each month, taking a detailed look at some feature of MS Excel and how to use that feature in PhpSpreadsheet, or on how to perform different activities in PhpSpreadsheet. + +Planned posts for the future include topics like: + - Tables + - Structured References + - AutoFiltering + - Array Formulae + - Conditional Formatting + - Data Validation + - Value Binders + - Images + - Charts + +After a period of six months exclusive to Patreon supporters, articles will be incorporated into the public documentation for the library. + ## PHPExcel vs PhpSpreadsheet ? PhpSpreadsheet is the next version of PHPExcel. It breaks compatibility to dramatically improve the code base quality (namespaces, PSR compliance, use of latest PHP language features, etc.). diff --git a/vendor/phpoffice/phpspreadsheet/composer.json b/vendor/phpoffice/phpspreadsheet/composer.json index a130e12..4b05be3 100644 --- a/vendor/phpoffice/phpspreadsheet/composer.json +++ b/vendor/phpoffice/phpspreadsheet/composer.json @@ -42,13 +42,19 @@ ], "scripts": { "check": [ + "phpcs src/ tests/ --report=checkstyle", + "phpcs --report-width=200 samples/ src/ tests/ --ignore=samples/Header.php --standard=PHPCompatibility --runtime-set testVersion 7.4- -n", "php-cs-fixer fix --ansi --dry-run --diff", - "phpcs", "phpunit --color=always", - "phpstan analyse --ansi" + "phpstan analyse --ansi --memory-limit=2048M" + ], + "style": [ + "phpcs src/ tests/ --report=checkstyle", + "php-cs-fixer fix --ansi --dry-run --diff" ], "fix": [ - "php-cs-fixer fix --ansi" + "phpcbf src/ tests/ --report=checkstyle", + "php-cs-fixer fix" ], "versions": [ "phpcs --report-width=200 samples/ src/ tests/ --ignore=samples/Header.php --standard=PHPCompatibility --runtime-set testVersion 7.4- -n" @@ -70,7 +76,7 @@ "ext-zip": "*", "ext-zlib": "*", "ezyang/htmlpurifier": "^4.15", - "maennchen/zipstream-php": "^2.1", + "maennchen/zipstream-php": "^2.1 || ^3.0", "markbaker/complex": "^3.0", "markbaker/matrix": "^3.0", "psr/http-client": "^1.0", @@ -78,15 +84,15 @@ "psr/simple-cache": "^1.0 || ^2.0 || ^3.0" }, "require-dev": { - "dealerdirect/phpcodesniffer-composer-installer": "dev-master", + "dealerdirect/phpcodesniffer-composer-installer": "dev-main", "dompdf/dompdf": "^1.0 || ^2.0", "friendsofphp/php-cs-fixer": "^3.2", - "mitoteam/jpgraph": "^10.2.4", + "mitoteam/jpgraph": "^10.3", "mpdf/mpdf": "^8.1.1", "phpcompatibility/php-compatibility": "^9.3", "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^8.5 || ^9.0", + "phpunit/phpunit": "^8.5 || ^9.0 || ^10.0", "squizlabs/php_codesniffer": "^3.7", "tecnickcom/tcpdf": "^6.5" }, diff --git a/vendor/phpoffice/phpspreadsheet/phpstan-baseline.neon b/vendor/phpoffice/phpspreadsheet/phpstan-baseline.neon index 1e34628..eff0391 100644 --- a/vendor/phpoffice/phpspreadsheet/phpstan-baseline.neon +++ b/vendor/phpoffice/phpspreadsheet/phpstan-baseline.neon @@ -1,195 +1,5 @@ parameters: ignoreErrors: - - - message: "#^Variable \\$dateValue on left side of \\?\\? always exists and is not nullable\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/DateTimeExcel/DateValue.php - - - - message: "#^Variable \\$timeValue on left side of \\?\\? always exists and is not nullable\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/DateTimeExcel/TimeValue.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Engineering\\\\BesselJ\\:\\:besselj2a\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Engineering/BesselJ.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Engineering\\\\BesselJ\\:\\:besselj2b\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Engineering/BesselJ.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Engineering\\\\ConvertBase\\:\\:validatePlaces\\(\\) has parameter \\$places with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Engineering/ConvertBase.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Engineering\\\\ConvertBase\\:\\:validateValue\\(\\) has parameter \\$value with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Engineering/ConvertBase.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Engineering\\\\ConvertUOM\\:\\:getUOMDetails\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Engineering/ConvertUOM.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Engineering\\\\ConvertUOM\\:\\:resolveTemperatureSynonyms\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Engineering/ConvertUOM.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Engineering\\\\Erf\\:\\:erfValue\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Engineering/Erf.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Engineering\\\\Erf\\:\\:erfValue\\(\\) has parameter \\$value with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Engineering/Erf.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Engineering\\\\Erf\\:\\:\\$twoSqrtPi has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Engineering/Erf.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Engineering\\\\ErfC\\:\\:erfcValue\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Engineering/ErfC.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Engineering\\\\ErfC\\:\\:erfcValue\\(\\) has parameter \\$value with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Engineering/ErfC.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Engineering\\\\ErfC\\:\\:\\$oneSqrtPi has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Engineering/ErfC.php - - - - message: "#^Parameter \\#1 \\$year of static method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\DateTimeExcel\\\\Helpers\\:\\:isLeapYear\\(\\) expects int\\|string, array\\|int\\|string given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Financial/Amortization.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Financial\\\\CashFlow\\\\Constant\\\\Periodic\\\\Interest\\:\\:rateNextGuess\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic/Interest.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Financial\\\\CashFlow\\\\Constant\\\\Periodic\\\\Interest\\:\\:rateNextGuess\\(\\) has parameter \\$futureValue with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic/Interest.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Financial\\\\CashFlow\\\\Constant\\\\Periodic\\\\Interest\\:\\:rateNextGuess\\(\\) has parameter \\$numberOfPeriods with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic/Interest.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Financial\\\\CashFlow\\\\Constant\\\\Periodic\\\\Interest\\:\\:rateNextGuess\\(\\) has parameter \\$payment with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic/Interest.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Financial\\\\CashFlow\\\\Constant\\\\Periodic\\\\Interest\\:\\:rateNextGuess\\(\\) has parameter \\$presentValue with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic/Interest.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Financial\\\\CashFlow\\\\Constant\\\\Periodic\\\\Interest\\:\\:rateNextGuess\\(\\) has parameter \\$rate with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic/Interest.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Financial\\\\CashFlow\\\\Constant\\\\Periodic\\\\Interest\\:\\:rateNextGuess\\(\\) has parameter \\$type with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic/Interest.php - - - - message: "#^Binary operation \"\\-\" between float\\|string and 0\\|float results in an error\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic/InterestAndPrincipal.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Financial\\\\CashFlow\\\\Constant\\\\Periodic\\\\InterestAndPrincipal\\:\\:\\$interest has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic/InterestAndPrincipal.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Financial\\\\CashFlow\\\\Constant\\\\Periodic\\\\InterestAndPrincipal\\:\\:\\$principal has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic/InterestAndPrincipal.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Financial\\\\CashFlow\\\\Variable\\\\NonPeriodic\\:\\:xnpvOrdered\\(\\) should return float\\|string but returns array\\|string\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Financial/CashFlow/Variable/NonPeriodic.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Financial\\\\CashFlow\\\\Variable\\\\Periodic\\:\\:presentValue\\(\\) has parameter \\$args with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Financial/CashFlow/Variable/Periodic.php - - - - message: "#^Parameter \\#1 \\$year of static method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Financial\\\\Helpers\\:\\:daysPerYear\\(\\) expects int\\|string, array\\|int\\|string given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Financial/Coupons.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Financial\\\\Depreciation\\:\\:validateCost\\(\\) has parameter \\$cost with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Financial/Depreciation.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Financial\\\\Depreciation\\:\\:validateFactor\\(\\) has parameter \\$factor with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Financial/Depreciation.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Financial\\\\Depreciation\\:\\:validateLife\\(\\) has parameter \\$life with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Financial/Depreciation.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Financial\\\\Depreciation\\:\\:validateMonth\\(\\) has parameter \\$month with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Financial/Depreciation.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Financial\\\\Depreciation\\:\\:validatePeriod\\(\\) has parameter \\$period with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Financial/Depreciation.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Financial\\\\Depreciation\\:\\:validateSalvage\\(\\) has parameter \\$salvage with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Financial/Depreciation.php - - - - message: "#^Binary operation \"/\" between float\\|string and float\\|string results in an error\\.$#" - count: 2 - path: src/PhpSpreadsheet/Calculation/Financial/Securities/Price.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Financial\\\\Securities\\\\Price\\:\\:received\\(\\) should return float\\|string but returns array\\|string\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Financial/Securities/Price.php - - - - message: "#^Parameter \\#1 \\$year of static method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Financial\\\\Helpers\\:\\:daysPerYear\\(\\) expects int\\|string, array\\|int\\|string given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Financial/Securities/Price.php - - - - message: "#^Parameter \\#1 \\$year of static method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Financial\\\\Helpers\\:\\:daysPerYear\\(\\) expects int\\|string, array\\|int\\|string given\\.$#" - count: 2 - path: src/PhpSpreadsheet/Calculation/Financial/Securities/Yields.php - - message: "#^Cannot call method getTokenSubType\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\FormulaToken\\|null\\.$#" count: 4 @@ -214,1918 +24,3 @@ parameters: message: "#^Strict comparison using \\=\\=\\= between PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\FormulaToken and null will always evaluate to false\\.$#" count: 1 path: src/PhpSpreadsheet/Calculation/FormulaParser.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Functions\\:\\:ifCondition\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Functions.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Functions\\:\\:ifCondition\\(\\) has parameter \\$condition with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Functions.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Functions\\:\\:isCellValue\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Functions.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Functions\\:\\:isCellValue\\(\\) has parameter \\$idx with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Functions.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Functions\\:\\:isMatrixValue\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Functions.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Functions\\:\\:isMatrixValue\\(\\) has parameter \\$idx with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Functions.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Functions\\:\\:isValue\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Functions.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Functions\\:\\:isValue\\(\\) has parameter \\$idx with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Functions.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Functions\\:\\:operandSpecialHandling\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Functions.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Functions\\:\\:operandSpecialHandling\\(\\) has parameter \\$operand with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Functions.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Internal\\\\MakeMatrix\\:\\:make\\(\\) has parameter \\$args with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Internal/MakeMatrix.php - - - - message: "#^Call to function is_string\\(\\) with null will always evaluate to false\\.$#" - count: 3 - path: src/PhpSpreadsheet/Calculation/Logical/Operations.php - - - - message: "#^Result of && is always false\\.$#" - count: 3 - path: src/PhpSpreadsheet/Calculation/Logical/Operations.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\LookupRef\\:\\:CHOOSE\\(\\) has parameter \\$chooseArgs with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/LookupRef.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\LookupRef\\:\\:OFFSET\\(\\) should return array\\|string but returns array\\|int\\|string\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/LookupRef.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\LookupRef\\\\Address\\:\\:sheetName\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/LookupRef/Address.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\LookupRef\\\\Lookup\\:\\:verifyResultVector\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/LookupRef/Lookup.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\LookupRef\\\\Lookup\\:\\:verifyResultVector\\(\\) has parameter \\$resultVector with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/LookupRef/Lookup.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\LookupRef\\\\LookupBase\\:\\:validateIndexLookup\\(\\) has parameter \\$index_number with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/LookupRef/LookupBase.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\LookupRef\\\\Matrix\\:\\:extractRowValue\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\LookupRef\\\\Offset\\:\\:adjustEndCellColumnForWidth\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/LookupRef/Offset.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\LookupRef\\\\Offset\\:\\:adjustEndCellColumnForWidth\\(\\) has parameter \\$columns with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/LookupRef/Offset.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\LookupRef\\\\Offset\\:\\:adjustEndCellColumnForWidth\\(\\) has parameter \\$width with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/LookupRef/Offset.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\LookupRef\\\\Offset\\:\\:adustEndCellRowForHeight\\(\\) has parameter \\$endCellRow with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/LookupRef/Offset.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\LookupRef\\\\Offset\\:\\:adustEndCellRowForHeight\\(\\) has parameter \\$height with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/LookupRef/Offset.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\LookupRef\\\\Offset\\:\\:adustEndCellRowForHeight\\(\\) has parameter \\$rows with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/LookupRef/Offset.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\LookupRef\\\\Offset\\:\\:extractRequiredCells\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/LookupRef/Offset.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\LookupRef\\\\Offset\\:\\:extractWorksheet\\(\\) has parameter \\$cellAddress with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/LookupRef/Offset.php - - - - message: "#^Binary operation \"/\" between array\\|float\\|int\\|string and array\\|float\\|int\\|string results in an error\\.$#" - count: 2 - path: src/PhpSpreadsheet/Calculation/MathTrig/Combinations.php - - - - message: "#^Binary operation \"/\" between array\\|float\\|int\\|string and float\\|int results in an error\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/MathTrig/Factorial.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\MathTrig\\\\IntClass\\:\\:evaluate\\(\\) should return array\\|string but returns int\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/MathTrig/IntClass.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\:\\:MAXIFS\\(\\) should return float but returns float\\|string\\|null\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\:\\:MINIFS\\(\\) should return float but returns float\\|string\\|null\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Averages\\:\\:filterArguments\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Averages.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Averages\\:\\:filterArguments\\(\\) has parameter \\$args with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Averages.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Averages\\:\\:modeCalc\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Averages.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Averages\\:\\:modeCalc\\(\\) has parameter \\$data with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Averages.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Conditional\\:\\:SUMIF\\(\\) should return float\\|string but returns float\\|string\\|null\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Conditional.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Conditional\\:\\:buildConditionSet\\(\\) has parameter \\$args with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Conditional.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Conditional\\:\\:buildConditionSetForValueRange\\(\\) has parameter \\$args with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Conditional.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Conditional\\:\\:buildConditions\\(\\) has parameter \\$args with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Conditional.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Conditional\\:\\:buildDataSet\\(\\) has parameter \\$args with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Conditional.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Conditional\\:\\:buildDatabase\\(\\) has parameter \\$args with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Conditional.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Conditional\\:\\:buildDatabaseWithValueRange\\(\\) has parameter \\$args with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Conditional.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Distributions\\\\Beta\\:\\:\\$logBetaCacheP has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Distributions/Beta.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Distributions\\\\Beta\\:\\:\\$logBetaCacheQ has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Distributions/Beta.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Distributions\\\\Beta\\:\\:\\$logBetaCacheResult has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Distributions/Beta.php - - - - message: "#^Constant PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Distributions\\\\ChiSquared\\:\\:MAX_ITERATIONS is unused\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Distributions/ChiSquared.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Distributions\\\\ChiSquared\\:\\:gammp\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Distributions/ChiSquared.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Distributions\\\\ChiSquared\\:\\:gammp\\(\\) has parameter \\$n with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Distributions/ChiSquared.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Distributions\\\\ChiSquared\\:\\:gammp\\(\\) has parameter \\$x with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Distributions/ChiSquared.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Distributions\\\\ChiSquared\\:\\:gcf\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Distributions/ChiSquared.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Distributions\\\\ChiSquared\\:\\:gcf\\(\\) has parameter \\$n with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Distributions/ChiSquared.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Distributions\\\\ChiSquared\\:\\:gcf\\(\\) has parameter \\$x with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Distributions/ChiSquared.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Distributions\\\\ChiSquared\\:\\:gser\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Distributions/ChiSquared.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Distributions\\\\ChiSquared\\:\\:gser\\(\\) has parameter \\$n with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Distributions/ChiSquared.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Distributions\\\\ChiSquared\\:\\:gser\\(\\) has parameter \\$x with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Distributions/ChiSquared.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Distributions\\\\ChiSquared\\:\\:pchisq\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Distributions/ChiSquared.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Distributions\\\\ChiSquared\\:\\:pchisq\\(\\) has parameter \\$chi2 with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Distributions/ChiSquared.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Distributions\\\\ChiSquared\\:\\:pchisq\\(\\) has parameter \\$degrees with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Distributions/ChiSquared.php - - - - message: "#^Parameter \\#2 \\$columns of static method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Distributions\\\\ChiSquared\\:\\:degrees\\(\\) expects int, float\\|int\\<0, max\\> given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Distributions/ChiSquared.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Distributions\\\\GammaBase\\:\\:calculateDistribution\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Distributions/GammaBase.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Distributions\\\\GammaBase\\:\\:calculateInverse\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Distributions/GammaBase.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Distributions\\\\GammaBase\\:\\:logGamma1\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Distributions/GammaBase.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Distributions\\\\GammaBase\\:\\:logGamma2\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Distributions/GammaBase.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Distributions\\\\GammaBase\\:\\:logGamma3\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Distributions/GammaBase.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Distributions\\\\GammaBase\\:\\:logGamma4\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Distributions/GammaBase.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Distributions\\\\GammaBase\\:\\:\\$logGammaCacheResult has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Distributions/GammaBase.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Distributions\\\\GammaBase\\:\\:\\$logGammaCacheX has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Distributions/GammaBase.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Distributions\\\\NewtonRaphson\\:\\:execute\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Distributions/NewtonRaphson.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Distributions\\\\NewtonRaphson\\:\\:\\$callback has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Distributions/NewtonRaphson.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Distributions\\\\Normal\\:\\:inverseNcdf\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Distributions/Normal.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Distributions\\\\Normal\\:\\:inverseNcdf\\(\\) has parameter \\$p with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Distributions/Normal.php - - - - message: "#^Binary operation \"\\-\" between float\\|string and float\\|int\\|numeric\\-string results in an error\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Distributions/StandardNormal.php - - - - message: "#^Constant PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Distributions\\\\StudentT\\:\\:MAX_ITERATIONS is unused\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Distributions/StudentT.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\MaxMinBase\\:\\:datatypeAdjustmentAllowStrings\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/MaxMinBase.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\MaxMinBase\\:\\:datatypeAdjustmentAllowStrings\\(\\) has parameter \\$value with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/MaxMinBase.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Percentiles\\:\\:percentileFilterValues\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Percentiles.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Percentiles\\:\\:rankFilterValues\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Percentiles.php - - - - message: "#^Binary operation \"/\" between array\\|float\\|int\\|string and array\\|float\\|int\\|string results in an error\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Permutations.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Trends\\:\\:GROWTH\\(\\) should return array\\ but returns array\\\\>\\>\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Trends.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Trends\\:\\:TREND\\(\\) should return array\\ but returns array\\\\>\\>\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Trends.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Trends\\:\\:checkTrendArrays\\(\\) has parameter \\$array1 with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Trends.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\Trends\\:\\:checkTrendArrays\\(\\) has parameter \\$array2 with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/Trends.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\VarianceBase\\:\\:datatypeAdjustmentAllowStrings\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/VarianceBase.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\VarianceBase\\:\\:datatypeAdjustmentAllowStrings\\(\\) has parameter \\$value with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/VarianceBase.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\VarianceBase\\:\\:datatypeAdjustmentBooleans\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/VarianceBase.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\\\VarianceBase\\:\\:datatypeAdjustmentBooleans\\(\\) has parameter \\$value with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Statistical/VarianceBase.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\TextData\\:\\:CONCATENATE\\(\\) has parameter \\$args with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/TextData.php - - - - message: "#^Variable \\$value on left side of \\?\\? always exists and is not nullable\\.$#" - count: 4 - path: src/PhpSpreadsheet/Calculation/TextData/Extract.php - - - - message: "#^Variable \\$value on left side of \\?\\? always exists and is not nullable\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/TextData/Text.php - - - - message: "#^Call to an undefined method object\\:\\:getHashCode\\(\\)\\.$#" - count: 1 - path: src/PhpSpreadsheet/Cell/Coordinate.php - - - - message: "#^Parameter \\#4 \\$currentRow of static method PhpOffice\\\\PhpSpreadsheet\\\\Cell\\\\Coordinate\\:\\:validateRange\\(\\) expects int, string given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Cell/Coordinate.php - - - - message: "#^Parameter \\#5 \\$endRow of static method PhpOffice\\\\PhpSpreadsheet\\\\Cell\\\\Coordinate\\:\\:validateRange\\(\\) expects int, string given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Cell/Coordinate.php - - - - message: "#^Parameter \\#1 \\$namedRange of method PhpOffice\\\\PhpSpreadsheet\\\\Spreadsheet\\:\\:addNamedRange\\(\\) expects PhpOffice\\\\PhpSpreadsheet\\\\NamedRange, \\$this\\(PhpOffice\\\\PhpSpreadsheet\\\\DefinedName\\) given\\.$#" - count: 1 - path: src/PhpSpreadsheet/DefinedName.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\DefinedName\\:\\:\\$scope \\(PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\) does not accept PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\|null\\.$#" - count: 3 - path: src/PhpSpreadsheet/DefinedName.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\DefinedName\\:\\:\\$worksheet \\(PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\) does not accept PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\|null\\.$#" - count: 2 - path: src/PhpSpreadsheet/DefinedName.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\IOFactory\\:\\:createReader\\(\\) should return PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\IReader but returns object\\.$#" - count: 1 - path: src/PhpSpreadsheet/IOFactory.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\IOFactory\\:\\:createWriter\\(\\) should return PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\IWriter but returns object\\.$#" - count: 1 - path: src/PhpSpreadsheet/IOFactory.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\IOFactory\\:\\:\\$readers has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/IOFactory.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\IOFactory\\:\\:\\$writers has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/IOFactory.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\BaseReader\\:\\:getSecurityScanner\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/BaseReader.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\BaseReader\\:\\:\\$fileHandle has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/BaseReader.php - - - - message: "#^Offset 'percentage' does not exist on SimpleXMLElement\\|null\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Gnumeric/PageSetup.php - - - - message: "#^Offset 'value' does not exist on SimpleXMLElement\\|null\\.$#" - count: 2 - path: src/PhpSpreadsheet/Reader/Gnumeric/PageSetup.php - - - - message: "#^Variable \\$orientation on left side of \\?\\? always exists and is not nullable\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Gnumeric/PageSetup.php - - - - message: "#^Variable \\$value on left side of \\?\\? always exists and is not nullable\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Html.php - - - - message: "#^Cannot call method children\\(\\) on SimpleXMLElement\\|false\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Ods.php - - - - message: "#^Cannot call method getAttributeNS\\(\\) on DOMElement\\|null\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Ods.php - - - - message: "#^Cannot call method getElementsByTagNameNS\\(\\) on DOMElement\\|null\\.$#" - count: 2 - path: src/PhpSpreadsheet/Reader/Ods.php - - - - message: "#^Cannot call method getNamedItem\\(\\) on DOMNamedNodeMap\\|null\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Ods.php - - - - message: "#^Cannot call method getNamespaces\\(\\) on SimpleXMLElement\\|false\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Ods.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Ods\\:\\:listWorksheetNames\\(\\) should return array\\ but returns array\\\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Ods.php - - - - message: "#^Parameter \\#1 \\$element of method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Ods\\:\\:scanElementForText\\(\\) expects DOMNode, DOMElement\\|null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Ods.php - - - - message: "#^Parameter \\#1 \\$settings of method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Ods\\:\\:lookForActiveSheet\\(\\) expects DOMElement, DOMElement\\|null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Ods.php - - - - message: "#^Parameter \\#1 \\$settings of method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Ods\\:\\:lookForSelectedCells\\(\\) expects DOMElement, DOMElement\\|null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Ods.php - - - - message: "#^Cannot call method getElementsByTagNameNS\\(\\) on DOMElement\\|null\\.$#" - count: 3 - path: src/PhpSpreadsheet/Reader/Ods/PageSettings.php - - - - message: "#^Expression on left side of \\?\\? is not nullable\\.$#" - count: 6 - path: src/PhpSpreadsheet/Reader/Ods/PageSettings.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Ods\\\\PageSettings\\:\\:\\$pageLayoutStyles has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Ods/PageSettings.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Ods\\\\Properties\\:\\:load\\(\\) has parameter \\$namespacesMeta with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Ods/Properties.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Ods\\\\Properties\\:\\:setMetaProperties\\(\\) has parameter \\$namespacesMeta with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Ods/Properties.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Ods\\\\Properties\\:\\:setMetaProperties\\(\\) has parameter \\$propertyName with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Ods/Properties.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Ods\\\\Properties\\:\\:setUserDefinedProperty\\(\\) has parameter \\$propertyValue with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Ods/Properties.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Ods\\\\Properties\\:\\:setUserDefinedProperty\\(\\) has parameter \\$propertyValueAttributes with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Ods/Properties.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Ods\\\\Properties\\:\\:\\$spreadsheet has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Ods/Properties.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Security\\\\XmlScanner\\:\\:__construct\\(\\) has parameter \\$pattern with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Security/XmlScanner.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Security\\\\XmlScanner\\:\\:getInstance\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Security/XmlScanner.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Security\\\\XmlScanner\\:\\:threadSafeLibxmlDisableEntityLoaderAvailability\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Security/XmlScanner.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Security\\\\XmlScanner\\:\\:\\$callback has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Security/XmlScanner.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Security\\\\XmlScanner\\:\\:\\$libxmlDisableEntityLoaderValue has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Security/XmlScanner.php - - - - message: "#^Call to an undefined method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Escher\\|PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Escher\\\\DgContainer\\|PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Escher\\\\DgContainer\\\\SpgrContainer\\|PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Escher\\\\DgContainer\\\\SpgrContainer\\\\SpContainer\\|PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Escher\\\\DggContainer\\|PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Escher\\\\DggContainer\\\\BstoreContainer\\|PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Escher\\\\DggContainer\\\\BstoreContainer\\\\BSE\\:\\:getDgContainer\\(\\)\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xls.php - - - - message: "#^Call to an undefined method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Escher\\|PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Escher\\\\DgContainer\\|PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Escher\\\\DgContainer\\\\SpgrContainer\\|PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Escher\\\\DgContainer\\\\SpgrContainer\\\\SpContainer\\|PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Escher\\\\DggContainer\\|PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Escher\\\\DggContainer\\\\BstoreContainer\\|PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Escher\\\\DggContainer\\\\BstoreContainer\\\\BSE\\:\\:getDggContainer\\(\\)\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xls.php - - - - message: "#^Call to an undefined method object\\:\\:getEndCoordinates\\(\\)\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xls.php - - - - message: "#^Call to an undefined method object\\:\\:getEndOffsetX\\(\\)\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xls.php - - - - message: "#^Call to an undefined method object\\:\\:getEndOffsetY\\(\\)\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xls.php - - - - message: "#^Call to an undefined method object\\:\\:getNestingLevel\\(\\)\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xls.php - - - - message: "#^Call to an undefined method object\\:\\:getOPT\\(\\)\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xls.php - - - - message: "#^Call to an undefined method object\\:\\:getStartCoordinates\\(\\)\\.$#" - count: 2 - path: src/PhpSpreadsheet/Reader/Xls.php - - - - message: "#^Call to an undefined method object\\:\\:getStartOffsetX\\(\\)\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xls.php - - - - message: "#^Call to an undefined method object\\:\\:getStartOffsetY\\(\\)\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xls.php - - - - message: "#^Cannot access offset 1 on array\\|false\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xls.php - - - - message: "#^If condition is always true\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xls.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xls\\:\\:includeCellRangeFiltered\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xls.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xls\\:\\:includeCellRangeFiltered\\(\\) has parameter \\$cellRangeAddress with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xls.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xls\\:\\:parseRichText\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xls.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xls\\:\\:parseRichText\\(\\) has parameter \\$is with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xls.php - - - - message: "#^Negated boolean expression is always false\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xls.php - - - - message: "#^Parameter \\#1 \\$block of method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xls\\:\\:makeKey\\(\\) expects int, float given\\.$#" - count: 2 - path: src/PhpSpreadsheet/Reader/Xls.php - - - - message: "#^Parameter \\#1 \\$showSummaryBelow of method PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\:\\:setShowSummaryBelow\\(\\) expects bool, int given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xls.php - - - - message: "#^Parameter \\#1 \\$showSummaryRight of method PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\:\\:setShowSummaryRight\\(\\) expects bool, int given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xls.php - - - - message: "#^Parameter \\#2 \\$row of method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\IReadFilter\\:\\:readCell\\(\\) expects int, string given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xls.php - - - - message: "#^Parameter \\#2 \\$row of static method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Xls\\:\\:sizeRow\\(\\) expects int, string given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xls.php - - - - message: "#^Parameter \\#2 \\$startRow of static method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Xls\\:\\:getDistanceY\\(\\) expects int, string given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xls.php - - - - message: "#^Parameter \\#3 \\$subject of function str_replace expects array\\|string, int\\|string\\|null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xls.php - - - - message: "#^Parameter \\#4 \\$endRow of static method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Xls\\:\\:getDistanceY\\(\\) expects int, string given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xls.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xls\\:\\:\\$data \\(string\\) does not accept string\\|null\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xls.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xls\\:\\:\\$documentSummaryInformation \\(string\\) does not accept string\\|null\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xls.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xls\\:\\:\\$documentSummaryInformation \\(string\\) in isset\\(\\) is not nullable\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xls.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xls\\:\\:\\$md5Ctxt is never written, only read\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xls.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xls\\:\\:\\$summaryInformation \\(string\\) does not accept string\\|null\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xls.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xls\\:\\:\\$summaryInformation \\(string\\) in isset\\(\\) is not nullable\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xls.php - - - - message: "#^Unreachable statement \\- code above always terminates\\.$#" - count: 7 - path: src/PhpSpreadsheet/Reader/Xls.php - - - - message: "#^Parameter \\#1 \\$haystack of function strpos expects string, string\\|false given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xml.php - - - - message: "#^Parameter \\#1 \\$textValue of static method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\StringHelper\\:\\:convertEncoding\\(\\) expects string, string\\|false given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xml.php - - - - message: "#^Parameter \\#2 \\$subject of function preg_match expects string, string\\|false given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xml.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xml\\:\\:\\$fileContents has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xml.php - - - - message: "#^Argument of an invalid type SimpleXMLElement\\|null supplied for foreach, only iterables are supported\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xml/Properties.php - - - - message: "#^Argument of an invalid type SimpleXMLElement\\|null supplied for foreach, only iterables are supported\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xml/Style.php - - - - message: "#^Elseif condition is always true\\.$#" - count: 1 - path: src/PhpSpreadsheet/ReferenceHelper.php - - - - message: "#^Expression on left side of \\?\\? is not nullable\\.$#" - count: 1 - path: src/PhpSpreadsheet/ReferenceHelper.php - - - - 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: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Escher\\\\DgContainer\\:\\:getDgId\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Escher/DgContainer.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Escher\\\\DgContainer\\:\\:getLastSpId\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Escher/DgContainer.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Escher\\\\DgContainer\\:\\:getSpgrContainer\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Escher/DgContainer.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Escher\\\\DgContainer\\:\\:setDgId\\(\\) has parameter \\$value with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Escher/DgContainer.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Escher\\\\DgContainer\\:\\:setLastSpId\\(\\) has parameter \\$value with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Escher/DgContainer.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Escher\\\\DgContainer\\:\\:setSpgrContainer\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Escher/DgContainer.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Escher\\\\DgContainer\\:\\:setSpgrContainer\\(\\) has parameter \\$spgrContainer with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Escher/DgContainer.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Escher\\\\DgContainer\\:\\:\\$spgrContainer has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Escher/DgContainer.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Escher\\\\DgContainer\\\\SpgrContainer\\:\\:getChildren\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Escher/DgContainer/SpgrContainer.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Escher\\\\DggContainer\\\\BstoreContainer\\\\BSE\\:\\:\\$parent is never read, only written\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Escher/DggContainer/BstoreContainer/BSE.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\JAMA\\\\Matrix\\:\\:__construct\\(\\) has parameter \\$args with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/JAMA/Matrix.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\JAMA\\\\Matrix\\:\\:arrayLeftDivide\\(\\) has parameter \\$args with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/JAMA/Matrix.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\JAMA\\\\Matrix\\:\\:arrayLeftDivideEquals\\(\\) has parameter \\$args with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/JAMA/Matrix.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\JAMA\\\\Matrix\\:\\:arrayRightDivide\\(\\) has parameter \\$args with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/JAMA/Matrix.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\JAMA\\\\Matrix\\:\\:arrayRightDivideEquals\\(\\) has parameter \\$args with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/JAMA/Matrix.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\JAMA\\\\Matrix\\:\\:arrayTimes\\(\\) has parameter \\$args with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/JAMA/Matrix.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\JAMA\\\\Matrix\\:\\:arrayTimesEquals\\(\\) has parameter \\$args with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/JAMA/Matrix.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\JAMA\\\\Matrix\\:\\:concat\\(\\) has parameter \\$args with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/JAMA/Matrix.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\JAMA\\\\Matrix\\:\\:getMatrix\\(\\) has parameter \\$args with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/JAMA/Matrix.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\JAMA\\\\Matrix\\:\\:minus\\(\\) has parameter \\$args with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/JAMA/Matrix.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\JAMA\\\\Matrix\\:\\:minusEquals\\(\\) has parameter \\$args with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/JAMA/Matrix.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\JAMA\\\\Matrix\\:\\:plus\\(\\) has parameter \\$args with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/JAMA/Matrix.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\JAMA\\\\Matrix\\:\\:plusEquals\\(\\) has parameter \\$args with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/JAMA/Matrix.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\JAMA\\\\Matrix\\:\\:power\\(\\) has parameter \\$args with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/JAMA/Matrix.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\JAMA\\\\Matrix\\:\\:times\\(\\) has parameter \\$args with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/JAMA/Matrix.php - - - - message: "#^Parameter \\#3 \\$c of method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\JAMA\\\\Matrix\\:\\:set\\(\\) expects float\\|int\\|null, string given\\.$#" - count: 2 - path: src/PhpSpreadsheet/Shared/JAMA/Matrix.php - - - - message: "#^Unreachable statement \\- code above always terminates\\.$#" - count: 14 - path: src/PhpSpreadsheet/Shared/JAMA/Matrix.php - - - - message: "#^Cannot access offset 1 on array\\|false\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/OLE.php - - - - message: "#^Cannot access offset 2 on array\\|false\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/OLE.php - - - - message: "#^Cannot access offset 3 on array\\|false\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/OLE.php - - - - message: "#^Cannot access offset 4 on array\\|false\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/OLE.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\:\\:getData\\(\\) should return string but returns string\\|false\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/OLE.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\:\\:getStream\\(\\) should return resource but returns resource\\|false\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/OLE.php - - - - message: "#^Parameter \\#1 \\$No of class PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\\\PPS constructor expects int, null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/OLE.php - - - - message: "#^Parameter \\#1 \\$oleTimestamp of static method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\:\\:OLE2LocalDate\\(\\) expects string, string\\|false given\\.$#" - count: 2 - path: src/PhpSpreadsheet/Shared/OLE.php - - - - message: "#^Parameter \\#1 \\$string of function substr expects string, string\\|false given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/OLE.php - - - - message: "#^Parameter \\#2 \\$name of class PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\\\PPS constructor expects string, null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/OLE.php - - - - message: "#^Parameter \\#3 \\$type of class PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\\\PPS constructor expects int, null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/OLE.php - - - - message: "#^Parameter \\#4 \\$prev of class PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\\\PPS constructor expects int, null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/OLE.php - - - - message: "#^Parameter \\#5 \\$next of class PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\\\PPS constructor expects int, null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/OLE.php - - - - message: "#^Parameter \\#6 \\$dir of class PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\\\PPS constructor expects int, null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/OLE.php - - - - message: "#^Parameter \\#9 \\$data of class PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\\\PPS constructor expects string, null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/OLE.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\:\\:\\$root \\(PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\\\PPS\\\\Root\\) in isset\\(\\) is not nullable\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/OLE.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\\\PPS\\:\\:\\$_data \\(string\\) in isset\\(\\) is not nullable\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/OLE/PPS.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\\\PPS\\:\\:\\$startBlock \\(int\\) on left side of \\?\\? is not nullable\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/OLE/PPS.php - - - - message: "#^Parameter \\#1 \\$No of method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\\\PPS\\:\\:__construct\\(\\) expects int, null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/OLE/PPS/File.php - - - - message: "#^Parameter \\#4 \\$prev of method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\\\PPS\\:\\:__construct\\(\\) expects int, null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/OLE/PPS/File.php - - - - message: "#^Parameter \\#5 \\$next of method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\\\PPS\\:\\:__construct\\(\\) expects int, null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/OLE/PPS/File.php - - - - message: "#^Parameter \\#6 \\$dir of method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\\\PPS\\:\\:__construct\\(\\) expects int, null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/OLE/PPS/File.php - - - - message: "#^Parameter \\#1 \\$No of method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\\\PPS\\:\\:__construct\\(\\) expects int, null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/OLE/PPS/Root.php - - - - message: "#^Parameter \\#4 \\$prev of method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\\\PPS\\:\\:__construct\\(\\) expects int, null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/OLE/PPS/Root.php - - - - message: "#^Parameter \\#5 \\$next of method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\\\PPS\\:\\:__construct\\(\\) expects int, null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/OLE/PPS/Root.php - - - - message: "#^Parameter \\#6 \\$dir of method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\\\PPS\\:\\:__construct\\(\\) expects int, null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/OLE/PPS/Root.php - - - - message: "#^Parameter \\#9 \\$data of method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\\\PPS\\:\\:__construct\\(\\) expects string, null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/OLE/PPS/Root.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\\\PPS\\\\Root\\:\\:\\$bigBlockSize \\(int\\) in isset\\(\\) is not nullable\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/OLE/PPS/Root.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\\\PPS\\\\Root\\:\\:\\$smallBlockSize \\(int\\) in isset\\(\\) is not nullable\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/OLE/PPS/Root.php - - - - message: "#^Parameter \\#1 \\$data of static method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLERead\\:\\:getInt4d\\(\\) expects string, string\\|false given\\.$#" - count: 8 - path: src/PhpSpreadsheet/Shared/OLERead.php - - - - message: "#^Parameter \\#1 \\$string of function substr expects string, string\\|false given\\.$#" - count: 2 - path: src/PhpSpreadsheet/Shared/OLERead.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLERead\\:\\:\\$data has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/OLERead.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLERead\\:\\:\\$documentSummaryInformation has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/OLERead.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLERead\\:\\:\\$summaryInformation has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/OLERead.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLERead\\:\\:\\$wrkbook has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/OLERead.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Trend\\\\BestFit\\:\\:calculateGoodnessOfFit\\(\\) has parameter \\$const with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Trend/BestFit.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Trend\\\\BestFit\\:\\:calculateGoodnessOfFit\\(\\) has parameter \\$meanX with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Trend/BestFit.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Trend\\\\BestFit\\:\\:calculateGoodnessOfFit\\(\\) has parameter \\$meanY with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Trend/BestFit.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Trend\\\\BestFit\\:\\:calculateGoodnessOfFit\\(\\) has parameter \\$sumX with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Trend/BestFit.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Trend\\\\BestFit\\:\\:calculateGoodnessOfFit\\(\\) has parameter \\$sumX2 with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Trend/BestFit.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Trend\\\\BestFit\\:\\:calculateGoodnessOfFit\\(\\) has parameter \\$sumXY with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Trend/BestFit.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Trend\\\\BestFit\\:\\:calculateGoodnessOfFit\\(\\) has parameter \\$sumY with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Trend/BestFit.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Trend\\\\BestFit\\:\\:calculateGoodnessOfFit\\(\\) has parameter \\$sumY2 with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Trend/BestFit.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Trend\\\\BestFit\\:\\:getBestFitType\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Trend/BestFit.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Trend\\\\BestFit\\:\\:getError\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Trend/BestFit.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Trend\\\\BestFit\\:\\:sumSquares\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Trend/BestFit.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Trend\\\\BestFit\\:\\:\\$DFResiduals has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Trend/BestFit.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Trend\\\\BestFit\\:\\:\\$SSRegression has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Trend/BestFit.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Trend\\\\BestFit\\:\\:\\$SSResiduals has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Trend/BestFit.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Trend\\\\BestFit\\:\\:\\$correlation has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Trend/BestFit.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Trend\\\\BestFit\\:\\:\\$covariance has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Trend/BestFit.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Trend\\\\BestFit\\:\\:\\$f has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Trend/BestFit.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Trend\\\\BestFit\\:\\:\\$goodnessOfFit has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Trend/BestFit.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Trend\\\\BestFit\\:\\:\\$intersect has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Trend/BestFit.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Trend\\\\BestFit\\:\\:\\$intersectSE has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Trend/BestFit.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Trend\\\\BestFit\\:\\:\\$slope has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Trend/BestFit.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Trend\\\\BestFit\\:\\:\\$slopeSE has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Trend/BestFit.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Trend\\\\BestFit\\:\\:\\$stdevOfResiduals has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Trend/BestFit.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Trend\\\\BestFit\\:\\:\\$xOffset has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Trend/BestFit.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Trend\\\\BestFit\\:\\:\\$yOffset has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Trend/BestFit.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Trend\\\\PolynomialBestFit\\:\\:getCoefficients\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Trend/PolynomialBestFit.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Trend\\\\PolynomialBestFit\\:\\:getCoefficients\\(\\) has parameter \\$dp with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Trend/PolynomialBestFit.php - - - - message: "#^Call to an undefined method object\\:\\:getGoodnessOfFit\\(\\)\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Trend/Trend.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Trend\\\\Trend\\:\\:calculate\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Trend/Trend.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Trend\\\\Trend\\:\\:calculate\\(\\) has parameter \\$const with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Trend/Trend.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Trend\\\\Trend\\:\\:calculate\\(\\) has parameter \\$trendType with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Trend/Trend.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Trend\\\\Trend\\:\\:calculate\\(\\) has parameter \\$xValues with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Shared/Trend/Trend.php - - - - 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: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\ConditionalFormatting\\\\ConditionalDataBar\\:\\:setConditionalFormattingRuleExt\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalDataBar.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\ConditionalFormatting\\\\ConditionalDataBar\\:\\:setMaximumConditionalFormatValueObject\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalDataBar.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\ConditionalFormatting\\\\ConditionalDataBar\\:\\:setMinimumConditionalFormatValueObject\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalDataBar.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\ConditionalFormatting\\\\ConditionalDataBar\\:\\:setShowValue\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalDataBar.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\ConditionalFormatting\\\\ConditionalDataBarExtension\\:\\:getXmlAttributes\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalDataBarExtension.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\ConditionalFormatting\\\\ConditionalDataBarExtension\\:\\:getXmlElements\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalDataBarExtension.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\ConditionalFormatting\\\\ConditionalDataBarExtension\\:\\:setMaximumConditionalFormatValueObject\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalDataBarExtension.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\ConditionalFormatting\\\\ConditionalDataBarExtension\\:\\:setMinimumConditionalFormatValueObject\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalDataBarExtension.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\ConditionalFormatting\\\\ConditionalFormatValueObject\\:\\:__construct\\(\\) has parameter \\$type with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormatValueObject.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\ConditionalFormatting\\\\ConditionalFormatValueObject\\:\\:__construct\\(\\) has parameter \\$value with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormatValueObject.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\ConditionalFormatting\\\\ConditionalFormatValueObject\\:\\:setCellFormula\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormatValueObject.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\ConditionalFormatting\\\\ConditionalFormatValueObject\\:\\:setType\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormatValueObject.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\ConditionalFormatting\\\\ConditionalFormatValueObject\\:\\:setValue\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormatValueObject.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\ConditionalFormatting\\\\ConditionalFormatValueObject\\:\\:\\$cellFormula has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormatValueObject.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\ConditionalFormatting\\\\ConditionalFormatValueObject\\:\\:\\$type has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormatValueObject.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\ConditionalFormatting\\\\ConditionalFormatValueObject\\:\\:\\$value has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormatValueObject.php - - - - message: "#^Cannot access property \\$axisPosition on SimpleXMLElement\\|null\\.$#" - count: 2 - path: src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormattingRuleExtension.php - - - - message: "#^Cannot access property \\$border on SimpleXMLElement\\|null\\.$#" - count: 2 - path: src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormattingRuleExtension.php - - - - message: "#^Cannot access property \\$direction on SimpleXMLElement\\|null\\.$#" - count: 2 - path: src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormattingRuleExtension.php - - - - message: "#^Cannot access property \\$gradient on SimpleXMLElement\\|null\\.$#" - count: 2 - path: src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormattingRuleExtension.php - - - - message: "#^Cannot access property \\$maxLength on SimpleXMLElement\\|null\\.$#" - count: 2 - path: src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormattingRuleExtension.php - - - - message: "#^Cannot access property \\$minLength on SimpleXMLElement\\|null\\.$#" - count: 2 - path: src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormattingRuleExtension.php - - - - message: "#^Cannot access property \\$negativeBarBorderColorSameAsPositive on SimpleXMLElement\\|null\\.$#" - count: 2 - path: src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormattingRuleExtension.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\ConditionalFormatting\\\\ConditionalFormattingRuleExtension\\:\\:__construct\\(\\) has parameter \\$id with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormattingRuleExtension.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\ConditionalFormatting\\\\ConditionalFormattingRuleExtension\\:\\:generateUuid\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormattingRuleExtension.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\ConditionalFormatting\\\\ConditionalFormattingRuleExtension\\:\\:parseExtDataBarElementChildrenFromXml\\(\\) has parameter \\$ns with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormattingRuleExtension.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\ConditionalFormatting\\\\ConditionalFormattingRuleExtension\\:\\:parseExtLstXml\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormattingRuleExtension.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\ConditionalFormatting\\\\ConditionalFormattingRuleExtension\\:\\:parseExtLstXml\\(\\) has parameter \\$extLstXml with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormattingRuleExtension.php - - - - message: "#^Offset 'rgb' does not exist on SimpleXMLElement\\|null\\.$#" - count: 4 - path: src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormattingRuleExtension.php - - - - message: "#^Offset 'theme' does not exist on SimpleXMLElement\\|null\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormattingRuleExtension.php - - - - message: "#^Offset 'tint' does not exist on SimpleXMLElement\\|null\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormattingRuleExtension.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\ConditionalFormatting\\\\ConditionalFormattingRuleExtension\\:\\:\\$id has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormattingRuleExtension.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\NumberFormat\\\\Formatter\\:\\:splitFormat\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/NumberFormat/Formatter.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\NumberFormat\\\\Formatter\\:\\:splitFormat\\(\\) has parameter \\$sections with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/NumberFormat/Formatter.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\NumberFormat\\\\Formatter\\:\\:splitFormat\\(\\) has parameter \\$value with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/NumberFormat/Formatter.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\NumberFormat\\\\Formatter\\:\\:splitFormatCompare\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/NumberFormat/Formatter.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\NumberFormat\\\\Formatter\\:\\:splitFormatCompare\\(\\) has parameter \\$cond with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/NumberFormat/Formatter.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\NumberFormat\\\\Formatter\\:\\:splitFormatCompare\\(\\) has parameter \\$dfcond with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/NumberFormat/Formatter.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\NumberFormat\\\\Formatter\\:\\:splitFormatCompare\\(\\) has parameter \\$dfval with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/NumberFormat/Formatter.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\NumberFormat\\\\Formatter\\:\\:splitFormatCompare\\(\\) has parameter \\$val with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/NumberFormat/Formatter.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\NumberFormat\\\\Formatter\\:\\:splitFormatCompare\\(\\) has parameter \\$value with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/NumberFormat/Formatter.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\NumberFormat\\\\Formatter\\:\\:toFormattedString\\(\\) should return string but returns float\\|int\\|string\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/NumberFormat/Formatter.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\NumberFormat\\\\PercentageFormatter\\:\\:format\\(\\) has parameter \\$value with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Style/NumberFormat/PercentageFormatter.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\CellIterator\\:\\:adjustForExistingOnlyRange\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Worksheet/CellIterator.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Drawing\\\\Shadow\\:\\:\\$color \\(PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Color\\) does not accept PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Color\\|null\\.$#" - count: 1 - path: src/PhpSpreadsheet/Worksheet/Drawing/Shadow.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\PageSetup\\:\\:getPrintArea\\(\\) should return string but returns string\\|null\\.$#" - count: 1 - path: src/PhpSpreadsheet/Worksheet/PageSetup.php - - - - message: "#^Cannot call method getCalculatedValue\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Cell\\\\Cell\\|null\\.$#" - count: 1 - path: src/PhpSpreadsheet/Worksheet/Worksheet.php - - - - message: "#^Cannot call method getHashCode\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\|null\\.$#" - count: 1 - path: src/PhpSpreadsheet/Worksheet/Worksheet.php - - - - message: "#^Cannot call method getValue\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Cell\\\\Cell\\|null\\.$#" - count: 4 - path: src/PhpSpreadsheet/Worksheet/Worksheet.php - - - - message: "#^Cannot call method getWorksheet\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\DefinedName\\|null\\.$#" - count: 1 - path: src/PhpSpreadsheet/Worksheet/Worksheet.php - - - - message: "#^Cannot call method getXfIndex\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Cell\\\\Cell\\|null\\.$#" - count: 1 - path: src/PhpSpreadsheet/Worksheet/Worksheet.php - - - - message: "#^Cannot call method rangeToArray\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\|null\\.$#" - count: 1 - path: src/PhpSpreadsheet/Worksheet/Worksheet.php - - - - message: "#^If condition is always true\\.$#" - count: 2 - path: src/PhpSpreadsheet/Worksheet/Worksheet.php - - - - message: "#^Left side of && is always true\\.$#" - count: 2 - path: src/PhpSpreadsheet/Worksheet/Worksheet.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\:\\:getChartByName\\(\\) should return PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Chart\\|false but returns PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Chart\\|null\\.$#" - count: 1 - path: src/PhpSpreadsheet/Worksheet/Worksheet.php - - - - message: "#^Parameter \\#1 \\$index of class PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\ColumnDimension constructor expects string, null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Worksheet/Worksheet.php - - - - message: "#^Parameter \\#1 \\$index of class PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\RowDimension constructor expects int, null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Worksheet/Worksheet.php - - - - message: "#^Parameter \\#1 \\$range of static method PhpOffice\\\\PhpSpreadsheet\\\\Cell\\\\Coordinate\\:\\:rangeDimension\\(\\) expects string, string\\|false given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Worksheet/Worksheet.php - - - - message: "#^Parameter \\#2 \\$format of static method PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\NumberFormat\\:\\:toFormattedString\\(\\) expects string, string\\|null given\\.$#" - count: 2 - path: src/PhpSpreadsheet/Worksheet/Worksheet.php - - - - message: "#^Parameter \\#3 \\$rotation of static method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Font\\:\\:calculateColumnWidth\\(\\) expects int, int\\|null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Worksheet/Worksheet.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\:\\:\\$parent \\(PhpOffice\\\\PhpSpreadsheet\\\\Spreadsheet\\) does not accept PhpOffice\\\\PhpSpreadsheet\\\\Spreadsheet\\|null\\.$#" - count: 1 - path: src/PhpSpreadsheet/Worksheet/Worksheet.php - - - - message: "#^Right side of && is always true\\.$#" - count: 1 - path: src/PhpSpreadsheet/Worksheet/Worksheet.php - - - - message: "#^Negated boolean expression is always false\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Ods.php - - - - message: "#^If condition is always true\\.$#" - count: 2 - path: src/PhpSpreadsheet/Writer/Ods/Cell/Style.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Ods\\\\Cell\\\\Style\\:\\:\\$writer has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Ods/Cell/Style.php - - - - message: "#^Parameter \\#1 \\$range of static method PhpOffice\\\\PhpSpreadsheet\\\\Cell\\\\Coordinate\\:\\:splitRange\\(\\) expects string, string\\|false given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Ods/Content.php - - - - message: "#^Parameter \\#2 \\$value of method XMLWriter\\:\\:writeAttribute\\(\\) expects string, int\\<2, max\\> given\\.$#" - count: 3 - path: src/PhpSpreadsheet/Writer/Ods/Content.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Ods\\\\Content\\:\\:\\$formulaConvertor has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Ods/Content.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Ods\\\\Formula\\:\\:\\$definedNames has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Ods/Formula.php - - - - message: "#^Cannot call method getHashCode\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Font\\|null\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls.php - - - - message: "#^Cannot use array destructuring on array\\|false\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls.php - - - - message: "#^Offset 'endCoordinates' does not exist on array\\|null\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls.php - - - - message: "#^Offset 'endOffsetX' does not exist on array\\|null\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls.php - - - - message: "#^Offset 'endOffsetY' does not exist on array\\|null\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls.php - - - - message: "#^Offset 'startCoordinates' does not exist on array\\|null\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls.php - - - - message: "#^Offset 'startOffsetX' does not exist on array\\|null\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls.php - - - - message: "#^Offset 'startOffsetY' does not exist on array\\|null\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls.php - - - - message: "#^Parameter \\#1 \\$blipType of method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Escher\\\\DggContainer\\\\BstoreContainer\\\\BSE\\:\\:setBlipType\\(\\) expects int, int\\|null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls.php - - - - message: "#^Parameter \\#1 \\$data of method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Escher\\\\DggContainer\\\\BstoreContainer\\\\BSE\\\\Blip\\:\\:setData\\(\\) expects string, string\\|false given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls.php - - - - message: "#^Parameter \\#1 \\$font of method PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xls\\\\Workbook\\:\\:addFont\\(\\) expects PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Font, PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Font\\|null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xls\\:\\:\\$documentSummaryInformation \\(string\\) in isset\\(\\) is not nullable\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xls\\:\\:\\$summaryInformation \\(string\\) in isset\\(\\) is not nullable\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xls\\\\BIFFwriter\\:\\:writeEof\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls/BIFFwriter.php - - - - message: "#^Static property PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xls\\\\BIFFwriter\\:\\:\\$byteOrder \\(int\\) in isset\\(\\) is not nullable\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls/BIFFwriter.php - - - - message: "#^Elseif condition is always true\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls/Escher.php - - - - message: "#^If condition is always true\\.$#" - count: 3 - path: src/PhpSpreadsheet/Writer/Xls/Escher.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xls\\\\Escher\\:\\:\\$data has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls/Escher.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xls\\\\Escher\\:\\:\\$object has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls/Escher.php - - - - message: "#^Cannot access offset 'encoding' on array\\|false\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls/Workbook.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xls\\\\Workbook\\:\\:writeAllDefinedNamesBiff8\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls/Workbook.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xls\\\\Workbook\\:\\:writeExternalsheetBiff8\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls/Workbook.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xls\\\\Workbook\\:\\:writeMsoDrawingGroup\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls/Workbook.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xls\\\\Workbook\\:\\:writeSupbookInternal\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls/Workbook.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xls\\\\Workbook\\:\\:\\$biffSize is never read, only written\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls/Workbook.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xls\\\\Workbook\\:\\:\\$colors has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls/Workbook.php - - - - message: "#^Cannot access offset 'comp' on array\\|false\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls/Worksheet.php - - - - message: "#^Cannot access offset 'ident' on array\\|false\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls/Worksheet.php - - - - message: "#^Cannot access offset 'sa' on array\\|false\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls/Worksheet.php - - - - message: "#^Cannot access offset 1 on array\\|false\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls/Worksheet.php - - - - message: "#^Cannot access offset 2 on array\\|false\\.$#" - count: 2 - path: src/PhpSpreadsheet/Writer/Xls/Worksheet.php - - - - message: "#^Cannot call method getHashCode\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Font\\|null\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls/Worksheet.php - - - - message: "#^Expression on left side of \\?\\? is not nullable\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls/Worksheet.php - - - - message: "#^Parameter \\#1 \\$string of function strlen expects string, string\\|false given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls/Worksheet.php - - - - message: "#^Parameter \\#1 \\$string of function substr expects string, string\\|false given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls/Worksheet.php - - - - message: "#^Parameter \\#2 \\$length of function fread expects int\\<0, max\\>, int\\<0, max\\>\\|false given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls/Worksheet.php - - - - message: "#^Parameter \\#4 \\$isError of method PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xls\\\\Worksheet\\:\\:writeBoolErr\\(\\) expects bool, int given\\.$#" - count: 3 - path: src/PhpSpreadsheet/Writer/Xls/Worksheet.php - - - - message: "#^Parameter \\#5 \\$width of method PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xls\\\\Worksheet\\:\\:positionImage\\(\\) expects int, float given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls/Worksheet.php - - - - message: "#^Parameter \\#6 \\$height of method PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xls\\\\Worksheet\\:\\:positionImage\\(\\) expects int, float given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls/Worksheet.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xls\\\\Worksheet\\:\\:\\$activePane \\(int\\) does not accept int\\|null\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls/Worksheet.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xls\\\\Worksheet\\:\\:\\$colors has no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls/Worksheet.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xls\\\\Worksheet\\:\\:\\$countCellStyleXfs is never read, only written\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls/Worksheet.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xls\\\\Worksheet\\:\\:\\$outlineBelow is never read, only written\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls/Worksheet.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xls\\\\Worksheet\\:\\:\\$outlineRight is never read, only written\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls/Worksheet.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xls\\\\Worksheet\\:\\:\\$selection is never read, only written\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls/Worksheet.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xls\\\\Worksheet\\:\\:\\$xlsStringMaxLength is never read, only written\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls/Worksheet.php - - - - message: "#^Parameter \\#1 \\$textRotation of static method PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xls\\\\Xf\\:\\:mapTextRotation\\(\\) expects int, int\\|null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls/Xf.php - - - - message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xls\\\\Xf\\:\\:\\$diag is never read, only written\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xls/Xf.php diff --git a/vendor/phpoffice/phpspreadsheet/phpstan-conditional.php b/vendor/phpoffice/phpspreadsheet/phpstan-conditional.php index eeb21d1..9b1150b 100644 --- a/vendor/phpoffice/phpspreadsheet/phpstan-conditional.php +++ b/vendor/phpoffice/phpspreadsheet/phpstan-conditional.php @@ -74,17 +74,12 @@ 'path' => __DIR__ . '/src/PhpSpreadsheet/Calculation/TextData/Text.php', 'count' => 1, ]; - $config['parameters']['ignoreErrors'][] = [ - 'message' => '#^Property PhpOffice\\PhpSpreadsheet\\Shared\\JAMA\\Matrix::$A (array) does not accept array|false>|false.$#', - 'path' => __DIR__ . '/src/PhpSpreadsheet/Shared/JAMA/Matrix.php', - 'count' => 2, - ]; } else { // Flagged in Php8+ - unsure how to correct code $config['parameters']['ignoreErrors'][] = [ 'message' => '#^Binary operation "/" between float and array[|]float[|]int[|]string results in an error.#', 'path' => __DIR__ . '/src/PhpSpreadsheet/Calculation/MathTrig/Combinations.php', - 'count' => 2, + 'count' => 1, ]; } diff --git a/vendor/phpoffice/phpspreadsheet/phpstan.neon.dist b/vendor/phpoffice/phpspreadsheet/phpstan.neon.dist index 30bd6c2..ef2ae14 100644 --- a/vendor/phpoffice/phpspreadsheet/phpstan.neon.dist +++ b/vendor/phpoffice/phpspreadsheet/phpstan.neon.dist @@ -12,6 +12,10 @@ parameters: excludePaths: - src/PhpSpreadsheet/Chart/Renderer/JpGraph.php - src/PhpSpreadsheet/Chart/Renderer/JpGraphRendererBase.php + - src/PhpSpreadsheet/Collection/Memory/SimpleCache1.php + - src/PhpSpreadsheet/Collection/Memory/SimpleCache3.php + - src/PhpSpreadsheet/Writer/ZipStream2.php + - src/PhpSpreadsheet/Writer/ZipStream3.php parallel: processTimeout: 300.0 checkMissingIterableValueType: false diff --git a/vendor/phpoffice/phpspreadsheet/phpunit10.xml.dist b/vendor/phpoffice/phpspreadsheet/phpunit10.xml.dist new file mode 100644 index 0000000..207d8ec --- /dev/null +++ b/vendor/phpoffice/phpspreadsheet/phpunit10.xml.dist @@ -0,0 +1,15 @@ + + + + + + + + ./tests/PhpSpreadsheetTests + + + + ./src + + + diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Calculation.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Calculation.php index 240e5a0..c88656b 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Calculation.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Calculation.php @@ -6,8 +6,6 @@ use PhpOffice\PhpSpreadsheet\Calculation\Engine\CyclicReferenceStack; use PhpOffice\PhpSpreadsheet\Calculation\Engine\Logger; use PhpOffice\PhpSpreadsheet\Calculation\Engine\Operands; -use PhpOffice\PhpSpreadsheet\Calculation\Information\ErrorValue; -use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError; use PhpOffice\PhpSpreadsheet\Calculation\Token\Stack; use PhpOffice\PhpSpreadsheet\Cell\AddressRange; use PhpOffice\PhpSpreadsheet\Cell\Cell; @@ -21,6 +19,7 @@ use ReflectionClassConstant; use ReflectionMethod; use ReflectionParameter; +use Throwable; class Calculation { @@ -3558,7 +3557,7 @@ public function calculateCellValue(?Cell $cell = null, $resetLog = true) } } - throw new Exception($e->getMessage()); + throw new Exception($e->getMessage(), $e->getCode(), $e); } if ((is_array($result)) && (self::$returnArrayAsType != self::RETURN_ARRAY_AS_ARRAY)) { @@ -3698,15 +3697,16 @@ public function saveValueToCache($cellReference, $cellValue): void * @param string $formula The formula to parse and calculate * @param string $cellID The ID (e.g. A3) of the cell that we are calculating * @param Cell $cell Cell to calculate + * @param bool $ignoreQuotePrefix If set to true, evaluate the formyla even if the referenced cell is quote prefixed * * @return mixed */ - public function _calculateFormulaValue($formula, $cellID = null, ?Cell $cell = null) + public function _calculateFormulaValue($formula, $cellID = null, ?Cell $cell = null, bool $ignoreQuotePrefix = false) { $cellValue = null; // Quote-Prefixed cell values cannot be formulae, but are treated as strings - if ($cell !== null && $cell->getStyle()->getQuotePrefix() === true) { + if ($cell !== null && $ignoreQuotePrefix === false && $cell->getStyle()->getQuotePrefix() === true) { return self::wrapResult((string) $formula); } @@ -4211,7 +4211,7 @@ private function internalParseFormula($formula, ?Cell $cell = null) try { $this->branchPruner->closingBrace($d['value']); } catch (Exception $e) { - return $this->raiseFormulaError($e->getMessage()); + return $this->raiseFormulaError($e->getMessage(), $e->getCode(), $e); } $functionName = $matches[1]; // Get the function name @@ -4250,7 +4250,7 @@ private function internalParseFormula($formula, ?Cell $cell = null) } elseif ($expectedArgumentCount != '*') { $isOperandOrFunction = preg_match('/(\d*)([-+,])(\d*)/', $expectedArgumentCount, $argMatch); self::doNothing($isOperandOrFunction); - switch ($argMatch[2]) { + switch ($argMatch[2] ?? '') { case '+': if ($argumentCount < $argMatch[1]) { $argumentCountError = true; @@ -4283,7 +4283,7 @@ private function internalParseFormula($formula, ?Cell $cell = null) try { $this->branchPruner->argumentSeparator(); } catch (Exception $e) { - return $this->raiseFormulaError($e->getMessage()); + return $this->raiseFormulaError($e->getMessage(), $e->getCode(), $e); } while (($o2 = $stack->pop()) && $o2['value'] !== '(') { // Pop off the stack back to the last ( @@ -4365,8 +4365,12 @@ private function internalParseFormula($formula, ?Cell $cell = null) $rangeStartCellRef = $output[count($output) - 2]['value'] ?? ''; } preg_match('/^' . self::CALCULATION_REGEXP_CELLREF . '$/miu', $rangeStartCellRef, $rangeStartMatches); - if ($rangeStartMatches[2] > '') { - $val = $rangeStartMatches[2] . '!' . $val; + if (array_key_exists(2, $rangeStartMatches)) { + if ($rangeStartMatches[2] > '') { + $val = $rangeStartMatches[2] . '!' . $val; + } + } else { + $val = Information\ExcelError::REF(); } } else { $rangeStartCellRef = $output[count($output) - 1]['value'] ?? ''; @@ -4392,7 +4396,7 @@ private function internalParseFormula($formula, ?Cell $cell = null) try { $structuredReference = Operands\StructuredReference::fromParser($formula, $index, $matches); } catch (Exception $e) { - return $this->raiseFormulaError($e->getMessage()); + return $this->raiseFormulaError($e->getMessage(), $e->getCode(), $e); } $val = $structuredReference->value(); @@ -4435,6 +4439,8 @@ private function internalParseFormula($formula, ?Cell $cell = null) } $val = $address; } + } elseif ($val === Information\ExcelError::REF()) { + $stackItemReference = $val; } else { $startRowColRef = $output[count($output) - 1]['value'] ?? ''; [$rangeWS1, $startRowColRef] = Worksheet::extractSheetTitle($startRowColRef, true); @@ -4452,7 +4458,7 @@ private function internalParseFormula($formula, ?Cell $cell = null) $refSheet = $pCellParent; if ($pCellParent !== null && $rangeSheetRef !== '' && $rangeSheetRef !== $pCellParent->getTitle()) { - $refSheet = $pCellParent->getParent()->getSheetByName($rangeSheetRef); + $refSheet = $pCellParent->getParentOrThrow()->getSheetByName($rangeSheetRef); } if (ctype_digit($val) && $val <= 1048576) { @@ -4632,14 +4638,6 @@ private static function dataTestReference(&$operandData) return $operand; } - private const NUMERIC_BINARY_OPERATIONS = [ - '+' => 'plusEquals', - '-' => 'minusEquals', - '*' => 'arrayTimesEquals', - '/' => 'arrayRightDivide', - '^' => 'power', - ]; - /** * @param mixed $tokens * @param null|string $cellID @@ -4679,7 +4677,7 @@ private function processTokenStack($tokens, $cellID = null, ?Cell $cell = null) if ( (isset($storeValue) || $tokenData['reference'] === 'NULL') - && (!$storeValueAsBool || ErrorValue::isError($storeValue) || ($storeValue === 'Pruned branch')) + && (!$storeValueAsBool || Information\ErrorValue::isError($storeValue) || ($storeValue === 'Pruned branch')) ) { // If branching value is not true, we don't need to compute if (!isset($fakedForBranchPruning['onlyIf-' . $onlyIfStoreKey])) { @@ -4711,7 +4709,7 @@ private function processTokenStack($tokens, $cellID = null, ?Cell $cell = null) if ( (isset($storeValue) || $tokenData['reference'] === 'NULL') - && ($storeValueAsBool || ErrorValue::isError($storeValue) || ($storeValue === 'Pruned branch')) + && ($storeValueAsBool || Information\ErrorValue::isError($storeValue) || ($storeValue === 'Pruned branch')) ) { // If branching value is true, we don't need to compute if (!isset($fakedForBranchPruning['onlyIfNot-' . $onlyIfNotStoreKey])) { @@ -4732,13 +4730,33 @@ private function processTokenStack($tokens, $cellID = null, ?Cell $cell = null) } if ($token instanceof Operands\StructuredReference) { - throw new Exception('Structured References are not currently supported'); - // The next step is converting any structured reference to a cell value of range - // to a new $token value, which can then be processed in the following code. - } + if ($cell === null) { + return $this->raiseFormulaError('Structured References must exist in a Cell context'); + } - // if the token is a binary operator, pop the top two values off the stack, do the operation, and push the result back on the stack - if (!is_numeric($token) && !is_object($token) && isset(self::BINARY_OPERATORS[$token])) { + try { + $cellRange = $token->parse($cell); + if (strpos($cellRange, ':') !== false) { + $this->debugLog->writeDebugLog('Evaluating Structured Reference %s as Cell Range %s', $token->value(), $cellRange); + $rangeValue = self::getInstance($cell->getWorksheet()->getParent())->_calculateFormulaValue("={$cellRange}", $cellRange, $cell); + $stack->push('Value', $rangeValue); + $this->debugLog->writeDebugLog('Evaluated Structured Reference %s as value %s', $token->value(), $this->showValue($rangeValue)); + } else { + $this->debugLog->writeDebugLog('Evaluating Structured Reference %s as Cell %s', $token->value(), $cellRange); + $cellValue = $cell->getWorksheet()->getCell($cellRange)->getCalculatedValue(false); + $stack->push('Cell Reference', $cellValue, $cellRange); + $this->debugLog->writeDebugLog('Evaluated Structured Reference %s as value %s', $token->value(), $this->showValue($cellValue)); + } + } catch (Exception $e) { + if ($e->getCode() === Exception::CALCULATION_ENGINE_PUSH_TO_STACK) { + $stack->push('Error', Information\ExcelError::REF(), null); + $this->debugLog->writeDebugLog('Evaluated Structured Reference %s as error value %s', $token->value(), Information\ExcelError::REF()); + } else { + return $this->raiseFormulaError($e->getMessage(), $e->getCode(), $e); + } + } + } elseif (!is_numeric($token) && !is_object($token) && isset(self::BINARY_OPERATORS[$token])) { + // if the token is a binary operator, pop the top two values off the stack, do the operation, and push the result back on the stack // We must have two operands, error if we don't if (($operand2Data = $stack->pop()) === null) { return $this->raiseFormulaError('Internal error - Operand value missing from stack'); @@ -4782,7 +4800,7 @@ private function processTokenStack($tokens, $cellID = null, ?Cell $cell = null) } } } - if (strpos($operand1Data['reference'], '!') !== false) { + if (strpos($operand1Data['reference'] ?? '', '!') !== false) { [$sheet1, $operand1Data['reference']] = Worksheet::extractSheetTitle($operand1Data['reference'], true); } else { $sheet1 = ($pCellWorksheet !== null) ? $pCellWorksheet->getTitle() : ''; @@ -4819,10 +4837,21 @@ private function processTokenStack($tokens, $cellID = null, ?Cell $cell = null) $oData = array_merge(explode(':', $operand1Data['reference']), explode(':', $operand2Data['reference'])); $oCol = $oRow = []; + $breakNeeded = false; foreach ($oData as $oDatum) { - $oCR = Coordinate::coordinateFromString($oDatum); - $oCol[] = Coordinate::columnIndexFromString($oCR[0]) - 1; - $oRow[] = $oCR[1]; + try { + $oCR = Coordinate::coordinateFromString($oDatum); + $oCol[] = Coordinate::columnIndexFromString($oCR[0]) - 1; + $oRow[] = $oCR[1]; + } catch (\Exception $e) { + $stack->push('Error', Information\ExcelError::REF(), null); + $breakNeeded = true; + + break; + } + } + if ($breakNeeded) { + break; } $cellRef = Coordinate::stringFromColumnIndex(min($oCol) + 1) . min($oRow) . ':' . Coordinate::stringFromColumnIndex(max($oCol) + 1) . max($oRow); if ($pCellParent !== null && $this->spreadsheet !== null) { @@ -4831,8 +4860,10 @@ private function processTokenStack($tokens, $cellID = null, ?Cell $cell = null) return $this->raiseFormulaError('Unable to access Cell Reference'); } + $this->debugLog->writeDebugLog('Evaluation Result is %s', $this->showTypeDetails($cellValue)); $stack->push('Cell Reference', $cellValue, $cellRef); } else { + $this->debugLog->writeDebugLog('Evaluation Result is a #REF! Error'); $stack->push('Error', Information\ExcelError::REF(), null); } @@ -4842,7 +4873,7 @@ private function processTokenStack($tokens, $cellID = null, ?Cell $cell = null) case '*': // Multiplication case '/': // Division case '^': // Exponential - $result = $this->executeNumericBinaryOperation($operand1, $operand2, $token, self::NUMERIC_BINARY_OPERATIONS[$token], $stack); + $result = $this->executeNumericBinaryOperation($operand1, $operand2, $token, $stack); if (isset($storeKey)) { $branchStore[$storeKey] = $result; } @@ -4852,29 +4883,30 @@ private function processTokenStack($tokens, $cellID = null, ?Cell $cell = null) // If either of the operands is a matrix, we need to treat them both as matrices // (converting the other operand to a matrix if need be); then perform the required // matrix operation - if (is_bool($operand1)) { - $operand1 = ($operand1) ? self::$localeBoolean['TRUE'] : self::$localeBoolean['FALSE']; - } - if (is_bool($operand2)) { - $operand2 = ($operand2) ? self::$localeBoolean['TRUE'] : self::$localeBoolean['FALSE']; - } - if ((is_array($operand1)) || (is_array($operand2))) { + $operand1 = self::boolToString($operand1); + $operand2 = self::boolToString($operand2); + if (is_array($operand1) || is_array($operand2)) { + if (is_string($operand1)) { + $operand1 = self::unwrapResult($operand1); + } + if (is_string($operand2)) { + $operand2 = self::unwrapResult($operand2); + } // Ensure that both operands are arrays/matrices - self::checkMatrixOperands($operand1, $operand2, 2); - - try { - // Convert operand 1 from a PHP array to a matrix - $matrix = new Shared\JAMA\Matrix($operand1); - // Perform the required operation against the operand 1 matrix, passing in operand 2 - $matrixResult = $matrix->concat($operand2); - $result = $matrixResult->getArray(); - if (isset($result[0][0])) { - $result[0][0] = Shared\StringHelper::substring($result[0][0], 0, DataType::MAX_STRING_LENGTH); + [$rows, $columns] = self::checkMatrixOperands($operand1, $operand2, 2); + + for ($row = 0; $row < $rows; ++$row) { + for ($column = 0; $column < $columns; ++$column) { + $operand1[$row][$column] = + Shared\StringHelper::substring( + self::boolToString($operand1[$row][$column]) + . self::boolToString($operand2[$row][$column]), + 0, + DataType::MAX_STRING_LENGTH + ); } - } catch (\Exception $ex) { - $this->debugLog->writeDebugLog('JAMA Matrix Exception: %s', $ex->getMessage()); - $result = '#VALUE!'; } + $result = $operand1; } else { // In theory, we should truncate here. // But I can't figure out a formula @@ -4927,23 +4959,26 @@ private function processTokenStack($tokens, $cellID = null, ?Cell $cell = null) $multiplier = 0.01; } if (is_array($arg)) { - self::checkMatrixOperands($arg, $multiplier, 2); - - try { - $matrix1 = new Shared\JAMA\Matrix($arg); - $matrixResult = $matrix1->arrayTimesEquals($multiplier); - $result = $matrixResult->getArray(); - } catch (\Exception $ex) { - $this->debugLog->writeDebugLog('JAMA Matrix Exception: %s', $ex->getMessage()); - $result = '#VALUE!'; + $operand2 = $multiplier; + $result = $arg; + [$rows, $columns] = self::checkMatrixOperands($result, $operand2, 0); + for ($row = 0; $row < $rows; ++$row) { + for ($column = 0; $column < $columns; ++$column) { + if (self::isNumericOrBool($result[$row][$column])) { + $result[$row][$column] *= $multiplier; + } else { + $result[$row][$column] = self::makeError($result[$row][$column]); + } + } } + $this->debugLog->writeDebugLog('Evaluation Result is %s', $this->showTypeDetails($result)); $stack->push('Value', $result); if (isset($storeKey)) { $branchStore[$storeKey] = $result; } } else { - $this->executeNumericBinaryOperation($multiplier, $arg, '*', 'arrayTimesEquals', $stack); + $this->executeNumericBinaryOperation($multiplier, $arg, '*', $stack); } } elseif (preg_match('/^' . self::CALCULATION_REGEXP_CELLREF . '$/i', $token ?? '', $matches)) { $cellRef = null; @@ -5283,12 +5318,11 @@ private function executeBinaryComparisonOperation($operand1, $operand2, $operati * @param mixed $operand1 * @param mixed $operand2 * @param string $operation - * @param string $matrixFunction * @param Stack $stack * * @return bool|mixed */ - private function executeNumericBinaryOperation($operand1, $operand2, $operation, $matrixFunction, &$stack) + private function executeNumericBinaryOperation($operand1, $operand2, $operation, &$stack) { // Validate the two operands if ( @@ -5298,70 +5332,113 @@ private function executeNumericBinaryOperation($operand1, $operand2, $operation, return false; } - // If either of the operands is a matrix, we need to treat them both as matrices - // (converting the other operand to a matrix if need be); then perform the required - // matrix operation - if ((is_array($operand1)) || (is_array($operand2))) { - // Ensure that both operands are arrays/matrices of the same size - self::checkMatrixOperands($operand1, $operand2, 2); - - try { - // Convert operand 1 from a PHP array to a matrix - $matrix = new Shared\JAMA\Matrix($operand1); - // Perform the required operation against the operand 1 matrix, passing in operand 2 - $matrixResult = $matrix->$matrixFunction($operand2); - $result = $matrixResult->getArray(); - } catch (\Exception $ex) { - $this->debugLog->writeDebugLog('JAMA Matrix Exception: %s', $ex->getMessage()); - $result = '#VALUE!'; + if ( + (Functions::getCompatibilityMode() != Functions::COMPATIBILITY_OPENOFFICE) && + ((is_string($operand1) && !is_numeric($operand1) && strlen($operand1) > 0) || + (is_string($operand2) && !is_numeric($operand2) && strlen($operand2) > 0)) + ) { + $result = Information\ExcelError::VALUE(); + } elseif (is_array($operand1) || is_array($operand2)) { + // Ensure that both operands are arrays/matrices + if (is_array($operand1)) { + foreach ($operand1 as $key => $value) { + $operand1[$key] = Functions::flattenArray($value); + } } - } else { - if ( - (Functions::getCompatibilityMode() != Functions::COMPATIBILITY_OPENOFFICE) && - ((is_string($operand1) && !is_numeric($operand1) && strlen($operand1) > 0) || - (is_string($operand2) && !is_numeric($operand2) && strlen($operand2) > 0)) - ) { - $result = Information\ExcelError::VALUE(); - } else { - // If we're dealing with non-matrix operations, execute the necessary operation - switch ($operation) { - // Addition - case '+': - $result = $operand1 + $operand2; + if (is_array($operand2)) { + foreach ($operand2 as $key => $value) { + $operand2[$key] = Functions::flattenArray($value); + } + } + [$rows, $columns] = self::checkMatrixOperands($operand1, $operand2, 2); - break; - // Subtraction - case '-': - $result = $operand1 - $operand2; + for ($row = 0; $row < $rows; ++$row) { + for ($column = 0; $column < $columns; ++$column) { + if ($operand1[$row][$column] === null) { + $operand1[$row][$column] = 0; + } elseif (!self::isNumericOrBool($operand1[$row][$column])) { + $operand1[$row][$column] = self::makeError($operand1[$row][$column]); - break; - // Multiplication - case '*': - $result = $operand1 * $operand2; + continue; + } + if ($operand2[$row][$column] === null) { + $operand2[$row][$column] = 0; + } elseif (!self::isNumericOrBool($operand2[$row][$column])) { + $operand1[$row][$column] = self::makeError($operand2[$row][$column]); - break; - // Division - case '/': - if ($operand2 == 0) { - // Trap for Divide by Zero error - $stack->push('Error', ExcelError::DIV0()); - $this->debugLog->writeDebugLog('Evaluation Result is %s', $this->showTypeDetails(ExcelError::DIV0())); - - return false; - } - $result = $operand1 / $operand2; + continue; + } + switch ($operation) { + case '+': + $operand1[$row][$column] += $operand2[$row][$column]; + + break; + case '-': + $operand1[$row][$column] -= $operand2[$row][$column]; + + break; + case '*': + $operand1[$row][$column] *= $operand2[$row][$column]; + + break; + case '/': + if ($operand2[$row][$column] == 0) { + $operand1[$row][$column] = Information\ExcelError::DIV0(); + } else { + $operand1[$row][$column] /= $operand2[$row][$column]; + } - break; - // Power - case '^': - $result = $operand1 ** $operand2; + break; + case '^': + $operand1[$row][$column] = $operand1[$row][$column] ** $operand2[$row][$column]; - break; + break; - default: - throw new Exception('Unsupported numeric binary operation'); + default: + throw new Exception('Unsupported numeric binary operation'); + } } } + $result = $operand1; + } else { + // If we're dealing with non-matrix operations, execute the necessary operation + switch ($operation) { + // Addition + case '+': + $result = $operand1 + $operand2; + + break; + // Subtraction + case '-': + $result = $operand1 - $operand2; + + break; + // Multiplication + case '*': + $result = $operand1 * $operand2; + + break; + // Division + case '/': + if ($operand2 == 0) { + // Trap for Divide by Zero error + $stack->push('Error', Information\ExcelError::DIV0()); + $this->debugLog->writeDebugLog('Evaluation Result is %s', $this->showTypeDetails(Information\ExcelError::DIV0())); + + return false; + } + $result = $operand1 / $operand2; + + break; + // Power + case '^': + $result = $operand1 ** $operand2; + + break; + + default: + throw new Exception('Unsupported numeric binary operation'); + } } // Log the result details @@ -5377,13 +5454,13 @@ private function executeNumericBinaryOperation($operand1, $operand2, $operation, * * @return false */ - protected function raiseFormulaError(string $errorMessage) + protected function raiseFormulaError(string $errorMessage, int $code = 0, ?Throwable $exception = null) { $this->formulaError = $errorMessage; $this->cyclicReferenceStack->clear(); $suppress = /** @scrutinizer ignore-deprecated */ $this->suppressFormulaErrors ?? $this->suppressFormulaErrorsNew; if (!$suppress) { - throw new Exception($errorMessage); + throw new Exception($errorMessage, $code, $exception); } return false; @@ -5623,25 +5700,6 @@ private function addCellReference(array $args, $passCellReference, $functionCall return $args; } - /** - * @param array $tokens - * - * @return string - */ - private function getTokensAsString($tokens) - { - $tokensStr = array_map(function ($token) { - $value = $token['value'] ?? 'no value'; - while (is_array($value)) { - $value = array_pop($value); - } - - return $value; - }, $tokens); - - return '[ ' . implode(' | ', $tokensStr) . ' ]'; - } - /** * @return mixed|string */ @@ -5683,7 +5741,7 @@ private function evaluateDefinedName(Cell $cell, DefinedName $namedRange, Worksh $recursiveCalculator = new self($this->spreadsheet); $recursiveCalculator->getDebugLog()->setWriteDebugLog($this->getDebugLog()->getWriteDebugLog()); $recursiveCalculator->getDebugLog()->setEchoDebugLog($this->getDebugLog()->getEchoDebugLog()); - $result = $recursiveCalculator->_calculateFormulaValue($definedNameValue, $recursiveCalculationCellAddress, $recursiveCalculationCell); + $result = $recursiveCalculator->_calculateFormulaValue($definedNameValue, $recursiveCalculationCellAddress, $recursiveCalculationCell, true); if ($this->getDebugLog()->getWriteDebugLog()) { $this->debugLog->mergeDebugLog(array_slice($recursiveCalculator->getDebugLog()->getLog(), 3)); @@ -5710,4 +5768,32 @@ private static function doNothing($arg): bool { return (bool) $arg; } + + /** + * @param mixed $operand1 + * + * @return mixed + */ + private static function boolToString($operand1) + { + if (is_bool($operand1)) { + $operand1 = ($operand1) ? self::$localeBoolean['TRUE'] : self::$localeBoolean['FALSE']; + } elseif ($operand1 === null) { + $operand1 = ''; + } + + return $operand1; + } + + /** @param mixed $operand */ + private static function isNumericOrBool($operand): bool + { + return is_numeric($operand) || is_bool($operand); + } + + /** @param mixed $operand */ + private static function makeError($operand = ''): string + { + return Information\ErrorValue::isError($operand) ? $operand : Information\ExcelError::VALUE(); + } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/DateValue.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/DateValue.php index 52543a7..1d59988 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/DateValue.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/DateValue.php @@ -24,7 +24,7 @@ class DateValue * Excel Function: * DATEVALUE(dateValue) * - * @param array|string $dateValue Text that represents a date in a Microsoft Excel date format. + * @param null|array|string $dateValue Text that represents a date in a Microsoft Excel date format. * For example, "1/30/2008" or "30-Jan-2008" are text strings within * quotation marks that represent dates. Using the default date * system in Excel for Windows, date_text must represent a date from @@ -45,6 +45,11 @@ public static function fromString($dateValue) return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $dateValue); } + // try to parse as date iff there is at least one digit + if (is_string($dateValue) && preg_match('/\\d/', $dateValue) !== 1) { + return ExcelError::VALUE(); + } + $dti = new DateTimeImmutable(); $baseYear = SharedDateHelper::getExcelCalendar(); $dateValue = trim($dateValue ?? '', '"'); diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/Month.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/Month.php index c72d006..5c42eac 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/Month.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/Month.php @@ -45,6 +45,7 @@ public static function adjust($dateValue, $adjustmentMonths) } catch (Exception $e) { return $e->getMessage(); } + $dateValue = floor($dateValue); $adjustmentMonths = floor($adjustmentMonths); // Execute function @@ -88,6 +89,7 @@ public static function lastDay($dateValue, $adjustmentMonths) } catch (Exception $e) { return $e->getMessage(); } + $dateValue = floor($dateValue); $adjustmentMonths = floor($adjustmentMonths); // Execute function diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/TimeValue.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/TimeValue.php index 4abdd75..78d67b8 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/TimeValue.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/TimeValue.php @@ -25,7 +25,7 @@ class TimeValue * Excel Function: * TIMEVALUE(timeValue) * - * @param array|string $timeValue A text string that represents a time in any one of the Microsoft + * @param null|array|string $timeValue A text string that represents a time in any one of the Microsoft * Excel time formats; for example, "6:45 PM" and "18:45" text strings * within quotation marks that represent time. * Date information in time_text is ignored. @@ -42,6 +42,11 @@ public static function fromString($timeValue) return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $timeValue); } + // try to parse as time iff there is at least one digit + if (is_string($timeValue) && preg_match('/\\d/', $timeValue) !== 1) { + return ExcelError::VALUE(); + } + $timeValue = trim($timeValue ?? '', '"'); $timeValue = str_replace(['/', '.'], '-', $timeValue); diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engine/FormattedNumber.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engine/FormattedNumber.php index 8fe7aa4..331fa44 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engine/FormattedNumber.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engine/FormattedNumber.php @@ -13,6 +13,9 @@ class FormattedNumber private const STRING_REGEXP_PERCENT = '~^(?:(?: *(?[-+])? *\% *(?[-+])? *(?[0-9]+\.?[0-9*]*(?:E[-+]?[0-9]*)?) *)|(?: *(?[-+])? *(?[0-9]+\.?[0-9]*(?:E[-+]?[0-9]*)?) *\% *))$~i'; + // preg_quoted string for major currency symbols, with a %s for locale currency + private const CURRENCY_CONVERSION_LIST = '\$€£¥%s'; + private const STRING_CONVERSION_LIST = [ [self::class, 'convertToNumberIfNumeric'], [self::class, 'convertToNumberIfFraction'], @@ -45,7 +48,10 @@ public static function convertToNumberIfFormatted(string &$operand): bool */ public static function convertToNumberIfNumeric(string &$operand): bool { - $value = preg_replace(['/(\d),(\d)/u', '/([+-])\s+(\d)/u'], ['$1$2', '$1$2'], trim($operand)); + $thousandsSeparator = preg_quote(StringHelper::getThousandsSeparator(), '/'); + $value = preg_replace(['/(\d)' . $thousandsSeparator . '(\d)/u', '/([+-])\s+(\d)/u'], ['$1$2', '$1$2'], trim($operand)); + $decimalSeparator = preg_quote(StringHelper::getDecimalSeparator(), '/'); + $value = preg_replace(['/(\d)' . $decimalSeparator . '(\d)/u', '/([+-])\s+(\d)/u'], ['$1.$2', '$1$2'], $value ?? ''); if (is_numeric($value)) { $operand = (float) $value; @@ -84,7 +90,10 @@ public static function convertToNumberIfFraction(string &$operand): bool */ public static function convertToNumberIfPercent(string &$operand): bool { - $value = preg_replace('/(\d),(\d)/u', '$1$2', $operand); + $thousandsSeparator = preg_quote(StringHelper::getThousandsSeparator(), '/'); + $value = preg_replace('/(\d)' . $thousandsSeparator . '(\d)/u', '$1$2', trim($operand)); + $decimalSeparator = preg_quote(StringHelper::getDecimalSeparator(), '/'); + $value = preg_replace(['/(\d)' . $decimalSeparator . '(\d)/u', '/([+-])\s+(\d)/u'], ['$1.$2', '$1$2'], $value ?? ''); $match = []; if ($value !== null && preg_match(self::STRING_REGEXP_PERCENT, $value, $match, PREG_UNMATCHED_AS_NULL)) { @@ -106,21 +115,33 @@ public static function convertToNumberIfPercent(string &$operand): bool */ public static function convertToNumberIfCurrency(string &$operand): bool { - $quotedCurrencyCode = preg_quote(StringHelper::getCurrencyCode()); - - $value = preg_replace('/(\d),(\d)/u', '$1$2', $operand); - $regExp = '~^(?:(?: *(?[-+])? *' . $quotedCurrencyCode . ' *(?[-+])? *(?[0-9]+\.?[0-9*]*(?:E[-+]?[0-9]*)?) *)|(?: *(?[-+])? *(?[0-9]+\.?[0-9]*(?:E[-+]?[0-9]*)?) *' . $quotedCurrencyCode . ' *))$~ui'; + $currencyRegexp = self::currencyMatcherRegexp(); + $thousandsSeparator = preg_quote(StringHelper::getThousandsSeparator(), '/'); + $value = preg_replace('/(\d)' . $thousandsSeparator . '(\d)/u', '$1$2', $operand); $match = []; - if ($value !== null && preg_match($regExp, $value, $match, PREG_UNMATCHED_AS_NULL)) { + if ($value !== null && preg_match($currencyRegexp, $value, $match, PREG_UNMATCHED_AS_NULL)) { //Determine the sign $sign = ($match['PrefixedSign'] ?? $match['PrefixedSign2'] ?? $match['PostfixedSign']) ?? ''; + $decimalSeparator = StringHelper::getDecimalSeparator(); //Cast to a float - $operand = (float) ($sign . ($match['PostfixedValue'] ?? $match['PrefixedValue'])); + $intermediate = (string) ($match['PostfixedValue'] ?? $match['PrefixedValue']); + $intermediate = str_replace($decimalSeparator, '.', $intermediate); + if (is_numeric($intermediate)) { + $operand = (float) ($sign . str_replace($decimalSeparator, '.', $intermediate)); - return true; + return true; + } } return false; } + + public static function currencyMatcherRegexp(): string + { + $currencyCodes = sprintf(self::CURRENCY_CONVERSION_LIST, preg_quote(StringHelper::getCurrencyCode(), '/')); + $decimalSeparator = preg_quote(StringHelper::getDecimalSeparator(), '/'); + + return '~^(?:(?: *(?[-+])? *(?[' . $currencyCodes . ']) *(?[-+])? *(?[0-9]+[' . $decimalSeparator . ']?[0-9*]*(?:E[-+]?[0-9]*)?) *)|(?: *(?[-+])? *(?[0-9]+' . $decimalSeparator . '?[0-9]*(?:E[-+]?[0-9]*)?) *(?[' . $currencyCodes . ']) *))$~ui'; + } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engine/Operands/StructuredReference.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engine/Operands/StructuredReference.php index 4a4d1b8..59cc3e3 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engine/Operands/StructuredReference.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engine/Operands/StructuredReference.php @@ -2,7 +2,11 @@ namespace PhpOffice\PhpSpreadsheet\Calculation\Engine\Operands; +use PhpOffice\PhpSpreadsheet\Calculation\Calculation; use PhpOffice\PhpSpreadsheet\Calculation\Exception; +use PhpOffice\PhpSpreadsheet\Cell\Cell; +use PhpOffice\PhpSpreadsheet\Cell\Coordinate; +use PhpOffice\PhpSpreadsheet\Worksheet\Table; final class StructuredReference implements Operand { @@ -11,8 +15,39 @@ final class StructuredReference implements Operand private const OPEN_BRACE = '['; private const CLOSE_BRACE = ']'; + private const ITEM_SPECIFIER_ALL = '#All'; + private const ITEM_SPECIFIER_HEADERS = '#Headers'; + private const ITEM_SPECIFIER_DATA = '#Data'; + private const ITEM_SPECIFIER_TOTALS = '#Totals'; + private const ITEM_SPECIFIER_THIS_ROW = '#This Row'; + + private const ITEM_SPECIFIER_ROWS_SET = [ + self::ITEM_SPECIFIER_ALL, + self::ITEM_SPECIFIER_HEADERS, + self::ITEM_SPECIFIER_DATA, + self::ITEM_SPECIFIER_TOTALS, + ]; + + private const TABLE_REFERENCE = '/([\p{L}_\\\\][\p{L}\p{N}\._]+)?(\[(?:[^\]\[]+|(?R))*+\])/miu'; + private string $value; + private string $tableName; + + private Table $table; + + private string $reference; + + private ?int $headersRow; + + private int $firstDataRow; + + private int $lastDataRow; + + private ?int $totalsRow; + + private array $columns; + public function __construct(string $structuredReference) { $this->value = $structuredReference; @@ -42,8 +77,268 @@ public static function fromParser(string $formula, int $index, array $matches): return new self($val); } + /** + * @throws Exception + * @throws \PhpOffice\PhpSpreadsheet\Exception + */ + public function parse(Cell $cell): string + { + $this->getTableStructure($cell); + $cellRange = ($this->isRowReference()) ? $this->getRowReference($cell) : $this->getColumnReference(); + + return $cellRange; + } + + private function isRowReference(): bool + { + return strpos($this->value, '[@') !== false + || strpos($this->value, '[' . self::ITEM_SPECIFIER_THIS_ROW . ']') !== false; + } + + /** + * @throws Exception + * @throws \PhpOffice\PhpSpreadsheet\Exception + */ + private function getTableStructure(Cell $cell): void + { + preg_match(self::TABLE_REFERENCE, $this->value, $matches); + + $this->tableName = $matches[1]; + $this->table = ($this->tableName === '') + ? $this->getTableForCell($cell) + : $this->getTableByName($cell); + $this->reference = $matches[2]; + $tableRange = Coordinate::getRangeBoundaries($this->table->getRange()); + + $this->headersRow = ($this->table->getShowHeaderRow()) ? (int) $tableRange[0][1] : null; + $this->firstDataRow = ($this->table->getShowHeaderRow()) ? (int) $tableRange[0][1] + 1 : $tableRange[0][1]; + $this->totalsRow = ($this->table->getShowTotalsRow()) ? (int) $tableRange[1][1] : null; + $this->lastDataRow = ($this->table->getShowTotalsRow()) ? (int) $tableRange[1][1] - 1 : $tableRange[1][1]; + + $this->columns = $this->getColumns($cell, $tableRange); + } + + /** + * @throws Exception + * @throws \PhpOffice\PhpSpreadsheet\Exception + */ + private function getTableForCell(Cell $cell): Table + { + $tables = $cell->getWorksheet()->getTableCollection(); + foreach ($tables as $table) { + /** @var Table $table */ + $range = $table->getRange(); + if ($cell->isInRange($range) === true) { + $this->tableName = $table->getName(); + + return $table; + } + } + + throw new Exception('Table for Structured Reference cannot be identified'); + } + + /** + * @throws Exception + * @throws \PhpOffice\PhpSpreadsheet\Exception + */ + private function getTableByName(Cell $cell): Table + { + $table = $cell->getWorksheet()->getTableByName($this->tableName); + + if ($table === null) { + throw new Exception("Table {$this->tableName} for Structured Reference cannot be located"); + } + + return $table; + } + + private function getColumns(Cell $cell, array $tableRange): array + { + $worksheet = $cell->getWorksheet(); + $cellReference = $cell->getCoordinate(); + + $columns = []; + $lastColumn = ++$tableRange[1][0]; + for ($column = $tableRange[0][0]; $column !== $lastColumn; ++$column) { + $columns[$column] = $worksheet + ->getCell($column . ($this->headersRow ?? ($this->firstDataRow - 1))) + ->getCalculatedValue(); + } + + $worksheet->getCell($cellReference); + + return $columns; + } + + private function getRowReference(Cell $cell): string + { + $reference = str_replace("\u{a0}", ' ', $this->reference); + /** @var string $reference */ + $reference = str_replace('[' . self::ITEM_SPECIFIER_THIS_ROW . '],', '', $reference); + + foreach ($this->columns as $columnId => $columnName) { + $columnName = str_replace("\u{a0}", ' ', $columnName); + $reference = $this->adjustRowReference($columnName, $reference, $cell, $columnId); + } + + /** @var string $reference */ + return $this->validateParsedReference(trim($reference, '[]@, ')); + } + + private function adjustRowReference(string $columnName, string $reference, Cell $cell, string $columnId): string + { + if ($columnName !== '') { + $cellReference = $columnId . $cell->getRow(); + $pattern1 = '/\[' . preg_quote($columnName, '/') . '\]/miu'; + $pattern2 = '/@' . preg_quote($columnName, '/') . '/miu'; + if (preg_match($pattern1, $reference) === 1) { + $reference = preg_replace($pattern1, $cellReference, $reference); + } elseif (preg_match($pattern2, $reference) === 1) { + $reference = preg_replace($pattern2, $cellReference, $reference); + } + /** @var string $reference */ + } + + return $reference; + } + + /** + * @throws Exception + * @throws \PhpOffice\PhpSpreadsheet\Exception + */ + private function getColumnReference(): string + { + $reference = str_replace("\u{a0}", ' ', $this->reference); + $startRow = ($this->totalsRow === null) ? $this->lastDataRow : $this->totalsRow; + $endRow = ($this->headersRow === null) ? $this->firstDataRow : $this->headersRow; + + [$startRow, $endRow] = $this->getRowsForColumnReference($reference, $startRow, $endRow); + $reference = $this->getColumnsForColumnReference($reference, $startRow, $endRow); + + $reference = trim($reference, '[]@, '); + if (substr_count($reference, ':') > 1) { + $cells = explode(':', $reference); + $firstCell = array_shift($cells); + $lastCell = array_pop($cells); + $reference = "{$firstCell}:{$lastCell}"; + } + + return $this->validateParsedReference($reference); + } + + /** + * @throws Exception + * @throws \PhpOffice\PhpSpreadsheet\Exception + */ + private function validateParsedReference(string $reference): string + { + if (preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . ':' . Calculation::CALCULATION_REGEXP_CELLREF . '$/miu', $reference) !== 1) { + if (preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/miu', $reference) !== 1) { + throw new Exception( + "Invalid Structured Reference {$this->reference} {$reference}", + Exception::CALCULATION_ENGINE_PUSH_TO_STACK + ); + } + } + + return $reference; + } + + private function fullData(int $startRow, int $endRow): string + { + $columns = array_keys($this->columns); + $firstColumn = array_shift($columns); + $lastColumn = (empty($columns)) ? $firstColumn : array_pop($columns); + + return "{$firstColumn}{$startRow}:{$lastColumn}{$endRow}"; + } + + private function getMinimumRow(string $reference): int + { + switch ($reference) { + case self::ITEM_SPECIFIER_ALL: + case self::ITEM_SPECIFIER_HEADERS: + return $this->headersRow ?? $this->firstDataRow; + case self::ITEM_SPECIFIER_DATA: + return $this->firstDataRow; + case self::ITEM_SPECIFIER_TOTALS: + return $this->totalsRow ?? $this->lastDataRow; + } + + return $this->headersRow ?? $this->firstDataRow; + } + + private function getMaximumRow(string $reference): int + { + switch ($reference) { + case self::ITEM_SPECIFIER_HEADERS: + return $this->headersRow ?? $this->firstDataRow; + case self::ITEM_SPECIFIER_DATA: + return $this->lastDataRow; + case self::ITEM_SPECIFIER_ALL: + case self::ITEM_SPECIFIER_TOTALS: + return $this->totalsRow ?? $this->lastDataRow; + } + + return $this->totalsRow ?? $this->lastDataRow; + } + public function value(): string { return $this->value; } + + /** + * @return array + */ + private function getRowsForColumnReference(string &$reference, int $startRow, int $endRow): array + { + $rowsSelected = false; + foreach (self::ITEM_SPECIFIER_ROWS_SET as $rowReference) { + $pattern = '/\[' . $rowReference . '\]/mui'; + /** @var string $reference */ + if (preg_match($pattern, $reference) === 1) { + if (($rowReference === self::ITEM_SPECIFIER_HEADERS) && ($this->table->getShowHeaderRow() === false)) { + throw new Exception( + 'Table Headers are Hidden, and should not be Referenced', + Exception::CALCULATION_ENGINE_PUSH_TO_STACK + ); + } + $rowsSelected = true; + $startRow = min($startRow, $this->getMinimumRow($rowReference)); + $endRow = max($endRow, $this->getMaximumRow($rowReference)); + $reference = preg_replace($pattern, '', $reference); + } + } + if ($rowsSelected === false) { + // If there isn't any Special Item Identifier specified, then the selection defaults to data rows only. + $startRow = $this->firstDataRow; + $endRow = $this->lastDataRow; + } + + return [$startRow, $endRow]; + } + + private function getColumnsForColumnReference(string $reference, int $startRow, int $endRow): string + { + $columnsSelected = false; + foreach ($this->columns as $columnId => $columnName) { + $columnName = str_replace("\u{a0}", ' ', $columnName); + $cellFrom = "{$columnId}{$startRow}"; + $cellTo = "{$columnId}{$endRow}"; + $cellReference = ($cellFrom === $cellTo) ? $cellFrom : "{$cellFrom}:{$cellTo}"; + $pattern = '/\[' . preg_quote($columnName, '/') . '\]/mui'; + if (preg_match($pattern, $reference) === 1) { + $columnsSelected = true; + $reference = preg_replace($pattern, $cellReference, $reference); + } + /** @var string $reference */ + } + if ($columnsSelected === false) { + return $this->fullData($startRow, $endRow); + } + + return $reference; + } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering.php index e3a2bd6..fdee750 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering.php @@ -20,28 +20,6 @@ class Engineering */ public const EULER = 2.71828182845904523536; - /** - * parseComplex. - * - * Parses a complex number into its real and imaginary parts, and an I or J suffix - * - * @deprecated 1.12.0 No longer used by internal code. Please use the \Complex\Complex class instead - * - * @param string $complexNumber The complex number - * - * @return mixed[] Indexed on "real", "imaginary" and "suffix" - */ - public static function parseComplex($complexNumber) - { - $complex = new Complex($complexNumber); - - return [ - 'real' => $complex->getReal(), - 'imaginary' => $complex->getImaginary(), - 'suffix' => $complex->getSuffix(), - ]; - } - /** * BESSELI. * diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/BesselJ.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/BesselJ.php index 800a8a1..457c74d 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/BesselJ.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/BesselJ.php @@ -133,7 +133,7 @@ private static function besselJ2(float $x, int $ord): float return self::besselj2b($ax, $ord, $x); } - private static function besselj2a(float $ax, int $ord, float $x) + private static function besselj2a(float $ax, int $ord, float $x): float { $tox = 2.0 / $ax; $bjm = self::besselJ0($ax); @@ -148,7 +148,7 @@ private static function besselj2a(float $ax, int $ord, float $x) return ($x < 0.0 && ($ord % 2) == 1) ? -$ans : $ans; } - private static function besselj2b(float $ax, int $ord, float $x) + private static function besselj2b(float $ax, int $ord, float $x): float { $tox = 2.0 / $ax; $jsum = false; diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/Complex.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/Complex.php index 691de8b..f7ec02d 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/Complex.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/Complex.php @@ -49,7 +49,7 @@ public static function COMPLEX($realNumber = 0.0, $imaginary = 0.0, $suffix = 'i return $e->getMessage(); } - if (($suffix == 'i') || ($suffix == 'j') || ($suffix == '')) { + if (($suffix === 'i') || ($suffix === 'j') || ($suffix === '')) { $complex = new ComplexObject($realNumber, $imaginary, $suffix); return (string) $complex; diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ConvertBase.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ConvertBase.php index e80490b..414e0b4 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ConvertBase.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ConvertBase.php @@ -11,6 +11,7 @@ abstract class ConvertBase { use ArrayEnabled; + /** @param mixed $value */ protected static function validateValue($value): string { if (is_bool($value)) { @@ -29,6 +30,7 @@ protected static function validateValue($value): string return strtoupper((string) $value); } + /** @param mixed $places */ protected static function validatePlaces($places = null): ?int { if ($places === null) { diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ConvertBinary.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ConvertBinary.php index 4741f30..04bf3e5 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ConvertBinary.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ConvertBinary.php @@ -40,7 +40,7 @@ public static function toDecimal($value) return $e->getMessage(); } - if (strlen($value) == 10) { + if (strlen($value) == 10 && $value[0] === '1') { // Two's Complement $value = substr($value, -9); @@ -91,7 +91,7 @@ public static function toHex($value, $places = null) return $e->getMessage(); } - if (strlen($value) == 10) { + if (strlen($value) == 10 && $value[0] === '1') { $high2 = substr($value, 0, 2); $low8 = substr($value, 2); $xarr = ['00' => '00000000', '01' => '00000001', '10' => 'FFFFFFFE', '11' => 'FFFFFFFF']; @@ -144,7 +144,7 @@ public static function toOctal($value, $places = null) return $e->getMessage(); } - if (strlen($value) == 10 && substr($value, 0, 1) === '1') { // Two's Complement + if (strlen($value) == 10 && $value[0] === '1') { // Two's Complement return str_repeat('7', 6) . strtoupper(decoct((int) bindec("11$value"))); } $octVal = (string) decoct((int) bindec($value)); diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ConvertUOM.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ConvertUOM.php index 8541a6c..32ef9d3 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ConvertUOM.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ConvertUOM.php @@ -572,7 +572,7 @@ public static function CONVERT($value, $fromUOM, $toUOM) return ($baseValue * self::$unitConversions[$fromCategory][$toUOM]) / $toMultiplier; } - private static function getUOMDetails(string $uom) + private static function getUOMDetails(string $uom): array { if (isset(self::$conversionUnits[$uom])) { $unitCategory = self::$conversionUnits[$uom]['Group']; @@ -678,7 +678,7 @@ protected static function convertTemperature(string $fromUOM, string $toUOM, $va return $value; } - private static function resolveTemperatureSynonyms(string $uom) + private static function resolveTemperatureSynonyms(string $uom): string { switch ($uom) { case 'fah': diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/Erf.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/Erf.php index 6254d47..133722d 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/Erf.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/Erf.php @@ -10,7 +10,7 @@ class Erf { use ArrayEnabled; - private static $twoSqrtPi = 1.128379167095512574; + private const TWO_SQRT_PI = 1.128379167095512574; /** * ERF. @@ -77,11 +77,16 @@ public static function ERFPRECISE($limit) return self::ERF($limit); } - // - // Private method to calculate the erf value - // + /** + * Method to calculate the erf value. + * + * @param float|int|string $value + * + * @return float + */ public static function erfValue($value) { + $value = (float) $value; if (abs($value) > 2.2) { return 1 - ErfC::ERFC($value); } @@ -100,6 +105,6 @@ public static function erfValue($value) } } while (abs($term / $sum) > Functions::PRECISION); - return self::$twoSqrtPi * $sum; + return self::TWO_SQRT_PI * $sum; } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ErfC.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ErfC.php index eb834b7..0350c9c 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ErfC.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ErfC.php @@ -43,13 +43,18 @@ public static function ERFC($value) return ExcelError::VALUE(); } - // - // Private method to calculate the erfc value - // - private static $oneSqrtPi = 0.564189583547756287; + private const ONE_SQRT_PI = 0.564189583547756287; + /** + * Method to calculate the erfc value. + * + * @param float|int|string $value + * + * @return float + */ private static function erfcValue($value) { + $value = (float) $value; if (abs($value) < 2.2) { return 1 - Erf::erfValue($value); } @@ -72,6 +77,6 @@ private static function erfcValue($value) $q2 = $b / $d; } while ((abs($q1 - $q2) / $q2) > Functions::PRECISION); - return self::$oneSqrtPi * exp(-$value * $value) * $q2; + return self::ONE_SQRT_PI * exp(-$value * $value) * $q2; } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Exception.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Exception.php index 0388f5a..a95a452 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Exception.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Exception.php @@ -6,6 +6,8 @@ class Exception extends PhpSpreadsheetException { + public const CALCULATION_ENGINE_PUSH_TO_STACK = 1; + /** * Error handler callback. * diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial.php index 43e27c7..dcca5f8 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial.php @@ -12,8 +12,6 @@ /** * @deprecated 1.18.0 - * - * @codeCoverageIgnore */ class Financial { @@ -543,7 +541,7 @@ public static function DDB($cost, $salvage, $life, $period, $factor = 2.0) * date when the security is traded to the buyer. * @param mixed $maturity The security's maturity date. * The maturity date is the date when the security expires. - * @param int $price The security's price per $100 face value + * @param mixed $price The security's price per $100 face value * @param int $redemption The security's redemption value per $100 face value * @param int $basis The type of day count to use. * 0 or omitted US (NASD) 30/360 @@ -1004,7 +1002,7 @@ public static function PRICE($settlement, $maturity, $rate, $yield, $redemption, * is traded to the buyer. * @param mixed $maturity The security's maturity date. * The maturity date is the date when the security expires. - * @param int $discount The security's discount rate + * @param mixed $discount The security's discount rate * @param int $redemption The security's redemption value per $100 face value * @param int $basis The type of day count to use. * 0 or omitted US (NASD) 30/360 @@ -1035,8 +1033,8 @@ public static function PRICEDISC($settlement, $maturity, $discount, $redemption, * @param mixed $maturity The security's maturity date. * The maturity date is the date when the security expires. * @param mixed $issue The security's issue date - * @param int $rate The security's interest rate at date of issue - * @param int $yield The security's annual yield + * @param mixed $rate The security's interest rate at date of issue + * @param mixed $yield The security's annual yield * @param int $basis The type of day count to use. * 0 or omitted US (NASD) 30/360 * 1 Actual/actual @@ -1216,7 +1214,7 @@ public static function SYD($cost, $salvage, $life, $period) * Treasury bill is traded to the buyer. * @param mixed $maturity The Treasury bill's maturity date. * The maturity date is the date when the Treasury bill expires. - * @param int $discount The Treasury bill's discount rate + * @param mixed $discount The Treasury bill's discount rate * * @return float|string Result, or a string containing an error */ @@ -1239,7 +1237,7 @@ public static function TBILLEQ($settlement, $maturity, $discount) * when the Treasury bill is traded to the buyer. * @param mixed $maturity The Treasury bill's maturity date. * The maturity date is the date when the Treasury bill expires. - * @param int $discount The Treasury bill's discount rate + * @param mixed $discount The Treasury bill's discount rate * * @return float|string Result, or a string containing an error */ @@ -1262,7 +1260,7 @@ public static function TBILLPRICE($settlement, $maturity, $discount) * when the Treasury bill is traded to the buyer. * @param mixed $maturity The Treasury bill's maturity date. * The maturity date is the date when the Treasury bill expires. - * @param int $price The Treasury bill's price per $100 face value + * @param mixed $price The Treasury bill's price per $100 face value * * @return float|mixed|string */ @@ -1342,7 +1340,7 @@ public static function XNPV($rate, $values, $dates) * is traded to the buyer. * @param mixed $maturity The security's maturity date. * The maturity date is the date when the security expires. - * @param int $price The security's price per $100 face value + * @param mixed $price The security's price per $100 face value * @param int $redemption The security's redemption value per $100 face value * @param int $basis The type of day count to use. * 0 or omitted US (NASD) 30/360 @@ -1373,8 +1371,8 @@ public static function YIELDDISC($settlement, $maturity, $price, $redemption, $b * @param mixed $maturity The security's maturity date. * The maturity date is the date when the security expires. * @param mixed $issue The security's issue date - * @param int $rate The security's interest rate at date of issue - * @param int $price The security's price per $100 face value + * @param mixed $rate The security's interest rate at date of issue + * @param mixed $price The security's price per $100 face value * @param int $basis The type of day count to use. * 0 or omitted US (NASD) 30/360 * 1 Actual/actual diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Amortization.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Amortization.php index 691ba40..72a71b2 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Amortization.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Amortization.php @@ -171,8 +171,9 @@ public static function AMORLINC( $yearFrac = $yearFracx; if ( - ($basis == FinancialConstants::BASIS_DAYS_PER_YEAR_ACTUAL) && - ($yearFrac < 1) && (Functions::scalar(DateTimeExcel\Helpers::isLeapYear($purchasedYear))) + $basis == FinancialConstants::BASIS_DAYS_PER_YEAR_ACTUAL + && $yearFrac < 1 + && DateTimeExcel\Helpers::isLeapYear(Functions::scalar($purchasedYear)) ) { $yearFrac *= 365 / 366; } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic/Interest.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic/Interest.php index 4a82514..caec74f 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic/Interest.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic/Interest.php @@ -199,7 +199,8 @@ public static function rate( return $close ? $rate : ExcelError::NAN(); } - private static function rateNextGuess($rate, $numberOfPeriods, $payment, $presentValue, $futureValue, $type) + /** @return float|string */ + private static function rateNextGuess(float $rate, int $numberOfPeriods, float $payment, float $presentValue, float $futureValue, int $type) { if ($rate == 0.0) { return ExcelError::NAN(); diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic/InterestAndPrincipal.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic/InterestAndPrincipal.php index ca989e0..1408d46 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic/InterestAndPrincipal.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic/InterestAndPrincipal.php @@ -6,8 +6,10 @@ class InterestAndPrincipal { + /** @var float */ protected $interest; + /** @var float */ protected $principal; public function __construct( @@ -24,7 +26,7 @@ public function __construct( $principal = 0.0; for ($i = 1; $i <= $period; ++$i) { $interest = ($type === FinancialConstants::PAYMENT_BEGINNING_OF_PERIOD && $i == 1) ? 0 : -$capital * $rate; - $principal = $payment - $interest; + $principal = (float) $payment - $interest; $capital += $principal; } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Variable/NonPeriodic.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Variable/NonPeriodic.php index b812613..b4247b7 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Variable/NonPeriodic.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Variable/NonPeriodic.php @@ -51,8 +51,11 @@ public static function rate($values, $dates, $guess = self::DEFAULT_GUESS) $f2 = self::xnpvOrdered($x2, $values, $dates, false); $found = false; for ($i = 0; $i < self::FINANCIAL_MAX_ITERATIONS; ++$i) { - if (!is_numeric($f1) || !is_numeric($f2)) { - break; + if (!is_numeric($f1)) { + return $f1; + } + if (!is_numeric($f2)) { + return $f2; } $f1 = (float) $f1; $f2 = (float) $f2; @@ -68,11 +71,32 @@ public static function rate($values, $dates, $guess = self::DEFAULT_GUESS) $f2 = self::xnpvOrdered($x2, $values, $dates, false); } } - if (!$found) { - return ExcelError::NAN(); + if ($found) { + return self::xirrPart3($values, $dates, $x1, $x2); } - return self::xirrPart3($values, $dates, $x1, $x2); + // Newton-Raphson didn't work - try bisection + $x1 = $guess - 0.5; + $x2 = $guess + 0.5; + for ($i = 0; $i < self::FINANCIAL_MAX_ITERATIONS; ++$i) { + $f1 = self::xnpvOrdered($x1, $values, $dates, false, true); + $f2 = self::xnpvOrdered($x2, $values, $dates, false, true); + if (!is_numeric($f1) || !is_numeric($f2)) { + break; + } + if ($f1 * $f2 <= 0) { + $found = true; + + break; + } + $x1 -= 0.5; + $x2 += 0.5; + } + if ($found) { + return self::xirrBisection($values, $dates, $x1, $x2); + } + + return ExcelError::NAN(); } /** @@ -190,6 +214,45 @@ private static function xirrPart3(array $values, array $dates, float $x1, float return $rslt; } + /** + * @return float|string + */ + private static function xirrBisection(array $values, array $dates, float $x1, float $x2) + { + $rslt = ExcelError::NAN(); + for ($i = 0; $i < self::FINANCIAL_MAX_ITERATIONS; ++$i) { + $rslt = ExcelError::NAN(); + $f1 = self::xnpvOrdered($x1, $values, $dates, false, true); + $f2 = self::xnpvOrdered($x2, $values, $dates, false, true); + if (!is_numeric($f1) || !is_numeric($f2)) { + break; + } + $f1 = (float) $f1; + $f2 = (float) $f2; + if (abs($f1) < self::FINANCIAL_PRECISION && abs($f2) < self::FINANCIAL_PRECISION) { + break; + } + if ($f1 * $f2 > 0) { + break; + } + $rslt = ($x1 + $x2) / 2; + $f3 = self::xnpvOrdered($rslt, $values, $dates, false, true); + if (!is_float($f3)) { + break; + } + if ($f3 * $f1 < 0) { + $x2 = $rslt; + } else { + $x1 = $rslt; + } + if (abs($f3) < self::FINANCIAL_PRECISION) { + break; + } + } + + return $rslt; + } + /** * @param mixed $rate * @param mixed $values @@ -197,7 +260,7 @@ private static function xirrPart3(array $values, array $dates, float $x1, float * * @return float|string */ - private static function xnpvOrdered($rate, $values, $dates, bool $ordered = true) + private static function xnpvOrdered($rate, $values, $dates, bool $ordered = true, bool $capAtNegative1 = false) { $rate = Functions::flattenSingleValue($rate); $values = Functions::flattenArray($values); @@ -206,6 +269,9 @@ private static function xnpvOrdered($rate, $values, $dates, bool $ordered = true try { self::validateXnpv($rate, $values, $dates); + if ($capAtNegative1 && $rate <= -1) { + $rate = -1.0 + 1.0E-10; + } $date0 = DateTimeExcel\Helpers::getDateValue($dates[0]); } catch (Exception $e) { return $e->getMessage(); @@ -225,7 +291,7 @@ private static function xnpvOrdered($rate, $values, $dates, bool $ordered = true if ($date0 > $datei) { $dif = $ordered ? ExcelError::NAN() : -((int) DateTimeExcel\Difference::interval($datei, $date0, 'd')); } else { - $dif = DateTimeExcel\Difference::interval($date0, $datei, 'd'); + $dif = Functions::scalar(DateTimeExcel\Difference::interval($date0, $datei, 'd')); } if (!is_numeric($dif)) { return $dif; diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Variable/Periodic.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Variable/Periodic.php index 545102f..d899e84 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Variable/Periodic.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Variable/Periodic.php @@ -144,6 +144,7 @@ public static function modifiedRate($values, $financeRate, $reinvestmentRate) * Returns the Net Present Value of a cash flow series given a discount rate. * * @param mixed $rate + * @param array $args * * @return float */ diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Coupons.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Coupons.php index 14c2d01..4028cd4 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Coupons.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Coupons.php @@ -200,7 +200,7 @@ public static function COUPDAYSNC( } /** @var int */ - $daysPerYear = Helpers::daysPerYear(DateTimeExcel\DateParts::year($settlement), $basis); + $daysPerYear = Helpers::daysPerYear(Functions::Scalar(DateTimeExcel\DateParts::year($settlement)), $basis); $next = self::couponFirstPeriodDate($settlement, $maturity, $frequency, self::PERIOD_DATE_NEXT); if ($basis === FinancialConstants::BASIS_DAYS_PER_YEAR_NASD) { diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Depreciation.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Depreciation.php index 8e1a2fc..e542a86 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Depreciation.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Depreciation.php @@ -208,6 +208,7 @@ public static function SYD($cost, $salvage, $life, $period) return $syd; } + /** @param mixed $cost */ private static function validateCost($cost, bool $negativeValueAllowed = false): float { $cost = FinancialValidations::validateFloat($cost); @@ -218,6 +219,7 @@ private static function validateCost($cost, bool $negativeValueAllowed = false): return $cost; } + /** @param mixed $salvage */ private static function validateSalvage($salvage, bool $negativeValueAllowed = false): float { $salvage = FinancialValidations::validateFloat($salvage); @@ -228,6 +230,7 @@ private static function validateSalvage($salvage, bool $negativeValueAllowed = f return $salvage; } + /** @param mixed $life */ private static function validateLife($life, bool $negativeValueAllowed = false): float { $life = FinancialValidations::validateFloat($life); @@ -238,6 +241,7 @@ private static function validateLife($life, bool $negativeValueAllowed = false): return $life; } + /** @param mixed $period */ private static function validatePeriod($period, bool $negativeValueAllowed = false): float { $period = FinancialValidations::validateFloat($period); @@ -248,6 +252,7 @@ private static function validatePeriod($period, bool $negativeValueAllowed = fal return $period; } + /** @param mixed $month */ private static function validateMonth($month): int { $month = FinancialValidations::validateInt($month); @@ -258,6 +263,7 @@ private static function validateMonth($month): int return $month; } + /** @param mixed $factor */ private static function validateFactor($factor): float { $factor = FinancialValidations::validateFloat($factor); diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Securities/Price.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Securities/Price.php index de1748a..22c93c0 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Securities/Price.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Securities/Price.php @@ -70,10 +70,10 @@ public static function price( return $e->getMessage(); } - $dsc = Coupons::COUPDAYSNC($settlement, $maturity, $frequency, $basis); - $e = Coupons::COUPDAYS($settlement, $maturity, $frequency, $basis); - $n = Coupons::COUPNUM($settlement, $maturity, $frequency, $basis); - $a = Coupons::COUPDAYBS($settlement, $maturity, $frequency, $basis); + $dsc = (float) Coupons::COUPDAYSNC($settlement, $maturity, $frequency, $basis); + $e = (float) Coupons::COUPDAYS($settlement, $maturity, $frequency, $basis); + $n = (int) Coupons::COUPNUM($settlement, $maturity, $frequency, $basis); + $a = (float) Coupons::COUPDAYBS($settlement, $maturity, $frequency, $basis); $baseYF = 1.0 + ($yield / $frequency); $rfp = 100 * ($rate / $frequency); @@ -195,7 +195,7 @@ public static function priceAtMaturity( return $e->getMessage(); } - $daysPerYear = Functions::scalar(Helpers::daysPerYear(DateTimeExcel\DateParts::year($settlement), $basis)); + $daysPerYear = Helpers::daysPerYear(Functions::scalar(DateTimeExcel\DateParts::year($settlement)), $basis); if (!is_numeric($daysPerYear)) { return $daysPerYear; } @@ -276,7 +276,7 @@ public static function received( $daysBetweenSettlementAndMaturity = DateTimeExcel\YearFrac::fraction($settlement, $maturity, $basis); if (!is_numeric($daysBetweenSettlementAndMaturity)) { // return date error - return $daysBetweenSettlementAndMaturity; + return Functions::scalar($daysBetweenSettlementAndMaturity); } return $investment / (1 - ($discount * $daysBetweenSettlementAndMaturity)); diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Securities/Yields.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Securities/Yields.php index bb2e8ae..d8aa67a 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Securities/Yields.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Securities/Yields.php @@ -57,7 +57,7 @@ public static function yieldDiscounted( return $e->getMessage(); } - $daysPerYear = Helpers::daysPerYear(DateTimeExcel\DateParts::year($settlement), $basis); + $daysPerYear = Helpers::daysPerYear(Functions::scalar(DateTimeExcel\DateParts::year($settlement)), $basis); if (!is_numeric($daysPerYear)) { return $daysPerYear; } @@ -122,7 +122,7 @@ public static function yieldAtMaturity( return $e->getMessage(); } - $daysPerYear = Helpers::daysPerYear(DateTimeExcel\DateParts::year($settlement), $basis); + $daysPerYear = Helpers::daysPerYear(Functions::scalar(DateTimeExcel\DateParts::year($settlement)), $basis); if (!is_numeric($daysPerYear)) { return $daysPerYear; } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Functions.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Functions.php index 747a1f4..0ec396f 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Functions.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Functions.php @@ -130,22 +130,26 @@ public static function DUMMY() return '#Not Yet Implemented'; } - public static function isMatrixValue($idx) + /** @param mixed $idx */ + public static function isMatrixValue($idx): bool { return (substr_count($idx, '.') <= 1) || (preg_match('/\.[A-Z]/', $idx) > 0); } - public static function isValue($idx) + /** @param mixed $idx */ + public static function isValue($idx): bool { return substr_count($idx, '.') === 0; } - public static function isCellValue($idx) + /** @param mixed $idx */ + public static function isCellValue($idx): bool { return substr_count($idx, '.') > 1; } - public static function ifCondition($condition) + /** @param mixed $condition */ + public static function ifCondition($condition): string { $condition = self::flattenSingleValue($condition); @@ -180,6 +184,11 @@ public static function ifCondition($condition) return str_replace('""""', '""', $operator . $operand); } + /** + * @param mixed $operand + * + * @return mixed + */ private static function operandSpecialHandling($operand) { if (is_numeric($operand) || is_bool($operand)) { @@ -635,7 +644,7 @@ public static function isFormula($cellReference = '', ?Cell $cell = null) public static function expandDefinedName(string $coordinate, Cell $cell): string { $worksheet = $cell->getWorksheet(); - $spreadsheet = $worksheet->getParent(); + $spreadsheet = $worksheet->getParentOrThrow(); // Uppercase coordinate $pCoordinatex = strtoupper($coordinate); // Eliminate leading equal sign diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Information/Value.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Information/Value.php index 2e524db..341d93b 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Information/Value.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Information/Value.php @@ -49,7 +49,7 @@ public static function isRef($value, ?Cell $cell = null) $cellValue = Functions::trimTrailingRange($value); if (preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/ui', $cellValue) === 1) { [$worksheet, $cellValue] = Worksheet::extractSheetTitle($cellValue, true); - if (!empty($worksheet) && $cell->getWorksheet()->getParent()->getSheetByName($worksheet) === null) { + if (!empty($worksheet) && $cell->getWorksheet()->getParentOrThrow()->getSheetByName($worksheet) === null) { return false; } [$column, $row] = Coordinate::indexesFromString($cellValue); @@ -60,7 +60,7 @@ public static function isRef($value, ?Cell $cell = null) return true; } - $namedRange = $cell->getWorksheet()->getParent()->getNamedRange($value); + $namedRange = $cell->getWorksheet()->getParentOrThrow()->getNamedRange($value); return $namedRange instanceof NamedRange; } @@ -227,7 +227,7 @@ public static function isFormula($cellReference = '', ?Cell $cell = null) $worksheetName = str_replace("''", "'", trim($matches[2], "'")); $worksheet = (!empty($worksheetName)) - ? $cell->getWorksheet()->getParent()->getSheetByName($worksheetName) + ? $cell->getWorksheet()->getParentOrThrow()->getSheetByName($worksheetName) : $cell->getWorksheet(); return ($worksheet !== null) ? $worksheet->getCell($fullCellReference)->isFormula() : ExcelError::REF(); diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Internal/MakeMatrix.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Internal/MakeMatrix.php index 8b53464..22c95e8 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Internal/MakeMatrix.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Internal/MakeMatrix.php @@ -4,6 +4,7 @@ class MakeMatrix { + /** @param array $args */ public static function make(...$args): array { return $args; diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Logical/Operations.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Logical/Operations.php index 2e2faa1..f097859 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Logical/Operations.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Logical/Operations.php @@ -33,23 +33,9 @@ class Operations */ public static function logicalAnd(...$args) { - $args = Functions::flattenArray($args); - - if (count($args) == 0) { - return ExcelError::VALUE(); - } - - $args = array_filter($args, function ($value) { - return $value !== null || (is_string($value) && trim($value) == ''); + return self::countTrueValues($args, function (int $trueValueCount, int $count): bool { + return $trueValueCount === $count; }); - - $returnValue = self::countTrueValues($args); - if (is_string($returnValue)) { - return $returnValue; - } - $argCount = count($args); - - return ($returnValue > 0) && ($returnValue == $argCount); } /** @@ -74,22 +60,9 @@ public static function logicalAnd(...$args) */ public static function logicalOr(...$args) { - $args = Functions::flattenArray($args); - - if (count($args) == 0) { - return ExcelError::VALUE(); - } - - $args = array_filter($args, function ($value) { - return $value !== null || (is_string($value) && trim($value) == ''); + return self::countTrueValues($args, function (int $trueValueCount): bool { + return $trueValueCount > 0; }); - - $returnValue = self::countTrueValues($args); - if (is_string($returnValue)) { - return $returnValue; - } - - return $returnValue > 0; } /** @@ -116,22 +89,9 @@ public static function logicalOr(...$args) */ public static function logicalXor(...$args) { - $args = Functions::flattenArray($args); - - if (count($args) == 0) { - return ExcelError::VALUE(); - } - - $args = array_filter($args, function ($value) { - return $value !== null || (is_string($value) && trim($value) == ''); + return self::countTrueValues($args, function (int $trueValueCount): bool { + return $trueValueCount % 2 === 1; }); - - $returnValue = self::countTrueValues($args); - if (is_string($returnValue)) { - return $returnValue; - } - - return $returnValue % 2 == 1; } /** @@ -177,31 +137,36 @@ public static function NOT($logical = false) } /** - * @return int|string + * @return bool|string */ - private static function countTrueValues(array $args) + private static function countTrueValues(array $args, callable $func) { $trueValueCount = 0; + $count = 0; - foreach ($args as $arg) { + $aArgs = Functions::flattenArrayIndexed($args); + foreach ($aArgs as $k => $arg) { + ++$count; // Is it a boolean value? if (is_bool($arg)) { $trueValueCount += $arg; - } elseif ((is_numeric($arg)) && (!is_string($arg))) { - $trueValueCount += ((int) $arg != 0); } elseif (is_string($arg)) { + $isLiteral = !Functions::isCellValue($k); $arg = mb_strtoupper($arg, 'UTF-8'); - if (($arg == 'TRUE') || ($arg == Calculation::getTRUE())) { - $arg = true; - } elseif (($arg == 'FALSE') || ($arg == Calculation::getFALSE())) { - $arg = false; + if ($isLiteral && ($arg == 'TRUE' || $arg == Calculation::getTRUE())) { + ++$trueValueCount; + } elseif ($isLiteral && ($arg == 'FALSE' || $arg == Calculation::getFALSE())) { + //$trueValueCount += 0; } else { - return ExcelError::VALUE(); + --$count; } - $trueValueCount += ($arg != 0); + } elseif (is_int($arg) || is_float($arg)) { + $trueValueCount += (int) ($arg != 0); + } else { + --$count; } } - return $trueValueCount; + return ($count === 0) ? ExcelError::VALUE() : $func($trueValueCount, $count); } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef.php index 354cb83..c7ddf89 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef.php @@ -223,7 +223,7 @@ public static function INDIRECT($cellAddress, Cell $cell) * @param mixed $width The width, in number of columns, that you want the returned reference to be. * Width must be a positive number. * - * @return array|string An array containing a cell or range of cells, or a string on error + * @return array|int|string An array containing a cell or range of cells, or a string on error */ public static function OFFSET($cellAddress = null, $rows = 0, $columns = 0, $height = null, $width = null, ?Cell $cell = null) { @@ -243,6 +243,8 @@ public static function OFFSET($cellAddress = null, $rows = 0, $columns = 0, $hei * Use the choose() method in the LookupRef\Selection class instead * @see LookupRef\Selection::choose() * + * @param array $chooseArgs + * * @return mixed The selected value */ public static function CHOOSE(...$chooseArgs) diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Address.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Address.php index 0d2db8b..1a0035d 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Address.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Address.php @@ -83,7 +83,7 @@ public static function cell($row, $column, $relativity = 1, $referenceStyle = tr return self::formatAsR1C1($row, $column, $relativity, $sheetName); } - private static function sheetName(string $sheetName) + private static function sheetName(string $sheetName): string { if ($sheetName > '') { if (strpos($sheetName, ' ') !== false || strpos($sheetName, '[') !== false) { diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Formula.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Formula.php index 834fe52..fceb191 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Formula.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Formula.php @@ -27,7 +27,7 @@ public static function text($cellReference = '', ?Cell $cell = null) $cellReference = $matches[6] . $matches[7]; $worksheetName = trim($matches[3], "'"); $worksheet = (!empty($worksheetName)) - ? $cell->getWorksheet()->getParent()->getSheetByName($worksheetName) + ? $cell->getWorksheet()->getParentOrThrow()->getSheetByName($worksheetName) : $cell->getWorksheet(); if ( diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/HLookup.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/HLookup.php index e2d27bd..bc425f8 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/HLookup.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/HLookup.php @@ -27,7 +27,7 @@ class HLookup extends LookupBase */ public static function lookup($lookupValue, $lookupArray, $indexNumber, $notExactMatch = true) { - if (is_array($lookupValue)) { + if (is_array($lookupValue) || is_array($indexNumber)) { return self::evaluateArrayArgumentsIgnore([self::class, __FUNCTION__], 1, $lookupValue, $lookupArray, $indexNumber, $notExactMatch); } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Helpers.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Helpers.php index 76a194b..33a7488 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Helpers.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Helpers.php @@ -66,7 +66,7 @@ public static function extractWorksheet(string $cellAddress, Cell $cell): array } $worksheet = ($sheetName !== '') - ? $cell->getWorksheet()->getParent()->getSheetByName($sheetName) + ? $cell->getWorksheet()->getParentOrThrow()->getSheetByName($sheetName) : $cell->getWorksheet(); return [$cellAddress, $worksheet, $sheetName]; diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Lookup.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Lookup.php index 76a360b..d836633 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Lookup.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Lookup.php @@ -39,7 +39,7 @@ public static function lookup($lookupValue, $lookupVector, $resultVector = null) $lookupColumns = self::columnCount($lookupVector); } - $resultVector = self::verifyResultVector($lookupVector, $resultVector); + $resultVector = self::verifyResultVector($resultVector ?? $lookupVector); if ($lookupRows === 2 && !$hasResultVector) { $resultVector = array_pop($lookupVector); @@ -78,12 +78,8 @@ private static function verifyLookupValues(array $lookupVector, array $resultVec return $lookupVector; } - private static function verifyResultVector(array $lookupVector, $resultVector) + private static function verifyResultVector(array $resultVector): array { - if ($resultVector === null) { - $resultVector = $lookupVector; - } - $resultRows = self::rowCount($resultVector); $resultColumns = self::columnCount($resultVector); diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/LookupBase.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/LookupBase.php index 5fe1676..be5d81c 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/LookupBase.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/LookupBase.php @@ -17,6 +17,7 @@ protected static function validateLookupArray($lookup_array): void } } + /** @param float|int|string $index_number */ protected static function validateIndexLookup(array $lookup_array, $index_number): int { // index_number must be a number greater than or equal to 1. diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php index d7d15d4..8ee759e 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php @@ -125,6 +125,7 @@ function ($value) { return $matrix[$rowNum][$columnNum]; } + /** @return mixed */ private static function extractRowValue(array $matrix, array $rowKeys, int $rowNum) { if ($rowNum === 0) { diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Offset.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Offset.php index 02a2558..562d753 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Offset.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Offset.php @@ -91,15 +91,16 @@ public static function OFFSET($cellAddress = null, $rows = 0, $columns = 0, $hei return self::extractRequiredCells($worksheet, $cellAddress); } + /** @return mixed */ private static function extractRequiredCells(?Worksheet $worksheet, string $cellAddress) { return Calculation::getInstance($worksheet !== null ? $worksheet->getParent() : null) ->extractCellRange($cellAddress, $worksheet, false); } - private static function extractWorksheet($cellAddress, Cell $cell): array + private static function extractWorksheet(?string $cellAddress, Cell $cell): array { - $cellAddress = self::assessCellAddress($cellAddress, $cell); + $cellAddress = self::assessCellAddress($cellAddress ?? '', $cell); $sheetName = ''; if (strpos($cellAddress, '!') !== false) { @@ -108,7 +109,7 @@ private static function extractWorksheet($cellAddress, Cell $cell): array } $worksheet = ($sheetName !== '') - ? $cell->getWorksheet()->getParent()->getSheetByName($sheetName) + ? $cell->getWorksheet()->getParentOrThrow()->getSheetByName($sheetName) : $cell->getWorksheet(); return [$cellAddress, $worksheet]; @@ -123,7 +124,11 @@ private static function assessCellAddress(string $cellAddress, Cell $cell): stri return $cellAddress; } - private static function adjustEndCellColumnForWidth(string $endCellColumn, $width, int $startCellColumn, $columns) + /** + * @param mixed $width + * @param mixed $columns + */ + private static function adjustEndCellColumnForWidth(string $endCellColumn, $width, int $startCellColumn, $columns): int { $endCellColumn = Coordinate::columnIndexFromString($endCellColumn) - 1; if (($width !== null) && (!is_object($width))) { @@ -135,6 +140,11 @@ private static function adjustEndCellColumnForWidth(string $endCellColumn, $widt return $endCellColumn; } + /** + * @param mixed $height + * @param mixed $rows + * @param mixed $endCellRow + */ private static function adustEndCellRowForHeight($height, int $startCellRow, $rows, $endCellRow): int { if (($height !== null) && (!is_object($height))) { diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/VLookup.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/VLookup.php index edeb1aa..badd105 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/VLookup.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/VLookup.php @@ -26,7 +26,7 @@ class VLookup extends LookupBase */ public static function lookup($lookupValue, $lookupArray, $indexNumber, $notExactMatch = true) { - if (is_array($lookupValue)) { + if (is_array($lookupValue) || is_array($indexNumber)) { return self::evaluateArrayArgumentsIgnore([self::class, __FUNCTION__], 1, $lookupValue, $lookupArray, $indexNumber, $notExactMatch); } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig.php index 1790b21..a92e9c8 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig.php @@ -766,7 +766,7 @@ public static function SUM(...$args) * @param string $criteria the criteria that defines which cells will be summed * @param mixed $sumRange * - * @return float|string + * @return null|float|string */ public static function SUMIF($range, $criteria, $sumRange = []) { diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Combinations.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Combinations.php index 5a652da..f68c402 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Combinations.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Combinations.php @@ -40,7 +40,7 @@ public static function withoutRepetition($numObjs, $numInSet) return $e->getMessage(); } - return round(Factorial::fact($numObjs) / Factorial::fact($numObjs - $numInSet)) / Factorial::fact($numInSet); + return round(Factorial::fact($numObjs) / Factorial::fact($numObjs - $numInSet)) / Factorial::fact($numInSet); // @phpstan-ignore-line } /** @@ -85,7 +85,7 @@ public static function withRepetition($numObjs, $numInSet) } return round( - Factorial::fact($numObjs + $numInSet - 1) / Factorial::fact($numObjs - 1) + Factorial::fact($numObjs + $numInSet - 1) / Factorial::fact($numObjs - 1) // @phpstan-ignore-line ) / Factorial::fact($numInSet); } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Factorial.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Factorial.php index b6883e2..8059eec 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Factorial.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Factorial.php @@ -5,6 +5,7 @@ use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled; use PhpOffice\PhpSpreadsheet\Calculation\Exception; use PhpOffice\PhpSpreadsheet\Calculation\Functions; +use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError; use PhpOffice\PhpSpreadsheet\Calculation\Statistical; class Factorial @@ -120,6 +121,6 @@ public static function multinomial(...$args) $summer = self::fact($summer); - return $summer / $divisor; + return is_numeric($summer) ? ($summer / $divisor) : ExcelError::VALUE(); } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/IntClass.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/IntClass.php index f7f7764..230f969 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/IntClass.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/IntClass.php @@ -19,7 +19,7 @@ class IntClass * * @param array|float $number Number to cast to an integer, or can be an array of numbers * - * @return array|string Integer value, or a string containing an error + * @return array|int|string Integer value, or a string containing an error * If an array of numbers is passed as the argument, then the returned result will also be an array * with the same dimensions */ diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Sum.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Sum.php index 1a797c8..56b0861 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Sum.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Sum.php @@ -66,8 +66,8 @@ public static function sumErroringStrings(...$args) $returnValue += (int) $arg; } elseif (ErrorValue::isError($arg)) { return $arg; - // ignore non-numerics from cell, but fail as literals (except null) } elseif ($arg !== null && !Functions::isCellValue($k)) { + // ignore non-numerics from cell, but fail as literals (except null) return ExcelError::VALUE(); } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical.php index 6758f47..6310ef3 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical.php @@ -15,8 +15,6 @@ /** * @deprecated 1.18.0 - * - * @codeCoverageIgnore */ class Statistical { @@ -953,7 +951,7 @@ public static function MAXA(...$args) * * @param mixed $args Data range and criterias * - * @return float + * @return null|float|string */ public static function MAXIFS(...$args) { @@ -1038,7 +1036,7 @@ public static function MINA(...$args) * * @param mixed $args Data range and criterias * - * @return float + * @return null|float|string */ public static function MINIFS(...$args) { @@ -1728,7 +1726,7 @@ public static function WEIBULL($value, $alpha, $beta, $cumulative) * Use the zTest() method in the Statistical\Distributions\StandardNormal class instead * @see Statistical\Distributions\StandardNormal::zTest() * - * @param float $dataSet + * @param mixed $dataSet * @param float $m0 Alpha Parameter * @param float $sigma Beta Parameter * diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Averages.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Averages.php index f2b5b2a..edb2984 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Averages.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Averages.php @@ -196,7 +196,7 @@ public static function mode(...$args) return $returnValue; } - protected static function filterArguments($args) + protected static function filterArguments(array $args): array { return array_filter( $args, @@ -207,11 +207,13 @@ function ($value) { ); } - // - // Special variant of array_count_values that isn't limited to strings and integers, - // but can work with floating point numbers as values - // - private static function modeCalc($data) + /** + * Special variant of array_count_values that isn't limited to strings and integers, + * but can work with floating point numbers as values. + * + * @return float|string + */ + private static function modeCalc(array $data) { $frequencyArray = []; $index = 0; diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Conditional.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Conditional.php index 5d40943..105db96 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Conditional.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Conditional.php @@ -187,7 +187,7 @@ public static function MINIFS(...$args) * @param mixed $sumRange * @param mixed $condition * - * @return float|string + * @return null|float|string */ public static function SUMIF($range, $condition, $sumRange = []) { @@ -223,6 +223,7 @@ public static function SUMIFS(...$args) return DSum::evaluate($database, self::VALUE_COLUMN_NAME, $conditions); } + /** @param array $args */ private static function buildConditionSet(...$args): array { $conditions = self::buildConditions(1, ...$args); @@ -231,6 +232,7 @@ private static function buildConditionSet(...$args): array return array_map(/** @scrutinizer ignore-type */ null, ...$conditions); } + /** @param array $args */ private static function buildConditionSetForValueRange(...$args): array { $conditions = self::buildConditions(2, ...$args); @@ -247,6 +249,7 @@ function ($value) { return array_map(/** @scrutinizer ignore-type */ null, ...$conditions); } + /** @param array $args */ private static function buildConditions(int $startOffset, ...$args): array { $conditions = []; @@ -261,6 +264,7 @@ private static function buildConditions(int $startOffset, ...$args): array return $conditions; } + /** @param array $args */ private static function buildDatabase(...$args): array { $database = []; @@ -268,6 +272,7 @@ private static function buildDatabase(...$args): array return self::buildDataSet(0, $database, ...$args); } + /** @param array $args */ private static function buildDatabaseWithValueRange(...$args): array { $database = []; @@ -279,6 +284,7 @@ private static function buildDatabaseWithValueRange(...$args): array return self::buildDataSet(1, $database, ...$args); } + /** @param array $args */ private static function buildDataSet(int $startOffset, array $database, ...$args): array { $pairCount = 1; diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/Beta.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/Beta.php index 8b41ac8..a88c105 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/Beta.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/Beta.php @@ -184,10 +184,13 @@ public static function incompleteBeta(float $x, float $p, float $q): float } // Function cache for logBeta function + /** @var float */ private static $logBetaCacheP = 0.0; + /** @var float */ private static $logBetaCacheQ = 0.0; + /** @var float */ private static $logBetaCacheResult = 0.0; /** diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/ChiSquared.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/ChiSquared.php index c874336..e0793a7 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/ChiSquared.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/ChiSquared.php @@ -11,8 +11,6 @@ class ChiSquared { use ArrayEnabled; - private const MAX_ITERATIONS = 256; - private const EPS = 2.22e-16; /** @@ -197,7 +195,7 @@ public static function test($actual, $expected) $rows = count($actual); $actual = Functions::flattenArray($actual); $expected = Functions::flattenArray($expected); - $columns = count($actual) / $rows; + $columns = intdiv(count($actual), $rows); $countActuals = count($actual); $countExpected = count($expected); @@ -261,12 +259,12 @@ private static function inverseLeftTailCalculation(float $probability, int $degr return $chi2; } - private static function pchisq($chi2, $degrees) + private static function pchisq(float $chi2, int $degrees): float { return self::gammp($degrees, 0.5 * $chi2); } - private static function gammp($n, $x) + private static function gammp(int $n, float $x): float { if ($x < 0.5 * $n + 1) { return self::gser($n, $x); @@ -279,7 +277,7 @@ private static function gammp($n, $x) // series representation. Algorithm from numerical recipe. // Assume that n is a positive integer and x>0, won't check arguments. // Relative error controlled by the eps parameter - private static function gser($n, $x) + private static function gser(int $n, float $x): float { /** @var float */ $gln = Gamma::ln($n / 2); @@ -303,7 +301,7 @@ private static function gser($n, $x) // its continued fraction representation. Algorithm from numerical recipe. // Assume that n is a postive integer and x>0, won't check arguments. // Relative error controlled by the eps parameter - private static function gcf($n, $x) + private static function gcf(int $n, float $x): float { /** @var float */ $gln = Gamma::ln($n / 2); diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/GammaBase.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/GammaBase.php index 8e6386e..ee826fc 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/GammaBase.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/GammaBase.php @@ -17,6 +17,7 @@ abstract class GammaBase private const MAX_ITERATIONS = 256; + /** @return float|string */ protected static function calculateDistribution(float $value, float $a, float $b, bool $cumulative) { if ($cumulative) { @@ -26,6 +27,7 @@ protected static function calculateDistribution(float $value, float $a, float $b return (1 / ($b ** $a * self::gammaValue($a))) * $value ** ($a - 1) * exp(0 - ($value / $b)); } + /** @return float|string */ protected static function calculateInverse(float $probability, float $alpha, float $beta) { $xLo = 0; @@ -38,6 +40,9 @@ protected static function calculateInverse(float $probability, float $alpha, flo while ((abs($dx) > Functions::PRECISION) && (++$i <= self::MAX_ITERATIONS)) { // Apply Newton-Raphson step $result = self::calculateDistribution($x, $alpha, $beta, true); + if (!is_float($result)) { + return ExcelError::NA(); + } $error = $result - $probability; if ($error == 0.0) { @@ -50,6 +55,9 @@ protected static function calculateInverse(float $probability, float $alpha, flo $pdf = self::calculateDistribution($x, $alpha, $beta, false); // Avoid division by zero + if (!is_float($pdf)) { + return ExcelError::NA(); + } if ($pdf !== 0.0) { $dx = $error / $pdf; $xNew = $x - $dx; @@ -209,8 +217,10 @@ public static function gammaValue(float $value): float private const PNT68 = 0.6796875; // Function cache for logGamma + /** @var float */ private static $logGammaCacheResult = 0.0; + /** @var float */ private static $logGammaCacheX = 0.0; /** @@ -292,7 +302,7 @@ public static function logGamma(float $x): float return $res; } - private static function logGamma1(float $y) + private static function logGamma1(float $y): float { // --------------------- // EPS .LT. X .LE. 1.5 @@ -325,7 +335,7 @@ private static function logGamma1(float $y) return $corr + $xm2 * (self::LG_D2 + $xm2 * ($xnum / $xden)); } - private static function logGamma2(float $y) + private static function logGamma2(float $y): float { // --------------------- // 1.5 .LT. X .LE. 4.0 @@ -341,7 +351,7 @@ private static function logGamma2(float $y) return $xm2 * (self::LG_D2 + $xm2 * ($xnum / $xden)); } - protected static function logGamma3(float $y) + protected static function logGamma3(float $y): float { // ---------------------- // 4.0 .LT. X .LE. 12.0 @@ -357,7 +367,7 @@ protected static function logGamma3(float $y) return self::LG_D4 + $xm4 * ($xnum / $xden); } - protected static function logGamma4(float $y) + protected static function logGamma4(float $y): float { // --------------------------------- // Evaluate for argument .GE. 12.0 diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/NewtonRaphson.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/NewtonRaphson.php index b994864..d301407 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/NewtonRaphson.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/NewtonRaphson.php @@ -9,6 +9,7 @@ class NewtonRaphson { private const MAX_ITERATIONS = 256; + /** @var callable */ protected $callback; public function __construct(callable $callback) @@ -16,6 +17,7 @@ public function __construct(callable $callback) $this->callback = $callback; } + /** @return float|string */ public function execute(float $probability) { $xLo = 100; diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/Normal.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/Normal.php index 67533c4..5715dac 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/Normal.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/Normal.php @@ -104,7 +104,7 @@ public static function inverse($probability, $mean, $stdDev) * email : nickersonm@yahoo.com * */ - private static function inverseNcdf($p) + private static function inverseNcdf(float $p): float { // Inverse ncdf approximation by Peter J. Acklam, implementation adapted to // PHP by Michael Nickerson, using Dr. Thomas Ziegler's C implementation as diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/StandardNormal.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/StandardNormal.php index a655fa7..2777d80 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/StandardNormal.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/StandardNormal.php @@ -146,6 +146,8 @@ public static function zTest($dataSet, $m0, $sigma = null) } $n = count($dataSet); - return 1 - self::cumulative((Averages::average($dataSet) - $m0) / ($sigma / sqrt($n))); + $sub1 = Averages::average($dataSet); + + return is_numeric($sub1) ? (1 - self::cumulative(($sub1 - $m0) / ($sigma / sqrt($n)))) : $sub1; } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/StudentT.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/StudentT.php index 8afc5c4..9d89af6 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/StudentT.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/StudentT.php @@ -11,8 +11,6 @@ class StudentT { use ArrayEnabled; - private const MAX_ITERATIONS = 256; - /** * TDIST. * diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/MaxMinBase.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/MaxMinBase.php index bd17b06..84726d5 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/MaxMinBase.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/MaxMinBase.php @@ -4,6 +4,11 @@ abstract class MaxMinBase { + /** + * @param mixed $value + * + * @return mixed + */ protected static function datatypeAdjustmentAllowStrings($value) { if (is_bool($value)) { diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Maximum.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Maximum.php index 3f8436f..304b44b 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Maximum.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Maximum.php @@ -3,6 +3,7 @@ namespace PhpOffice\PhpSpreadsheet\Calculation\Statistical; use PhpOffice\PhpSpreadsheet\Calculation\Functions; +use PhpOffice\PhpSpreadsheet\Calculation\Information\ErrorValue; class Maximum extends MaxMinBase { @@ -26,6 +27,11 @@ public static function max(...$args) // Loop through arguments $aArgs = Functions::flattenArray($args); foreach ($aArgs as $arg) { + if (ErrorValue::isError($arg)) { + $returnValue = $arg; + + break; + } // Is it a numeric value? if ((is_numeric($arg)) && (!is_string($arg))) { if (($returnValue === null) || ($arg > $returnValue)) { @@ -60,6 +66,11 @@ public static function maxA(...$args) // Loop through arguments $aArgs = Functions::flattenArray($args); foreach ($aArgs as $arg) { + if (ErrorValue::isError($arg)) { + $returnValue = $arg; + + break; + } // Is it a numeric value? if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) { $arg = self::datatypeAdjustmentAllowStrings($arg); diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Minimum.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Minimum.php index 596aad7..0dbbf3a 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Minimum.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Minimum.php @@ -3,6 +3,7 @@ namespace PhpOffice\PhpSpreadsheet\Calculation\Statistical; use PhpOffice\PhpSpreadsheet\Calculation\Functions; +use PhpOffice\PhpSpreadsheet\Calculation\Information\ErrorValue; class Minimum extends MaxMinBase { @@ -26,6 +27,11 @@ public static function min(...$args) // Loop through arguments $aArgs = Functions::flattenArray($args); foreach ($aArgs as $arg) { + if (ErrorValue::isError($arg)) { + $returnValue = $arg; + + break; + } // Is it a numeric value? if ((is_numeric($arg)) && (!is_string($arg))) { if (($returnValue === null) || ($arg < $returnValue)) { @@ -60,6 +66,11 @@ public static function minA(...$args) // Loop through arguments $aArgs = Functions::flattenArray($args); foreach ($aArgs as $arg) { + if (ErrorValue::isError($arg)) { + $returnValue = $arg; + + break; + } // Is it a numeric value? if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) { $arg = self::datatypeAdjustmentAllowStrings($arg); diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Percentiles.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Percentiles.php index 9973823..4565ca4 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Percentiles.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Percentiles.php @@ -110,7 +110,7 @@ public static function PERCENTRANK($valueSet, $value, $significance = 3) $pos += (($value - $valueSet[$pos]) / ($testValue - $valueSet[$pos])); } - return round($pos / $valueAdjustor, $significance); + return round(((float) $pos) / $valueAdjustor, $significance); } /** @@ -184,7 +184,7 @@ public static function RANK($value, $valueSet, $order = self::RANK_SORT_DESCENDI return ++$pos; } - protected static function percentileFilterValues(array $dataSet) + protected static function percentileFilterValues(array $dataSet): array { return array_filter( $dataSet, @@ -194,7 +194,7 @@ function ($value): bool { ); } - protected static function rankFilterValues(array $dataSet) + protected static function rankFilterValues(array $dataSet): array { return array_filter( $dataSet, diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Permutations.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Permutations.php index 5d9d304..b29356c 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Permutations.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Permutations.php @@ -46,7 +46,16 @@ public static function PERMUT($numObjs, $numInSet) if ($numObjs < $numInSet) { return ExcelError::NAN(); } - $result = round(MathTrig\Factorial::fact($numObjs) / MathTrig\Factorial::fact($numObjs - $numInSet)); + $result1 = MathTrig\Factorial::fact($numObjs); + if (is_string($result1)) { + return $result1; + } + $result2 = MathTrig\Factorial::fact($numObjs - $numInSet); + if (is_string($result2)) { + return $result2; + } + // phpstan thinks result1 and result2 can be arrays; they can't. + $result = round($result1 / $result2); // @phpstan-ignore-line return IntOrFloat::evaluate($result); } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Trends.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Trends.php index af73519..705de17 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Trends.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Trends.php @@ -21,6 +21,10 @@ private static function filterTrendValues(array &$array1, array &$array2): void } } + /** + * @param mixed $array1 should be array, but scalar is made into one + * @param mixed $array2 should be array, but scalar is made into one + */ private static function checkTrendArrays(&$array1, &$array2): void { if (!is_array($array1)) { @@ -168,7 +172,7 @@ public static function GROWTH($yValues, $xValues = [], $newValues = [], $const = $returnArray[0][] = [$bestFitExponential->getValueOfYForX($xValue)]; } - return $returnArray; + return $returnArray; //* @phpstan-ignore-line } /** @@ -425,6 +429,6 @@ public static function TREND($yValues, $xValues = [], $newValues = [], $const = $returnArray[0][] = [$bestFitLinear->getValueOfYForX($xValue)]; } - return $returnArray; + return $returnArray; //* @phpstan-ignore-line } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/VarianceBase.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/VarianceBase.php index e533467..25393fd 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/VarianceBase.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/VarianceBase.php @@ -6,6 +6,11 @@ abstract class VarianceBase { + /** + * @param mixed $value + * + * @return mixed + */ protected static function datatypeAdjustmentAllowStrings($value) { if (is_bool($value)) { @@ -17,6 +22,11 @@ protected static function datatypeAdjustmentAllowStrings($value) return $value; } + /** + * @param mixed $value + * + * @return mixed + */ protected static function datatypeAdjustmentBooleans($value) { if (is_bool($value) && (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE)) { diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData.php index 97f4629..7cc1c70 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData.php @@ -80,6 +80,8 @@ public static function ASCIICODE($characters) * Use the CONCATENATE() method in the TextData\Concatenate class instead * @see TextData\Concatenate::CONCATENATE() * + * @param array $args + * * @return string */ public static function CONCATENATE(...$args) diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Extract.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Extract.php index d3668f8..24ddff2 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Extract.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Extract.php @@ -37,7 +37,7 @@ public static function left($value, $chars = 1) return $e->getMessage(); } - return mb_substr($value ?? '', 0, $chars, 'UTF-8'); + return mb_substr($value, 0, $chars, 'UTF-8'); } /** @@ -68,7 +68,7 @@ public static function mid($value, $start, $chars) return $e->getMessage(); } - return mb_substr($value ?? '', --$start, $chars, 'UTF-8'); + return mb_substr($value, --$start, $chars, 'UTF-8'); } /** @@ -96,7 +96,7 @@ public static function right($value, $chars = 1) return $e->getMessage(); } - return mb_substr($value ?? '', mb_strlen($value ?? '', 'UTF-8') - $chars, $chars, 'UTF-8'); + return mb_substr($value, mb_strlen($value, 'UTF-8') - $chars, $chars, 'UTF-8'); } /** @@ -261,7 +261,7 @@ private static function buildDelimiter($delimiter): string $delimiter = Functions::flattenArray($delimiter); $quotedDelimiters = array_map( function ($delimiter) { - return preg_quote($delimiter ?? ''); + return preg_quote($delimiter ?? '', '/'); }, $delimiter ); @@ -270,7 +270,7 @@ function ($delimiter) { return '(' . $delimiters . ')'; } - return '(' . preg_quote($delimiter ?? '') . ')'; + return '(' . preg_quote($delimiter ?? '', '/') . ')'; } private static function matchFlags(int $matchMode): string diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Format.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Format.php index 93e7282..57d3316 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Format.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Format.php @@ -129,7 +129,7 @@ public static function TEXTFORMAT($value, $format) $format = Helpers::extractString($format); if (!is_numeric($value) && Date::isDateTimeFormatCode($format)) { - $value = DateTimeExcel\DateValue::fromString($value); + $value = DateTimeExcel\DateValue::fromString($value) + DateTimeExcel\TimeValue::fromString($value); } return (string) NumberFormat::toFormattedString($value, $format); @@ -140,7 +140,7 @@ public static function TEXTFORMAT($value, $format) * * @return mixed */ - private static function convertValue($value) + private static function convertValue($value, bool $spacesMeanZero = false) { $value = $value ?? 0; if (is_bool($value)) { @@ -150,6 +150,12 @@ private static function convertValue($value) throw new CalcExp(ExcelError::VALUE()); } } + if (is_string($value)) { + $value = trim($value); + if ($spacesMeanZero && $value === '') { + $value = 0; + } + } return $value; } @@ -181,6 +187,9 @@ public static function VALUE($value = '') '', trim($value, " \t\n\r\0\x0B" . StringHelper::getCurrencyCode()) ); + if ($numberValue === '') { + return ExcelError::VALUE(); + } if (is_numeric($numberValue)) { return (float) $numberValue; } @@ -277,7 +286,7 @@ public static function NUMBERVALUE($value = '', $decimalSeparator = null, $group } try { - $value = self::convertValue($value); + $value = self::convertValue($value, true); $decimalSeparator = self::getDecimalSeparator($decimalSeparator); $groupSeparator = self::getGroupSeparator($groupSeparator); } catch (CalcExp $e) { @@ -285,12 +294,12 @@ public static function NUMBERVALUE($value = '', $decimalSeparator = null, $group } if (!is_numeric($value)) { - $decimalPositions = preg_match_all('/' . preg_quote($decimalSeparator) . '/', $value, $matches, PREG_OFFSET_CAPTURE); + $decimalPositions = preg_match_all('/' . preg_quote($decimalSeparator, '/') . '/', $value, $matches, PREG_OFFSET_CAPTURE); if ($decimalPositions > 1) { return ExcelError::VALUE(); } - $decimalOffset = array_pop($matches[0])[1]; // @phpstan-ignore-line - if (strpos($value, $groupSeparator, $decimalOffset) !== false) { + $decimalOffset = array_pop($matches[0])[1] ?? null; + if ($decimalOffset === null || strpos($value, $groupSeparator, $decimalOffset) !== false) { return ExcelError::VALUE(); } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Text.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Text.php index 7b97f91..b8a7307 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Text.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Text.php @@ -29,7 +29,7 @@ public static function length($value = '') $value = Helpers::extractString($value); - return mb_strlen($value ?? '', 'UTF-8'); + return mb_strlen($value, 'UTF-8'); } /** @@ -193,7 +193,7 @@ private static function buildDelimiter($delimiter): string if (is_array($delimiter) && count($valueSet) > 1) { $quotedDelimiters = array_map( function ($delimiter) { - return preg_quote($delimiter ?? ''); + return preg_quote($delimiter ?? '', '/'); }, $valueSet ); @@ -202,7 +202,7 @@ function ($delimiter) { return '(' . $delimiters . ')'; } - return '(' . preg_quote(/** @scrutinizer ignore-type */ Functions::flattenSingleValue($delimiter)) . ')'; + return '(' . preg_quote(/** @scrutinizer ignore-type */ Functions::flattenSingleValue($delimiter), '/') . ')'; } private static function matchFlags(bool $matchMode): string diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/AddressRange.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/AddressRange.php index 5475231..614abe9 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/AddressRange.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/AddressRange.php @@ -8,6 +8,8 @@ interface AddressRange public const MAX_COLUMN = 'XFD'; + public const MAX_COLUMN_INT = 16384; + /** * @return mixed */ diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/AdvancedValueBinder.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/AdvancedValueBinder.php index 49631f7..c0fb387 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/AdvancedValueBinder.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/AdvancedValueBinder.php @@ -3,6 +3,7 @@ namespace PhpOffice\PhpSpreadsheet\Cell; use PhpOffice\PhpSpreadsheet\Calculation\Calculation; +use PhpOffice\PhpSpreadsheet\Calculation\Engine\FormattedNumber; use PhpOffice\PhpSpreadsheet\RichText\RichText; use PhpOffice\PhpSpreadsheet\Shared\Date; use PhpOffice\PhpSpreadsheet\Shared\StringHelper; @@ -33,11 +34,11 @@ public function bindValue(Cell $cell, $value = null) // Style logic - strings if ($dataType === DataType::TYPE_STRING && !$value instanceof RichText) { // Test for booleans using locale-setting - if ($value == Calculation::getTRUE()) { + if (StringHelper::strToUpper($value) === Calculation::getTRUE()) { $cell->setValueExplicit(true, DataType::TYPE_BOOL); return true; - } elseif ($value == Calculation::getFALSE()) { + } elseif (StringHelper::strToUpper($value) === Calculation::getFALSE()) { $cell->setValueExplicit(false, DataType::TYPE_BOOL); return true; @@ -50,35 +51,23 @@ public function bindValue(Cell $cell, $value = null) return $this->setImproperFraction($matches, $cell); } + $decimalSeparatorNoPreg = StringHelper::getDecimalSeparator(); + $decimalSeparator = preg_quote($decimalSeparatorNoPreg, '/'); + $thousandsSeparator = preg_quote(StringHelper::getThousandsSeparator(), '/'); + // Check for percentage - if (preg_match('/^\-?\d*\.?\d*\s?\%$/', $value)) { - return $this->setPercentage($value, $cell); + if (preg_match('/^\-?\d*' . $decimalSeparator . '?\d*\s?\%$/', preg_replace('/(\d)' . $thousandsSeparator . '(\d)/u', '$1$2', $value))) { + return $this->setPercentage(preg_replace('/(\d)' . $thousandsSeparator . '(\d)/u', '$1$2', $value), $cell); } // Check for currency - $currencyCode = StringHelper::getCurrencyCode(); - $decimalSeparator = StringHelper::getDecimalSeparator(); - $thousandsSeparator = StringHelper::getThousandsSeparator(); - if (preg_match('/^' . preg_quote($currencyCode, '/') . ' *(\d{1,3}(' . preg_quote($thousandsSeparator, '/') . '\d{3})*|(\d+))(' . preg_quote($decimalSeparator, '/') . '\d{2})?$/', $value)) { + if (preg_match(FormattedNumber::currencyMatcherRegexp(), preg_replace('/(\d)' . $thousandsSeparator . '(\d)/u', '$1$2', $value), $matches, PREG_UNMATCHED_AS_NULL)) { // Convert value to number - $value = (float) trim(str_replace([$currencyCode, $thousandsSeparator, $decimalSeparator], ['', '', '.'], $value)); - $cell->setValueExplicit($value, DataType::TYPE_NUMERIC); - // Set style - $cell->getWorksheet()->getStyle($cell->getCoordinate()) - ->getNumberFormat()->setFormatCode( - str_replace('$', $currencyCode, NumberFormat::FORMAT_CURRENCY_USD_SIMPLE) - ); + $sign = ($matches['PrefixedSign'] ?? $matches['PrefixedSign2'] ?? $matches['PostfixedSign']) ?? null; + $currencyCode = $matches['PrefixedCurrency'] ?? $matches['PostfixedCurrency']; + $value = (float) ($sign . trim(str_replace([$decimalSeparatorNoPreg, $currencyCode, ' ', '-'], ['.', '', '', ''], preg_replace('/(\d)' . $thousandsSeparator . '(\d)/u', '$1$2', $value)))); // @phpstan-ignore-line - return true; - } elseif (preg_match('/^\$ *(\d{1,3}(\,\d{3})*|(\d+))(\.\d{2})?$/', $value)) { - // Convert value to number - $value = (float) trim(str_replace(['$', ','], '', $value)); - $cell->setValueExplicit($value, DataType::TYPE_NUMERIC); - // Set style - $cell->getWorksheet()->getStyle($cell->getCoordinate()) - ->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_CURRENCY_USD_SIMPLE); - - return true; + return $this->setCurrency($value, $cell, $currencyCode); // @phpstan-ignore-line } // Check for time without seconds e.g. '9:45', '09:45' @@ -175,6 +164,18 @@ protected function setPercentage(string $value, Cell $cell): bool return true; } + protected function setCurrency(float $value, Cell $cell, string $currencyCode): bool + { + $cell->setValueExplicit($value, DataType::TYPE_NUMERIC); + // Set style + $cell->getWorksheet()->getStyle($cell->getCoordinate()) + ->getNumberFormat()->setFormatCode( + str_replace('$', '[$' . $currencyCode . ']', NumberFormat::FORMAT_CURRENCY_USD) + ); + + return true; + } + protected function setTimeHoursMinutes(string $value, Cell $cell): bool { // Convert value to number diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/Cell.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/Cell.php index 58a39af..e9e41d7 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/Cell.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/Cell.php @@ -71,6 +71,9 @@ class Cell */ private $formulaAttributes; + /** @var IgnoredErrors */ + private $ignoredErrors; + /** * Update the cell into the cell collection. * @@ -119,6 +122,7 @@ public function __construct($value, ?string $dataType, Worksheet $worksheet) } elseif (self::getValueBinder()->bindValue($this, $value) === false) { throw new Exception('Value could not be bound to cell.'); } + $this->ignoredErrors = new IgnoredErrors(); } /** @@ -196,9 +200,9 @@ public function getFormattedValue(): string * @param mixed $oldValue * @param mixed $newValue */ - protected static function updateIfCellIsTableHeader(Worksheet $workSheet, self $cell, $oldValue, $newValue): void + protected static function updateIfCellIsTableHeader(?Worksheet $workSheet, self $cell, $oldValue, $newValue): void { - if (StringHelper::strToLower($oldValue ?? '') === StringHelper::strToLower($newValue ?? '')) { + if (StringHelper::strToLower($oldValue ?? '') === StringHelper::strToLower($newValue ?? '') || $workSheet === null) { return; } @@ -221,12 +225,16 @@ protected static function updateIfCellIsTableHeader(Worksheet $workSheet, self $ * Sets the value for a cell, automatically determining the datatype using the value binder * * @param mixed $value Value + * @param null|IValueBinder $binder Value Binder to override the currently set Value Binder + * + * @throws Exception * * @return $this */ - public function setValue($value): self + public function setValue($value, ?IValueBinder $binder = null): self { - if (!self::getValueBinder()->bindValue($this, $value)) { + $binder ??= self::getValueBinder(); + if (!$binder->bindValue($this, $value)) { throw new Exception('Value could not be bound to cell.'); } @@ -365,14 +373,14 @@ public function getCalculatedValue(bool $resetLog = true) { if ($this->dataType === DataType::TYPE_FORMULA) { try { - $index = $this->getWorksheet()->getParent()->getActiveSheetIndex(); + $index = $this->getWorksheet()->getParentOrThrow()->getActiveSheetIndex(); $selected = $this->getWorksheet()->getSelectedCells(); $result = Calculation::getInstance( $this->getWorksheet()->getParent() )->calculateCellValue($this, $resetLog); $result = $this->convertDateTimeInt($result); $this->getWorksheet()->setSelectedCells($selected); - $this->getWorksheet()->getParent()->setActiveSheetIndex($index); + $this->getWorksheet()->getParentOrThrow()->setActiveSheetIndex($index); // We don't yet handle array returns if (is_array($result)) { while (is_array($result)) { @@ -387,7 +395,9 @@ public function getCalculatedValue(bool $resetLog = true) } throw new \PhpOffice\PhpSpreadsheet\Calculation\Exception( - $this->getWorksheet()->getTitle() . '!' . $this->getCoordinate() . ' -> ' . $ex->getMessage() + $this->getWorksheet()->getTitle() . '!' . $this->getCoordinate() . ' -> ' . $ex->getMessage(), + $ex->getCode(), + $ex ); } @@ -790,4 +800,9 @@ public function __toString() { return (string) $this->getValue(); } + + public function getIgnoredErrors(): IgnoredErrors + { + return $this->ignoredErrors; + } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/Coordinate.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/Coordinate.php index 89b4768..db1d06d 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/Coordinate.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/Coordinate.php @@ -263,7 +263,7 @@ public static function getRangeBoundaries($range) /** * Column index from string. * - * @param string $columnAddress eg 'A' + * @param ?string $columnAddress eg 'A' * * @return int Column index (A = 1) */ @@ -273,6 +273,7 @@ public static function columnIndexFromString($columnAddress) // caching using a static within the method is faster than a class static, // though it's additional memory overhead static $indexCache = []; + $columnAddress = $columnAddress ?? ''; if (isset($indexCache[$columnAddress])) { return $indexCache[$columnAddress]; @@ -460,7 +461,7 @@ private static function getReferencesForCellBlock($cellBlock) $currentColumnIndex = $startColumnIndex; $currentRow = $startRow; - self::validateRange($cellBlock, $startColumnIndex, $endColumnIndex, $currentRow, $endRow); + self::validateRange($cellBlock, $startColumnIndex, $endColumnIndex, (int) $currentRow, (int) $endRow); // Loop cells while ($currentColumnIndex < $endColumnIndex) { @@ -507,7 +508,7 @@ public static function mergeRangesInCollection(array $coordinateCollection) [$column, $row] = self::coordinateFromString($coord); $row = (int) (ltrim($row, '$')); - $hashCode = $column . '-' . (is_object($value) ? $value->getHashCode() : $value); + $hashCode = $column . '-' . ((is_object($value) && method_exists($value, 'getHashCode')) ? $value->getHashCode() : $value); if (!isset($hashedValues[$hashCode])) { $hashedValues[$hashCode] = (object) [ diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/DataValidator.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/DataValidator.php index 0e395a7..692f316 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/DataValidator.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/DataValidator.php @@ -20,7 +20,7 @@ class DataValidator */ public function isValid(Cell $cell) { - if (!$cell->hasDataValidation()) { + if (!$cell->hasDataValidation() || $cell->getDataValidation()->getType() === DataValidation::TYPE_NONE) { return true; } @@ -31,13 +31,55 @@ public function isValid(Cell $cell) return false; } - // TODO: write check on all cases - switch ($dataValidation->getType()) { - case DataValidation::TYPE_LIST: - return $this->isValueInList($cell); + $returnValue = false; + $type = $dataValidation->getType(); + if ($type === DataValidation::TYPE_LIST) { + $returnValue = $this->isValueInList($cell); + } elseif ($type === DataValidation::TYPE_WHOLE) { + if (!is_numeric($cellValue) || fmod((float) $cellValue, 1) != 0) { + $returnValue = false; + } else { + $returnValue = $this->numericOperator($dataValidation, (int) $cellValue); + } + } elseif ($type === DataValidation::TYPE_DECIMAL || $type === DataValidation::TYPE_DATE || $type === DataValidation::TYPE_TIME) { + if (!is_numeric($cellValue)) { + $returnValue = false; + } else { + $returnValue = $this->numericOperator($dataValidation, (float) $cellValue); + } + } elseif ($type === DataValidation::TYPE_TEXTLENGTH) { + $returnValue = $this->numericOperator($dataValidation, mb_strlen((string) $cellValue)); + } + + return $returnValue; + } + + /** @param float|int $cellValue */ + private function numericOperator(DataValidation $dataValidation, $cellValue): bool + { + $operator = $dataValidation->getOperator(); + $formula1 = $dataValidation->getFormula1(); + $formula2 = $dataValidation->getFormula2(); + $returnValue = false; + if ($operator === DataValidation::OPERATOR_BETWEEN) { + $returnValue = $cellValue >= $formula1 && $cellValue <= $formula2; + } elseif ($operator === DataValidation::OPERATOR_NOTBETWEEN) { + $returnValue = $cellValue < $formula1 || $cellValue > $formula2; + } elseif ($operator === DataValidation::OPERATOR_EQUAL) { + $returnValue = $cellValue == $formula1; + } elseif ($operator === DataValidation::OPERATOR_NOTEQUAL) { + $returnValue = $cellValue != $formula1; + } elseif ($operator === DataValidation::OPERATOR_LESSTHAN) { + $returnValue = $cellValue < $formula1; + } elseif ($operator === DataValidation::OPERATOR_LESSTHANOREQUAL) { + $returnValue = $cellValue <= $formula1; + } elseif ($operator === DataValidation::OPERATOR_GREATERTHAN) { + $returnValue = $cellValue > $formula1; + } elseif ($operator === DataValidation::OPERATOR_GREATERTHANOREQUAL) { + $returnValue = $cellValue >= $formula1; } - return false; + return $returnValue; } /** diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/IgnoredErrors.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/IgnoredErrors.php new file mode 100644 index 0000000..ee4b515 --- /dev/null +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/IgnoredErrors.php @@ -0,0 +1,66 @@ +numberStoredAsText = $value; + + return $this; + } + + public function getNumberStoredAsText(): bool + { + return $this->numberStoredAsText; + } + + public function setFormula(bool $value): self + { + $this->formula = $value; + + return $this; + } + + public function getFormula(): bool + { + return $this->formula; + } + + public function setTwoDigitTextYear(bool $value): self + { + $this->twoDigitTextYear = $value; + + return $this; + } + + public function getTwoDigitTextYear(): bool + { + return $this->twoDigitTextYear; + } + + public function setEvalError(bool $value): self + { + $this->evalError = $value; + + return $this; + } + + public function getEvalError(): bool + { + return $this->evalError; + } +} diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/CellReferenceHelper.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/CellReferenceHelper.php index bf4e295..0e16454 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/CellReferenceHelper.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/CellReferenceHelper.php @@ -116,10 +116,9 @@ public function cellAddressInDeleteRange(string $cellAddress): bool protected function updateColumnReference(int $newColumnIndex, string $absoluteColumn): string { - $newColumn = Coordinate::stringFromColumnIndex($newColumnIndex + $this->numberOfColumns); - $newColumn = ($newColumn > AddressRange::MAX_COLUMN) ? AddressRange::MAX_COLUMN : $newColumn; + $newColumn = Coordinate::stringFromColumnIndex(min($newColumnIndex + $this->numberOfColumns, AddressRange::MAX_COLUMN_INT)); - return $absoluteColumn . $newColumn; + return "{$absoluteColumn}{$newColumn}"; } protected function updateRowReference(int $newRowIndex, string $absoluteRow): string @@ -127,6 +126,6 @@ protected function updateRowReference(int $newRowIndex, string $absoluteRow): st $newRow = $newRowIndex + $this->numberOfRows; $newRow = ($newRow > AddressRange::MAX_ROW) ? AddressRange::MAX_ROW : $newRow; - return $absoluteRow . (string) $newRow; + return "{$absoluteRow}{$newRow}"; } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Axis.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Axis.php index ade7b99..3d48134 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Axis.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Axis.php @@ -52,6 +52,9 @@ public function __construct() /** @var string */ private $axisType = ''; + /** @var ?AxisText */ + private $axisText; + /** * Axis Options. * @@ -88,6 +91,9 @@ public function __construct() Properties::FORMAT_CODE_DATE_ISO8601, ]; + /** @var bool */ + private $noFill = false; + /** * Get Series Data Type. * @@ -183,6 +189,14 @@ public function setAxisOptionsProperties( */ public function getAxisOptionsProperty($property) { + if ($property === 'textRotation') { + if ($this->axisText !== null) { + if ($this->axisText->getRotation() !== null) { + return (string) $this->axisText->getRotation(); + } + } + } + return $this->axisOptions[$property]; } @@ -295,4 +309,28 @@ public function setMinorGridlines(?GridLines $gridlines): self return $this; } + + public function getAxisText(): ?AxisText + { + return $this->axisText; + } + + public function setAxisText(?AxisText $axisText): self + { + $this->axisText = $axisText; + + return $this; + } + + public function setNoFill(bool $noFill): self + { + $this->noFill = $noFill; + + return $this; + } + + public function getNoFill(): bool + { + return $this->noFill; + } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/AxisText.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/AxisText.php new file mode 100644 index 0000000..cd9ba2c --- /dev/null +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/AxisText.php @@ -0,0 +1,56 @@ +font = new Font(); + $this->font->setSize(null, true); + } + + public function setRotation(?int $rotation): self + { + $this->rotation = $rotation; + + return $this; + } + + public function getRotation(): ?int + { + return $this->rotation; + } + + public function getFillColorObject(): ChartColor + { + $fillColor = $this->font->getChartColor(); + if ($fillColor === null) { + $fillColor = new ChartColor(); + $this->font->setChartColorFromObject($fillColor); + } + + return $fillColor; + } + + public function getFont(): Font + { + return $this->font; + } + + public function setFont(Font $font): self + { + $this->font = $font; + + return $this; + } +} diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Chart.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Chart.php index 2ff22a3..38c69a4 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Chart.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Chart.php @@ -150,6 +150,12 @@ class Chart /** @var bool */ private $roundedCorners = false; + /** @var GridLines */ + private $borderLines; + + /** @var ChartColor */ + private $fillColor; + /** * Create a new Chart. * majorGridlines and minorGridlines are deprecated, moved to Axis. @@ -176,6 +182,8 @@ public function __construct($name, ?Title $title = null, ?Legend $legend = null, if ($minorGridlines !== null) { $this->yAxis->setMinorGridlines($minorGridlines); } + $this->fillColor = new ChartColor(); + $this->borderLines = new GridLines(); } /** @@ -786,4 +794,21 @@ public function setRoundedCorners(?bool $roundedCorners): self return $this; } + + public function getBorderLines(): GridLines + { + return $this->borderLines; + } + + public function setBorderLines(GridLines $borderLines): self + { + $this->borderLines = $borderLines; + + return $this; + } + + public function getFillColor(): ChartColor + { + return $this->fillColor; + } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Layout.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Layout.php index 0018d79..ac36c25 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Layout.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Layout.php @@ -2,6 +2,8 @@ namespace PhpOffice\PhpSpreadsheet\Chart; +use PhpOffice\PhpSpreadsheet\Style\Font; + class Layout { /** @@ -127,8 +129,11 @@ class Layout /** @var ?ChartColor */ private $labelBorderColor; - /** @var ?ChartColor */ - private $labelFontColor; + /** @var ?Font */ + private $labelFont; + + /** @var Properties */ + private $labelEffects; /** * Create a new Layout. @@ -172,7 +177,18 @@ public function __construct(array $layout = []) $this->initBoolean($layout, 'numFmtLinked'); $this->initColor($layout, 'labelFillColor'); $this->initColor($layout, 'labelBorderColor'); - $this->initColor($layout, 'labelFontColor'); + $labelFont = $layout['labelFont'] ?? null; + if ($labelFont instanceof Font) { + $this->labelFont = $labelFont; + } + $labelFontColor = $layout['labelFontColor'] ?? null; + if ($labelFontColor instanceof ChartColor) { + $this->setLabelFontColor($labelFontColor); + } + $labelEffects = $layout['labelEffects'] ?? null; + if ($labelEffects instanceof Properties) { + $this->labelEffects = $labelEffects; + } } private function initBoolean(array $layout, string $name): void @@ -493,14 +509,32 @@ public function setLabelBorderColor(?ChartColor $chartColor): self return $this; } + public function getLabelFont(): ?Font + { + return $this->labelFont; + } + + public function getLabelEffects(): ?Properties + { + return $this->labelEffects; + } + public function getLabelFontColor(): ?ChartColor { - return $this->labelFontColor; + if ($this->labelFont === null) { + return null; + } + + return $this->labelFont->getChartColor(); } public function setLabelFontColor(?ChartColor $chartColor): self { - $this->labelFontColor = $chartColor; + if ($this->labelFont === null) { + $this->labelFont = new Font(); + $this->labelFont->setSize(null, true); + } + $this->labelFont->setChartColorFromObject($chartColor); return $this; } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Legend.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Legend.php index e499e77..04040ae 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Legend.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Legend.php @@ -48,10 +48,20 @@ class Legend */ private $layout; + /** @var GridLines */ + private $borderLines; + + /** @var ChartColor */ + private $fillColor; + + /** @var ?AxisText */ + private $legendText; + /** * Create a new Legend. * * @param string $position + * @param ?Layout $layout * @param bool $overlay */ public function __construct($position = self::POSITION_RIGHT, ?Layout $layout = null, $overlay = false) @@ -59,6 +69,13 @@ public function __construct($position = self::POSITION_RIGHT, ?Layout $layout = $this->setPosition($position); $this->layout = $layout; $this->setOverlay($overlay); + $this->borderLines = new GridLines(); + $this->fillColor = new ChartColor(); + } + + public function getFillColor(): ChartColor + { + return $this->fillColor; } /** @@ -147,4 +164,28 @@ public function getLayout() { return $this->layout; } + + public function getLegendText(): ?AxisText + { + return $this->legendText; + } + + public function setLegendText(?AxisText $legendText): self + { + $this->legendText = $legendText; + + return $this; + } + + public function getBorderLines(): GridLines + { + return $this->borderLines; + } + + public function setBorderLines(GridLines $borderLines): self + { + $this->borderLines = $borderLines; + + return $this; + } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/PlotArea.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/PlotArea.php index ccde4bb..2b78d9a 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/PlotArea.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/PlotArea.php @@ -163,4 +163,49 @@ public function getGradientFillStops() { return $this->gradientFillStops; } + + /** @var ?int */ + private $gapWidth; + + /** @var bool */ + private $useUpBars = false; + + /** @var bool */ + private $useDownBars = false; + + public function getGapWidth(): ?int + { + return $this->gapWidth; + } + + public function setGapWidth(?int $gapWidth): self + { + $this->gapWidth = $gapWidth; + + return $this; + } + + public function getUseUpBars(): bool + { + return $this->useUpBars; + } + + public function setUseUpBars(bool $useUpBars): self + { + $this->useUpBars = $useUpBars; + + return $this; + } + + public function getUseDownBars(): bool + { + return $this->useDownBars; + } + + public function setUseDownBars(bool $useDownBars): self + { + $this->useDownBars = $useDownBars; + + return $this; + } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/JpGraphRendererBase.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/JpGraphRendererBase.php index cb9b544..d676f1d 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/JpGraphRendererBase.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/JpGraphRendererBase.php @@ -434,12 +434,33 @@ private function renderPlotScatter($groupID, $bubble): void // Loop through each data series in turn for ($i = 0; $i < $seriesCount; ++$i) { - $dataValuesY = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues(); + $plotCategoryByIndex = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i); + if ($plotCategoryByIndex === false) { + $plotCategoryByIndex = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0); + } + $dataValuesY = $plotCategoryByIndex->getDataValues(); $dataValuesX = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues(); - foreach ($dataValuesY as $k => $dataValueY) { - $dataValuesY[$k] = $k; + $redoDataValuesY = true; + if ($bubble) { + if (!$bubbleSize) { + $bubbleSize = '10'; + } + $redoDataValuesY = false; + foreach ($dataValuesY as $dataValueY) { + if (!is_int($dataValueY) && !is_float($dataValueY)) { + $redoDataValuesY = true; + + break; + } + } + } + if ($redoDataValuesY) { + foreach ($dataValuesY as $k => $dataValueY) { + $dataValuesY[$k] = $k; + } } + //var_dump($dataValuesY, $dataValuesX, $bubbleSize); $seriesPlot = new ScatterPlot($dataValuesX, $dataValuesY); if ($scatterStyle == 'lineMarker') { @@ -483,7 +504,7 @@ private function renderPlotRadar($groupID): void $dataValues = []; foreach ($dataValuesY as $k => $dataValueY) { - $dataValues[$k] = implode(' ', array_reverse($dataValueY)); + $dataValues[$k] = is_array($dataValueY) ? implode(' ', array_reverse($dataValueY)) : $dataValueY; } $tmp = array_shift($dataValues); $dataValues[] = $tmp; diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/MtJpGraphRenderer.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/MtJpGraphRenderer.php index e1f0f90..b5e70d3 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/MtJpGraphRenderer.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/MtJpGraphRenderer.php @@ -3,12 +3,12 @@ namespace PhpOffice\PhpSpreadsheet\Chart\Renderer; /** - * Jpgraph is not oficially maintained in Composer. + * Jpgraph is not officially maintained by Composer at packagist.org. * * This renderer implementation uses package * https://packagist.org/packages/mitoteam/jpgraph * - * This package is up to date for August 2022 and has PHP 8.1 support. + * This package is up to date for June 2023 and has PHP 8.2 support. */ class MtJpGraphRenderer extends JpGraphRendererBase { @@ -29,7 +29,7 @@ protected static function init(): void 'regstat', 'scatter', 'stock', - ]); + ], true); // enable Extended mode $loaded = true; } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Title.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Title.php index 9b0540d..9c99cca 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Title.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Title.php @@ -13,6 +13,13 @@ class Title */ private $caption = ''; + /** + * Allow overlay of other elements? + * + * @var bool + */ + private $overlay = true; + /** * Title Layout. * @@ -24,11 +31,14 @@ class Title * Create a new Title. * * @param array|RichText|string $caption + * @param ?Layout $layout + * @param bool $overlay */ - public function __construct($caption = '', ?Layout $layout = null) + public function __construct($caption = '', ?Layout $layout = null, $overlay = false) { $this->caption = $caption; $this->layout = $layout; + $this->setOverlay($overlay); } /** @@ -78,6 +88,26 @@ public function setCaption($caption) return $this; } + /** + * Get allow overlay of other elements? + * + * @return bool + */ + public function getOverlay() + { + return $this->overlay; + } + + /** + * Set allow overlay of other elements? + * + * @param bool $overlay + */ + public function setOverlay($overlay): void + { + $this->overlay = $overlay; + } + public function getLayout(): ?Layout { return $this->layout; diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/DefinedName.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/DefinedName.php index 0f4df26..07433b1 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/DefinedName.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/DefinedName.php @@ -18,7 +18,7 @@ abstract class DefinedName /** * Worksheet on which the defined name can be resolved. * - * @var Worksheet + * @var ?Worksheet */ protected $worksheet; @@ -39,7 +39,7 @@ abstract class DefinedName /** * Scope. * - * @var Worksheet + * @var ?Worksheet */ protected $scope; @@ -141,17 +141,19 @@ public function setName(string $name): self // Re-attach if ($this->worksheet !== null) { - $this->worksheet->getParent()->removeNamedRange($this->name, $this->worksheet); + $this->worksheet->getParentOrThrow()->removeNamedRange($this->name, $this->worksheet); } $this->name = $name; if ($this->worksheet !== null) { - $this->worksheet->getParent()->addNamedRange($this); + $this->worksheet->getParentOrThrow()->addDefinedName($this); } - // New title - $newTitle = $this->name; - ReferenceHelper::getInstance()->updateNamedFormulae($this->worksheet->getParent(), $oldTitle, $newTitle); + if ($this->worksheet !== null) { + // New title + $newTitle = $this->name; + ReferenceHelper::getInstance()->updateNamedFormulae($this->worksheet->getParentOrThrow(), $oldTitle, $newTitle); + } } return $this; @@ -247,13 +249,13 @@ public static function resolveName(string $definedName, Worksheet $worksheet, st if ($sheetName === '') { $worksheet2 = $worksheet; } else { - $worksheet2 = $worksheet->getParent()->getSheetByName($sheetName); + $worksheet2 = $worksheet->getParentOrThrow()->getSheetByName($sheetName); if ($worksheet2 === null) { return null; } } - return $worksheet->getParent()->getDefinedName($definedName, $worksheet2); + return $worksheet->getParentOrThrow()->getDefinedName($definedName, $worksheet2); } /** diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Document/Properties.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Document/Properties.php index afdeea9..302afee 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Document/Properties.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Document/Properties.php @@ -107,6 +107,8 @@ class Properties */ private $customProperties = []; + private string $hyperlinkBase = ''; + /** * Create a new Document Properties instance. */ @@ -434,7 +436,7 @@ private function identifyPropertyType($propertyValue): string * * @param mixed $propertyValue * @param string $propertyType - * 'i' : Integer + * 'i' : Integer * 'f' : Floating Point * 's' : String * 'd' : Date/Time @@ -534,4 +536,16 @@ public static function convertPropertyType(string $propertyType): string { return self::PROPERTY_TYPE_ARRAY[$propertyType] ?? self::PROPERTY_TYPE_UNKNOWN; } + + public function getHyperlinkBase(): string + { + return $this->hyperlinkBase; + } + + public function setHyperlinkBase(string $hyperlinkBase): self + { + $this->hyperlinkBase = $hyperlinkBase; + + return $this; + } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Downloader.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Downloader.php new file mode 100644 index 0000000..e66ae42 --- /dev/null +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Downloader.php @@ -0,0 +1,89 @@ + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'xls' => 'application/vnd.ms-excel', + 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', + 'csv' => 'text/csv', + 'html' => 'text/html', + 'pdf' => 'application/pdf', + ]; + + public function __construct(string $folder, string $filename, ?string $filetype = null) + { + if ((is_dir($folder) === false) || (is_readable($folder) === false)) { + throw new Exception("Folder {$folder} is not accessable"); + } + $filepath = "{$folder}/{$filename}"; + $this->filepath = (string) realpath($filepath); + $this->filename = basename($filepath); + if ((file_exists($this->filepath) === false) || (is_readable($this->filepath) === false)) { + throw new Exception("{$this->filename} not found, or cannot be read"); + } + + $filetype ??= pathinfo($filename, PATHINFO_EXTENSION); + if (array_key_exists(strtolower($filetype), self::CONTENT_TYPES) === false) { + throw new Exception("Invalid filetype: {$filetype} cannot be downloaded"); + } + $this->filetype = strtolower($filetype); + } + + public function download(): void + { + $this->headers(); + + readfile($this->filepath); + } + + public function headers(): void + { + ob_clean(); + + $this->contentType(); + $this->contentDisposition(); + $this->cacheHeaders(); + $this->fileSize(); + + flush(); + } + + protected function contentType(): void + { + header('Content-Type: ' . self::CONTENT_TYPES[$this->filetype]); + } + + protected function contentDisposition(): void + { + header('Content-Disposition: attachment;filename="' . $this->filename . '"'); + } + + protected function cacheHeaders(): void + { + header('Cache-Control: max-age=0'); + // If you're serving to IE 9, then the following may be needed + header('Cache-Control: max-age=1'); + + // If you're serving to IE over SSL, then the following may be needed + header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past + header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); // always modified + header('Cache-Control: cache, must-revalidate'); // HTTP/1.1 + header('Pragma: public'); // HTTP/1.0 + } + + protected function fileSize(): void + { + header('Content-Length: ' . filesize($this->filepath)); + } +} diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Handler.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Handler.php new file mode 100644 index 0000000..d05197c --- /dev/null +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Handler.php @@ -0,0 +1,46 @@ +attributes; if ($attrs !== null) { @@ -737,72 +737,72 @@ private function startFontTag(DOMElement $tag): void } } - private function endFontTag(): void + protected function endFontTag(): void { $this->face = $this->size = $this->color = null; } - private function startBoldTag(): void + protected function startBoldTag(): void { $this->bold = true; } - private function endBoldTag(): void + protected function endBoldTag(): void { $this->bold = false; } - private function startItalicTag(): void + protected function startItalicTag(): void { $this->italic = true; } - private function endItalicTag(): void + protected function endItalicTag(): void { $this->italic = false; } - private function startUnderlineTag(): void + protected function startUnderlineTag(): void { $this->underline = true; } - private function endUnderlineTag(): void + protected function endUnderlineTag(): void { $this->underline = false; } - private function startSubscriptTag(): void + protected function startSubscriptTag(): void { $this->subscript = true; } - private function endSubscriptTag(): void + protected function endSubscriptTag(): void { $this->subscript = false; } - private function startSuperscriptTag(): void + protected function startSuperscriptTag(): void { $this->superscript = true; } - private function endSuperscriptTag(): void + protected function endSuperscriptTag(): void { $this->superscript = false; } - private function startStrikethruTag(): void + protected function startStrikethruTag(): void { $this->strikethrough = true; } - private function endStrikethruTag(): void + protected function endStrikethruTag(): void { $this->strikethrough = false; } - private function breakTag(): void + protected function breakTag(): void { $this->stringData .= "\n"; } @@ -826,8 +826,9 @@ private function handleCallback(DOMElement $element, $callbackTag, array $callba if (isset($callbacks[$callbackTag])) { $elementHandler = $callbacks[$callbackTag]; if (method_exists($this, $elementHandler)) { - /** @phpstan-ignore-next-line */ - call_user_func([$this, $elementHandler], $element); + /** @var callable */ + $callable = [$this, $elementHandler]; + call_user_func($callable, $element); } } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Sample.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Sample.php index 5ca546e..6244375 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Sample.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Sample.php @@ -2,7 +2,9 @@ namespace PhpOffice\PhpSpreadsheet\Helper; +use PhpOffice\PhpSpreadsheet\Chart\Chart; use PhpOffice\PhpSpreadsheet\IOFactory; +use PhpOffice\PhpSpreadsheet\Settings; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet; use PhpOffice\PhpSpreadsheet\Writer\IWriter; @@ -12,6 +14,7 @@ use ReflectionClass; use RegexIterator; use RuntimeException; +use Throwable; /** * Helper class to be used in sample code. @@ -120,7 +123,7 @@ public function getSamples() * @param string $filename * @param string[] $writers */ - public function write(Spreadsheet $spreadsheet, $filename, array $writers = ['Xlsx', 'Xls']): void + public function write(Spreadsheet $spreadsheet, $filename, array $writers = ['Xlsx', 'Xls'], bool $withCharts = false, ?callable $writerCallback = null): void { // Set active sheet index to the first sheet, so Excel opens this as the first sheet $spreadsheet->setActiveSheetIndex(0); @@ -129,9 +132,16 @@ public function write(Spreadsheet $spreadsheet, $filename, array $writers = ['Xl foreach ($writers as $writerType) { $path = $this->getFilename($filename, mb_strtolower($writerType)); $writer = IOFactory::createWriter($spreadsheet, $writerType); + $writer->setIncludeCharts($withCharts); + if ($writerCallback !== null) { + $writerCallback($writer); + } $callStartTime = microtime(true); $writer->save($path); $this->logWrite($writer, $path, /** @scrutinizer ignore-type */ $callStartTime); + if ($this->isCli() === false) { + echo 'Download ' . basename($path) . '
'; + } } $this->logEndingNotes(); @@ -147,7 +157,7 @@ protected function isDirOrMkdir(string $folder): bool * * @return string */ - private function getTemporaryFolder() + public function getTemporaryFolder() { $tempFolder = sys_get_temp_dir() . '/phpspreadsheet'; if (!$this->isDirOrMkdir($tempFolder)) { @@ -162,10 +172,8 @@ private function getTemporaryFolder() * * @param string $filename * @param string $extension - * - * @return string */ - public function getFilename($filename, $extension = 'xlsx') + public function getFilename($filename, $extension = 'xlsx'): string { $originalExtension = pathinfo($filename, PATHINFO_EXTENSION); @@ -195,7 +203,29 @@ public function getTemporaryFilename($extension = 'xlsx') public function log(string $message): void { $eol = $this->isCli() ? PHP_EOL : '
'; - echo date('H:i:s ') . $message . $eol; + echo($this->isCli() ? date('H:i:s ') : '') . $message . $eol; + } + + public function renderChart(Chart $chart, string $fileName): void + { + if ($this->isCli() === true) { + return; + } + + Settings::setChartRenderer(\PhpOffice\PhpSpreadsheet\Chart\Renderer\MtJpGraphRenderer::class); + + $fileName = $this->getFilename($fileName, 'png'); + + try { + $chart->render($fileName); + $this->log('Rendered image: ' . $fileName); + $imageData = file_get_contents($fileName); + if ($imageData !== false) { + echo '
'; + } + } catch (Throwable $e) { + $this->log('Error rendering chart: ' . $e->getMessage() . PHP_EOL); + } } public function titles(string $category, string $functionName, ?string $description = null): void @@ -246,7 +276,10 @@ public function logWrite(IWriter $writer, $path, $callStartTime): void $callTime = $callEndTime - $callStartTime; $reflection = new ReflectionClass($writer); $format = $reflection->getShortName(); - $message = "Write {$format} format to {$path} in " . sprintf('%.4f', $callTime) . ' seconds'; + + $message = ($this->isCli() === true) + ? "Write {$format} format to {$path} in " . sprintf('%.4f', $callTime) . ' seconds' + : "Write {$format} format to {$path} in " . sprintf('%.4f', $callTime) . ' seconds'; $this->log($message); } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/TextGrid.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/TextGrid.php index ed146a5..3a4a98f 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/TextGrid.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/TextGrid.php @@ -48,17 +48,17 @@ function (&$row): void { public function render(): string { - $this->gridDisplay = $this->isCli ? '' : ''; + $this->gridDisplay = $this->isCli ? '' : '
';
 
         $maxRow = max($this->rows);
-        $maxRowLength = strlen((string) $maxRow) + 1;
+        $maxRowLength = mb_strlen((string) $maxRow) + 1;
         $columnWidths = $this->getColumnWidths();
 
         $this->renderColumnHeader($maxRowLength, $columnWidths);
         $this->renderRows($maxRowLength, $columnWidths);
         $this->renderFooter($maxRowLength, $columnWidths);
 
-        $this->gridDisplay .= $this->isCli ? '' : '';
+        $this->gridDisplay .= $this->isCli ? '' : '
'; return $this->gridDisplay; } @@ -75,9 +75,9 @@ private function renderRows(int $maxRowLength, array $columnWidths): void private function renderCells(array $rowData, array $columnWidths): void { foreach ($rowData as $column => $cell) { - $cell = ($this->isCli) ? (string) $cell : htmlentities((string) $cell); + $displayCell = ($this->isCli) ? (string) $cell : htmlentities((string) $cell); $this->gridDisplay .= '| '; - $this->gridDisplay .= str_pad($cell, $columnWidths[$column] + 1, ' '); + $this->gridDisplay .= $displayCell . str_repeat(' ', $columnWidths[$column] - mb_strlen($cell ?? '') + 1); } } @@ -126,12 +126,12 @@ private function getColumnWidth(array $columnData): int foreach ($columnData as $columnValue) { if (is_string($columnValue)) { - $columnWidth = max($columnWidth, strlen($columnValue)); + $columnWidth = max($columnWidth, mb_strlen($columnValue)); } elseif (is_bool($columnValue)) { - $columnWidth = max($columnWidth, strlen($columnValue ? 'TRUE' : 'FALSE')); + $columnWidth = max($columnWidth, mb_strlen($columnValue ? 'TRUE' : 'FALSE')); } - $columnWidth = max($columnWidth, strlen((string) $columnWidth)); + $columnWidth = max($columnWidth, mb_strlen((string) $columnWidth)); } return $columnWidth; diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/IOFactory.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/IOFactory.php index e437a22..c088397 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/IOFactory.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/IOFactory.php @@ -30,6 +30,7 @@ abstract class IOFactory public const WRITER_CSV = 'Csv'; public const WRITER_HTML = 'Html'; + /** @var string[] */ private static $readers = [ self::READER_XLSX => Reader\Xlsx::class, self::READER_XLS => Reader\Xls::class, @@ -41,6 +42,7 @@ abstract class IOFactory self::READER_CSV => Reader\Csv::class, ]; + /** @var string[] */ private static $writers = [ self::WRITER_XLS => Writer\Xls::class, self::WRITER_XLSX => Writer\Xlsx::class, @@ -62,6 +64,7 @@ public static function createWriter(Spreadsheet $spreadsheet, string $writerType } // Instantiate writer + /** @var IWriter */ $className = self::$writers[$writerType]; return new $className($spreadsheet); @@ -77,6 +80,7 @@ public static function createReader(string $readerType): IReader } // Instantiate reader + /** @var IReader */ $className = self::$readers[$readerType]; return new $className(); @@ -88,7 +92,9 @@ public static function createReader(string $readerType): IReader * @param string $filename The name of the spreadsheet file * @param int $flags the optional second parameter flags may be used to identify specific elements * that should be loaded, but which won't be loaded by default, using these values: - * IReader::LOAD_WITH_CHARTS - Include any charts that are defined in the loaded file + * IReader::LOAD_WITH_CHARTS - Include any charts that are defined in the loaded file. + * IReader::READ_DATA_ONLY - Read cell values only, not formatting or merge structure. + * IReader::IGNORE_EMPTY_CELLS - Don't load empty cells into the model. * @param string[] $readers An array of Readers to use to identify the file type. By default, load() will try * all possible Readers until it finds a match; but this allows you to pass in a * list of Readers so it will only try the subset that you specify here. diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/BaseReader.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/BaseReader.php index 42268d6..aa380aa 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/BaseReader.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/BaseReader.php @@ -51,10 +51,11 @@ abstract class BaseReader implements IReader */ protected $readFilter; + /** @var resource */ protected $fileHandle; /** - * @var XmlScanner + * @var ?XmlScanner */ protected $securityScanner; @@ -134,11 +135,20 @@ public function setReadFilter(IReadFilter $readFilter) return $this; } - public function getSecurityScanner() + public function getSecurityScanner(): ?XmlScanner { return $this->securityScanner; } + public function getSecurityScannerOrThrow(): XmlScanner + { + if ($this->securityScanner === null) { + throw new ReaderException('Security scanner is unexpectedly null'); + } + + return $this->securityScanner; + } + protected function processFlags(int $flags): void { if (((bool) ($flags & self::LOAD_WITH_CHARTS)) === true) { @@ -147,7 +157,7 @@ protected function processFlags(int $flags): void if (((bool) ($flags & self::READ_DATA_ONLY)) === true) { $this->setReadDataOnly(true); } - if (((bool) ($flags & self::SKIP_EMPTY_CELLS)) === true) { + if (((bool) ($flags & self::SKIP_EMPTY_CELLS) || (bool) ($flags & self::IGNORE_EMPTY_CELLS)) === true) { $this->setReadEmptyCells(false); } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Csv.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Csv.php index 4f128d6..be9a2a3 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Csv.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Csv.php @@ -294,8 +294,9 @@ private function openFileOrMemory(string $filename): void if ($this->inputEncoding !== 'UTF-8') { fclose($this->fileHandle); $entireFile = file_get_contents($filename); - $this->fileHandle = fopen('php://memory', 'r+b'); - if ($this->fileHandle !== false && $entireFile !== false) { + $fileHandle = fopen('php://memory', 'r+b'); + if ($fileHandle !== false && $entireFile !== false) { + $this->fileHandle = $fileHandle; $data = StringHelper::convertEncoding($entireFile, 'UTF-8', $this->inputEncoding); fwrite($this->fileHandle, $data); $this->skipBOM(); diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Gnumeric.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Gnumeric.php index b33af24..99e4d6a 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Gnumeric.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Gnumeric.php @@ -80,17 +80,15 @@ public function __construct() */ public function canRead(string $filename): bool { - // Check if gzlib functions are available - if (File::testFileNoThrow($filename) && function_exists('gzread')) { - // Read signature data (first 3 bytes) - $fh = fopen($filename, 'rb'); - if ($fh !== false) { - $data = fread($fh, 2); - fclose($fh); + $data = null; + if (File::testFileNoThrow($filename)) { + $data = $this->gzfileGetContents($filename); + if (strpos($data, self::NAMESPACE_GNM) === false) { + $data = ''; } } - return isset($data) && $data === chr(0x1F) . chr(0x8B); + return !empty($data); } private static function matchXml(XMLReader $xml, string $expectedLocalName): bool @@ -110,9 +108,13 @@ private static function matchXml(XMLReader $xml, string $expectedLocalName): boo public function listWorksheetNames($filename) { File::assertFile($filename); + if (!$this->canRead($filename)) { + throw new Exception($filename . ' is an invalid Gnumeric file.'); + } $xml = new XMLReader(); - $xml->xml($this->securityScanner->scanFile('compress.zlib://' . realpath($filename)), null, Settings::getLibXmlLoaderOptions()); + $contents = $this->gzfileGetContents($filename); + $xml->xml($contents, null, Settings::getLibXmlLoaderOptions()); $xml->setParserProperty(2, true); $worksheetNames = []; @@ -139,9 +141,13 @@ public function listWorksheetNames($filename) public function listWorksheetInfo($filename) { File::assertFile($filename); + if (!$this->canRead($filename)) { + throw new Exception($filename . ' is an invalid Gnumeric file.'); + } $xml = new XMLReader(); - $xml->xml($this->securityScanner->scanFile('compress.zlib://' . realpath($filename)), null, Settings::getLibXmlLoaderOptions()); + $contents = $this->gzfileGetContents($filename); + $xml->xml($contents, null, Settings::getLibXmlLoaderOptions()); $xml->setParserProperty(2, true); $worksheetInfo = []; @@ -185,13 +191,23 @@ public function listWorksheetInfo($filename) */ private function gzfileGetContents($filename) { - $file = @gzopen($filename, 'rb'); $data = ''; - if ($file !== false) { - while (!gzeof($file)) { - $data .= gzread($file, 1024); + $contents = @file_get_contents($filename); + if ($contents !== false) { + if (substr($contents, 0, 2) === "\x1f\x8b") { + // Check if gzlib functions are available + if (function_exists('gzdecode')) { + $contents = @gzdecode($contents); + if ($contents !== false) { + $data = $contents; + } + } + } else { + $data = $contents; } - gzclose($file); + } + if ($data !== '') { + $data = $this->getSecurityScannerOrThrow()->scan($data); } return $data; @@ -245,10 +261,13 @@ public function loadIntoExisting(string $filename, Spreadsheet $spreadsheet): Sp { $this->spreadsheet = $spreadsheet; File::assertFile($filename); + if (!$this->canRead($filename)) { + throw new Exception($filename . ' is an invalid Gnumeric file.'); + } $gFileData = $this->gzfileGetContents($filename); - $xml2 = simplexml_load_string($this->securityScanner->scan($gFileData), 'SimpleXMLElement', Settings::getLibXmlLoaderOptions()); + $xml2 = simplexml_load_string($gFileData, 'SimpleXMLElement', Settings::getLibXmlLoaderOptions()); $xml = self::testSimpleXml($xml2); $gnmXML = $xml->children(self::NAMESPACE_GNM); diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Gnumeric/PageSetup.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Gnumeric/PageSetup.php index 204c730..0257fc9 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Gnumeric/PageSetup.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Gnumeric/PageSetup.php @@ -24,19 +24,30 @@ public function printInformation(SimpleXMLElement $sheet): self { if (isset($sheet->PrintInformation, $sheet->PrintInformation[0])) { $printInformation = $sheet->PrintInformation[0]; + $setup = $this->spreadsheet->getActiveSheet()->getPageSetup(); - $scale = (string) $printInformation->Scale->attributes()['percentage']; + $attributes = $printInformation->Scale->attributes(); + if (isset($attributes['percentage'])) { + $setup->setScale((int) $attributes['percentage']); + } $pageOrder = (string) $printInformation->order; + if ($pageOrder === 'r_then_d') { + $setup->setPageOrder(WorksheetPageSetup::PAGEORDER_OVER_THEN_DOWN); + } elseif ($pageOrder === 'd_then_r') { + $setup->setPageOrder(WorksheetPageSetup::PAGEORDER_DOWN_THEN_OVER); + } $orientation = (string) $printInformation->orientation; - $horizontalCentered = (string) $printInformation->hcenter->attributes()['value']; - $verticalCentered = (string) $printInformation->vcenter->attributes()['value']; - - $this->spreadsheet->getActiveSheet()->getPageSetup() - ->setPageOrder($pageOrder === 'r_then_d' ? WorksheetPageSetup::PAGEORDER_OVER_THEN_DOWN : WorksheetPageSetup::PAGEORDER_DOWN_THEN_OVER) - ->setScale((int) $scale) - ->setOrientation($orientation ?? WorksheetPageSetup::ORIENTATION_DEFAULT) - ->setHorizontalCentered((bool) $horizontalCentered) - ->setVerticalCentered((bool) $verticalCentered); + if ($orientation !== '') { + $setup->setOrientation($orientation); + } + $attributes = $printInformation->hcenter->attributes(); + if (isset($attributes['value'])) { + $setup->setHorizontalCentered((bool) (string) $attributes['value']); + } + $attributes = $printInformation->vcenter->attributes(); + if (isset($attributes['value'])) { + $setup->setVerticalCentered((bool) (string) $attributes['value']); + } } return $this; diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Html.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Html.php index 76f128e..bfb5240 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Html.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Html.php @@ -7,6 +7,8 @@ use DOMNode; use DOMText; use PhpOffice\PhpSpreadsheet\Cell\Coordinate; +use PhpOffice\PhpSpreadsheet\Cell\DataType; +use PhpOffice\PhpSpreadsheet\Document\Properties; use PhpOffice\PhpSpreadsheet\Helper\Dimension as CssDimension; use PhpOffice\PhpSpreadsheet\Reader\Security\XmlScanner; use PhpOffice\PhpSpreadsheet\Spreadsheet; @@ -283,15 +285,35 @@ protected function releaseTableStartColumn(): string * @param int|string $row * @param mixed $cellContent */ - protected function flushCell(Worksheet $sheet, $column, $row, &$cellContent): void + protected function flushCell(Worksheet $sheet, $column, $row, &$cellContent, array $attributeArray): void { if (is_string($cellContent)) { // Simple String content if (trim($cellContent) > '') { // Only actually write it if there's content in the string // Write to worksheet to be done here... - // ... we return the cell so we can mess about with styles more easily - $sheet->setCellValue($column . $row, $cellContent); + // ... we return the cell, so we can mess about with styles more easily + + // Set cell value explicitly if there is data-type attribute + if (isset($attributeArray['data-type'])) { + $datatype = $attributeArray['data-type']; + if (in_array($datatype, [DataType::TYPE_STRING, DataType::TYPE_STRING2, DataType::TYPE_INLINE])) { + //Prevent to Excel treat string with beginning equal sign or convert big numbers to scientific number + if (substr($cellContent, 0, 1) === '=') { + $sheet->getCell($column . $row) + ->getStyle() + ->setQuotePrefix(true); + } + } + //catching the Exception and ignoring the invalid data types + try { + $sheet->setCellValueExplicit($column . $row, $cellContent, $attributeArray['data-type']); + } catch (\PhpOffice\PhpSpreadsheet\Exception $exception) { + $sheet->setCellValue($column . $row, $cellContent); + } + } else { + $sheet->setCellValue($column . $row, $cellContent); + } $this->dataArray[$row][$column] = $cellContent; } } else { @@ -305,7 +327,7 @@ protected function flushCell(Worksheet $sheet, $column, $row, &$cellContent): vo private function processDomElementBody(Worksheet $sheet, int &$row, string &$column, string &$cellContent, DOMElement $child): void { $attributeArray = []; - foreach (($child->attributes ?? []) as $attribute) { + foreach ($child->attributes as $attribute) { $attributeArray[$attribute->name] = $attribute->value; } @@ -355,7 +377,7 @@ private function processDomElementSpanEtc(Worksheet $sheet, int &$row, string &$ private function processDomElementHr(Worksheet $sheet, int &$row, string &$column, string &$cellContent, DOMElement $child, array &$attributeArray): void { if ($child->nodeName === 'hr') { - $this->flushCell($sheet, $column, $row, $cellContent); + $this->flushCell($sheet, $column, $row, $cellContent, $attributeArray); ++$row; if (isset($this->formats[$child->nodeName])) { $sheet->getStyle($column . $row)->applyFromArray($this->formats[$child->nodeName]); @@ -375,7 +397,7 @@ private function processDomElementBr(Worksheet $sheet, int &$row, string &$colum $sheet->getStyle($column . $row)->getAlignment()->setWrapText(true); } else { // Otherwise flush our existing content and move the row cursor on - $this->flushCell($sheet, $column, $row, $cellContent); + $this->flushCell($sheet, $column, $row, $cellContent, $attributeArray); ++$row; } } else { @@ -421,11 +443,11 @@ private function processDomElementH1Etc(Worksheet $sheet, int &$row, string &$co $this->processDomElement($child, $sheet, $row, $column, $cellContent); } else { if ($cellContent > '') { - $this->flushCell($sheet, $column, $row, $cellContent); + $this->flushCell($sheet, $column, $row, $cellContent, $attributeArray); ++$row; } $this->processDomElement($child, $sheet, $row, $column, $cellContent); - $this->flushCell($sheet, $column, $row, $cellContent); + $this->flushCell($sheet, $column, $row, $cellContent, $attributeArray); if (isset($this->formats[$child->nodeName])) { $sheet->getStyle($column . $row)->applyFromArray($this->formats[$child->nodeName]); @@ -448,11 +470,11 @@ private function processDomElementLi(Worksheet $sheet, int &$row, string &$colum $this->processDomElement($child, $sheet, $row, $column, $cellContent); } else { if ($cellContent > '') { - $this->flushCell($sheet, $column, $row, $cellContent); + $this->flushCell($sheet, $column, $row, $cellContent, $attributeArray); } ++$row; $this->processDomElement($child, $sheet, $row, $column, $cellContent); - $this->flushCell($sheet, $column, $row, $cellContent); + $this->flushCell($sheet, $column, $row, $cellContent, $attributeArray); $column = 'A'; } } else { @@ -469,10 +491,13 @@ private function processDomElementImg(Worksheet $sheet, int &$row, string &$colu } } + private string $currentColumn = 'A'; + private function processDomElementTable(Worksheet $sheet, int &$row, string &$column, string &$cellContent, DOMElement $child, array &$attributeArray): void { if ($child->nodeName === 'table') { - $this->flushCell($sheet, $column, $row, $cellContent); + $this->currentColumn = 'A'; + $this->flushCell($sheet, $column, $row, $cellContent, $attributeArray); $column = $this->setTableStartColumn($column); if ($this->tableLevel > 1 && $row > 1) { --$row; @@ -491,7 +516,10 @@ private function processDomElementTable(Worksheet $sheet, int &$row, string &$co private function processDomElementTr(Worksheet $sheet, int &$row, string &$column, string &$cellContent, DOMElement $child, array &$attributeArray): void { - if ($child->nodeName === 'tr') { + if ($child->nodeName === 'col') { + $this->applyInlineStyle($sheet, -1, $this->currentColumn, $attributeArray); + ++$this->currentColumn; + } elseif ($child->nodeName === 'tr') { $column = $this->getTableStartColumn(); $cellContent = ''; $this->processDomElement($child, $sheet, $row, $column, $cellContent); @@ -574,7 +602,7 @@ private function processDomElementThTd(Worksheet $sheet, int &$row, string &$col // apply inline style $this->applyInlineStyle($sheet, $row, $column, $attributeArray); - $this->flushCell($sheet, $column, $row, $cellContent); + $this->flushCell($sheet, $column, $row, $cellContent, $attributeArray); $this->processDomElementBgcolor($sheet, $row, $column, $attributeArray); $this->processDomElementWidth($sheet, $column, $attributeArray); @@ -650,7 +678,7 @@ public function loadIntoExisting($filename, Spreadsheet $spreadsheet) $dom = new DOMDocument(); // Reload the HTML file into the DOM object try { - $convert = $this->securityScanner->scanFile($filename); + $convert = $this->getSecurityScannerOrThrow()->scanFile($filename); $lowend = "\u{80}"; $highend = "\u{10ffff}"; $regexp = "/[$lowend-$highend]/u"; @@ -664,10 +692,94 @@ public function loadIntoExisting($filename, Spreadsheet $spreadsheet) if ($loaded === false) { throw new Exception('Failed to load ' . $filename . ' as a DOM Document', 0, $e ?? null); } + self::loadProperties($dom, $spreadsheet); return $this->loadDocument($dom, $spreadsheet); } + private static function loadProperties(DOMDocument $dom, Spreadsheet $spreadsheet): void + { + $properties = $spreadsheet->getProperties(); + foreach ($dom->getElementsByTagName('meta') as $meta) { + $metaContent = (string) $meta->getAttribute('content'); + if ($metaContent !== '') { + $metaName = (string) $meta->getAttribute('name'); + switch ($metaName) { + case 'author': + $properties->setCreator($metaContent); + + break; + case 'category': + $properties->setCategory($metaContent); + + break; + case 'company': + $properties->setCompany($metaContent); + + break; + case 'created': + $properties->setCreated($metaContent); + + break; + case 'description': + $properties->setDescription($metaContent); + + break; + case 'keywords': + $properties->setKeywords($metaContent); + + break; + case 'lastModifiedBy': + $properties->setLastModifiedBy($metaContent); + + break; + case 'manager': + $properties->setManager($metaContent); + + break; + case 'modified': + $properties->setModified($metaContent); + + break; + case 'subject': + $properties->setSubject($metaContent); + + break; + case 'title': + $properties->setTitle($metaContent); + + break; + default: + if (preg_match('/^custom[.](bool|date|float|int|string)[.](.+)$/', $metaName, $matches) === 1) { + switch ($matches[1]) { + case 'bool': + $properties->setCustomProperty($matches[2], (bool) $metaContent, Properties::PROPERTY_TYPE_BOOLEAN); + + break; + case 'float': + $properties->setCustomProperty($matches[2], (float) $metaContent, Properties::PROPERTY_TYPE_FLOAT); + + break; + case 'int': + $properties->setCustomProperty($matches[2], (int) $metaContent, Properties::PROPERTY_TYPE_INTEGER); + + break; + case 'date': + $properties->setCustomProperty($matches[2], $metaContent, Properties::PROPERTY_TYPE_DATE); + + break; + default: // string + $properties->setCustomProperty($matches[2], $metaContent, Properties::PROPERTY_TYPE_STRING); + } + } + } + } + } + if (!empty($dom->baseURI)) { + $properties->setHyperlinkBase($dom->baseURI); + } + } + private static function replaceNonAscii(array $matches): string { return '&#' . mb_ord($matches[0], 'UTF-8') . ';'; @@ -684,7 +796,7 @@ public function loadFromString($content, ?Spreadsheet $spreadsheet = null): Spre $dom = new DOMDocument(); // Reload the HTML file into the DOM object try { - $convert = $this->securityScanner->scan($content); + $convert = $this->getSecurityScannerOrThrow()->scan($content); $lowend = "\u{80}"; $highend = "\u{10ffff}"; $regexp = "/[$lowend-$highend]/u"; @@ -698,8 +810,10 @@ public function loadFromString($content, ?Spreadsheet $spreadsheet = null): Spre if ($loaded === false) { throw new Exception('Failed to load content as a DOM Document', 0, $e ?? null); } + $spreadsheet = $spreadsheet ?? new Spreadsheet(); + self::loadProperties($dom, $spreadsheet); - return $this->loadDocument($dom, $spreadsheet ?? new Spreadsheet()); + return $this->loadDocument($dom, $spreadsheet); } /** @@ -769,7 +883,9 @@ private function applyInlineStyle(Worksheet &$sheet, $row, $column, $attributeAr return; } - if (isset($attributeArray['rowspan'], $attributeArray['colspan'])) { + if ($row <= 0 || $column === '') { + $cellStyle = new Style(); + } elseif (isset($attributeArray['rowspan'], $attributeArray['colspan'])) { $columnTo = $column; for ($i = 0; $i < (int) $attributeArray['colspan'] - 1; ++$i) { ++$columnTo; @@ -901,16 +1017,20 @@ private function applyInlineStyle(Worksheet &$sheet, $row, $column, $attributeAr break; case 'width': - $sheet->getColumnDimension($column)->setWidth( - (new CssDimension($styleValue ?? ''))->width() - ); + if ($column !== '') { + $sheet->getColumnDimension($column)->setWidth( + (new CssDimension($styleValue ?? ''))->width() + ); + } break; case 'height': - $sheet->getRowDimension($row)->setRowHeight( - (new CssDimension($styleValue ?? ''))->height() - ); + if ($row > 0) { + $sheet->getRowDimension($row)->setRowHeight( + (new CssDimension($styleValue ?? ''))->height() + ); + } break; @@ -941,7 +1061,7 @@ private function applyInlineStyle(Worksheet &$sheet, $row, $column, $attributeAr public function getStyleColor($value) { $value = (string) $value; - if (strpos($value ?? '', '#') === 0) { + if (strpos($value, '#') === 0) { return substr($value, 1); } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/IReader.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/IReader.php index d4a997b..97afe3c 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/IReader.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/IReader.php @@ -9,6 +9,7 @@ interface IReader public const READ_DATA_ONLY = 2; public const SKIP_EMPTY_CELLS = 4; + public const IGNORE_EMPTY_CELLS = 4; /** * IReader constructor. @@ -22,7 +23,8 @@ public function canRead(string $filename): bool; /** * Read data only? - * If this is true, then the Reader will only read data values for cells, it will not read any formatting information. + * If this is true, then the Reader will only read data values for cells, it will not read any formatting + * or structural information (like merges). * If false (the default) it will read data and formatting. * * @return bool @@ -31,7 +33,8 @@ public function getReadDataOnly(); /** * Set read data only - * Set to true, to advise the Reader only to read data values for cells, and to ignore any formatting information. + * Set to true, to advise the Reader only to read data values for cells, and to ignore any formatting + * or structural information (like merges). * Set to false (the default) to advise the Reader to read both data and formatting for cells. * * @param bool $readDataOnly @@ -62,9 +65,9 @@ public function setReadEmptyCells($readEmptyCells); /** * Read charts in workbook? - * If this is true, then the Reader will include any charts that exist in the workbook. - * Note that a ReadDataOnly value of false overrides, and charts won't be read regardless of the IncludeCharts value. - * If false (the default) it will ignore any charts defined in the workbook file. + * If this is true, then the Reader will include any charts that exist in the workbook. + * Note that a ReadDataOnly value of false overrides, and charts won't be read regardless of the IncludeCharts value. + * If false (the default) it will ignore any charts defined in the workbook file. * * @return bool */ @@ -72,9 +75,9 @@ public function getIncludeCharts(); /** * Set read charts in workbook - * Set to true, to advise the Reader to include any charts that exist in the workbook. - * Note that a ReadDataOnly value of false overrides, and charts won't be read regardless of the IncludeCharts value. - * Set to false (the default) to discard charts. + * Set to true, to advise the Reader to include any charts that exist in the workbook. + * Note that a ReadDataOnly value of false overrides, and charts won't be read regardless of the IncludeCharts value. + * Set to false (the default) to discard charts. * * @param bool $includeCharts * diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods.php index 3e0d803..9913f33 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods.php @@ -8,6 +8,7 @@ use DOMNode; use PhpOffice\PhpSpreadsheet\Cell\Coordinate; use PhpOffice\PhpSpreadsheet\Cell\DataType; +use PhpOffice\PhpSpreadsheet\Helper\Dimension as HelperDimension; use PhpOffice\PhpSpreadsheet\Reader\Ods\AutoFilter; use PhpOffice\PhpSpreadsheet\Reader\Ods\DefinedNames; use PhpOffice\PhpSpreadsheet\Reader\Ods\FormulaTranslator; @@ -56,20 +57,22 @@ public function canRead(string $filename): bool $mimeType = $zip->getFromName($stat['name']); } elseif ($zip->statName('META-INF/manifest.xml')) { $xml = simplexml_load_string( - $this->securityScanner->scan($zip->getFromName('META-INF/manifest.xml')), + $this->getSecurityScannerOrThrow()->scan($zip->getFromName('META-INF/manifest.xml')), 'SimpleXMLElement', Settings::getLibXmlLoaderOptions() ); - $namespacesContent = $xml->getNamespaces(true); - if (isset($namespacesContent['manifest'])) { - $manifest = $xml->children($namespacesContent['manifest']); - foreach ($manifest as $manifestDataSet) { - /** @scrutinizer ignore-call */ - $manifestAttributes = $manifestDataSet->attributes($namespacesContent['manifest']); - if ($manifestAttributes && $manifestAttributes->{'full-path'} == '/') { - $mimeType = (string) $manifestAttributes->{'media-type'}; - - break; + if ($xml !== false) { + $namespacesContent = $xml->getNamespaces(true); + if (isset($namespacesContent['manifest'])) { + $manifest = $xml->children($namespacesContent['manifest']); + foreach ($manifest as $manifestDataSet) { + /** @scrutinizer ignore-call */ + $manifestAttributes = $manifestDataSet->attributes($namespacesContent['manifest']); + if ($manifestAttributes && $manifestAttributes->{'full-path'} == '/') { + $mimeType = (string) $manifestAttributes->{'media-type'}; + + break; + } } } } @@ -97,7 +100,7 @@ public function listWorksheetNames($filename) $xml = new XMLReader(); $xml->xml( - $this->securityScanner->scanFile('zip://' . realpath($filename) . '#' . self::INITIAL_FILE), + $this->getSecurityScannerOrThrow()->scanFile('zip://' . realpath($filename) . '#' . self::INITIAL_FILE), null, Settings::getLibXmlLoaderOptions() ); @@ -120,7 +123,10 @@ public function listWorksheetNames($filename) if ($xmlName == 'table:table' && $xml->nodeType == XMLReader::ELEMENT) { // Loop through each table:table node reading the table:name attribute for each worksheet name do { - $worksheetNames[] = $xml->getAttribute('table:name'); + $worksheetName = $xml->getAttribute('table:name'); + if (!empty($worksheetName)) { + $worksheetNames[] = $worksheetName; + } $xml->next(); } while (self::getXmlName($xml) == 'table:table' && $xml->nodeType == XMLReader::ELEMENT); } @@ -145,7 +151,7 @@ public function listWorksheetInfo($filename) $xml = new XMLReader(); $xml->xml( - $this->securityScanner->scanFile('zip://' . realpath($filename) . '#' . self::INITIAL_FILE), + $this->getSecurityScannerOrThrow()->scanFile('zip://' . realpath($filename) . '#' . self::INITIAL_FILE), null, Settings::getLibXmlLoaderOptions() ); @@ -256,7 +262,7 @@ public function loadIntoExisting($filename, Spreadsheet $spreadsheet) // Meta $xml = @simplexml_load_string( - $this->securityScanner->scan($zip->getFromName('meta.xml')), + $this->getSecurityScannerOrThrow()->scan($zip->getFromName('meta.xml')), 'SimpleXMLElement', Settings::getLibXmlLoaderOptions() ); @@ -272,7 +278,7 @@ public function loadIntoExisting($filename, Spreadsheet $spreadsheet) $dom = new DOMDocument('1.01', 'UTF-8'); $dom->loadXML( - $this->securityScanner->scan($zip->getFromName('styles.xml')), + $this->getSecurityScannerOrThrow()->scan($zip->getFromName('styles.xml')), Settings::getLibXmlLoaderOptions() ); @@ -282,7 +288,7 @@ public function loadIntoExisting($filename, Spreadsheet $spreadsheet) $dom = new DOMDocument('1.01', 'UTF-8'); $dom->loadXML( - $this->securityScanner->scan($zip->getFromName(self::INITIAL_FILE)), + $this->getSecurityScannerOrThrow()->scan($zip->getFromName(self::INITIAL_FILE)), Settings::getLibXmlLoaderOptions() ); @@ -290,16 +296,33 @@ public function loadIntoExisting($filename, Spreadsheet $spreadsheet) $tableNs = $dom->lookupNamespaceUri('table'); $textNs = $dom->lookupNamespaceUri('text'); $xlinkNs = $dom->lookupNamespaceUri('xlink'); + $styleNs = $dom->lookupNamespaceUri('style'); $pageSettings->readStyleCrossReferences($dom); $autoFilterReader = new AutoFilter($spreadsheet, $tableNs); $definedNameReader = new DefinedNames($spreadsheet, $tableNs); + $columnWidths = []; + $automaticStyle0 = $dom->getElementsByTagNameNS($officeNs, 'automatic-styles')->item(0); + $automaticStyles = ($automaticStyle0 === null) ? [] : $automaticStyle0->getElementsByTagNameNS($styleNs, 'style'); + foreach ($automaticStyles as $automaticStyle) { + $styleName = $automaticStyle->getAttributeNS($styleNs, 'name'); + $styleFamily = $automaticStyle->getAttributeNS($styleNs, 'family'); + if ($styleFamily === 'table-column') { + $tcprops = $automaticStyle->getElementsByTagNameNS($styleNs, 'table-column-properties'); + if ($tcprops !== null) { + $tcprop = $tcprops->item(0); + if ($tcprop !== null) { + $columnWidth = $tcprop->getAttributeNs($styleNs, 'column-width'); + $columnWidths[$styleName] = $columnWidth; + } + } + } + } // Content - $spreadsheets = $dom->getElementsByTagNameNS($officeNs, 'body') - ->item(0) - ->getElementsByTagNameNS($officeNs, 'spreadsheet'); + $item0 = $dom->getElementsByTagNameNS($officeNs, 'body')->item(0); + $spreadsheets = ($item0 === null) ? [] : $item0->getElementsByTagNameNS($officeNs, 'spreadsheet'); foreach ($spreadsheets as $workbookData) { /** @var DOMElement $workbookData */ @@ -336,6 +359,7 @@ public function loadIntoExisting($filename, Spreadsheet $spreadsheet) // Go through every child of table element $rowID = 1; + $tableColumnIndex = 1; foreach ($worksheetDataSet->childNodes as $childNode) { /** @var DOMElement $childNode */ @@ -362,6 +386,26 @@ public function loadIntoExisting($filename, Spreadsheet $spreadsheet) // $rowData = $cellData; // break; // } + break; + case 'table-column': + if ($childNode->hasAttributeNS($tableNs, 'number-columns-repeated')) { + $rowRepeats = (int) $childNode->getAttributeNS($tableNs, 'number-columns-repeated'); + } else { + $rowRepeats = 1; + } + $tableStyleName = $childNode->getAttributeNS($tableNs, 'style-name'); + if (isset($columnWidths[$tableStyleName])) { + $columnWidth = new HelperDimension($columnWidths[$tableStyleName]); + $tableColumnString = Coordinate::stringFromColumnIndex($tableColumnIndex); + for ($rowRepeats2 = $rowRepeats; $rowRepeats2 > 0; --$rowRepeats2) { + $spreadsheet->getActiveSheet() + ->getColumnDimension($tableColumnString) + ->setWidth($columnWidth->toUnit('cm'), 'cm'); + ++$tableColumnString; + } + } + $tableColumnIndex += $rowRepeats; + break; case 'table-row': if ($childNode->hasAttributeNS($tableNs, 'number-rows-repeated')) { @@ -402,10 +446,10 @@ public function loadIntoExisting($filename, Spreadsheet $spreadsheet) // Annotations $annotation = $cellData->getElementsByTagNameNS($officeNs, 'annotation'); - if ($annotation->length > 0) { + if ($annotation->length > 0 && $annotation->item(0) !== null) { $textNode = $annotation->item(0)->getElementsByTagNameNS($textNs, 'p'); - if ($textNode->length > 0) { + if ($textNode->length > 0 && $textNode->item(0) !== null) { $text = $this->scanElementForText($textNode->item(0)); $spreadsheet->getActiveSheet() @@ -452,7 +496,7 @@ public function loadIntoExisting($filename, Spreadsheet $spreadsheet) foreach ($paragraphs as $paragraph) { $link = $paragraph->getElementsByTagNameNS($textNs, 'a'); - if ($link->length > 0) { + if ($link->length > 0 && $link->item(0) !== null) { $hyperlink = $link->item(0)->getAttributeNS($xlinkNs, 'href'); } } @@ -481,7 +525,7 @@ public function loadIntoExisting($filename, Spreadsheet $spreadsheet) if (floor($dataValue) == $dataValue) { $dataValue = (int) $dataValue; } - $formatting = NumberFormat::FORMAT_CURRENCY_USD_SIMPLE; + $formatting = NumberFormat::FORMAT_CURRENCY_USD_INTEGER; break; case 'float': @@ -620,7 +664,7 @@ private function processSettings(ZipArchive $zip, Spreadsheet $spreadsheet): voi { $dom = new DOMDocument('1.01', 'UTF-8'); $dom->loadXML( - $this->securityScanner->scan($zip->getFromName('settings.xml')), + $this->getSecurityScannerOrThrow()->scan($zip->getFromName('settings.xml')), Settings::getLibXmlLoaderOptions() ); //$xlinkNs = $dom->lookupNamespaceUri('xlink'); @@ -629,8 +673,10 @@ private function processSettings(ZipArchive $zip, Spreadsheet $spreadsheet): voi $officeNs = $dom->lookupNamespaceUri('office'); $settings = $dom->getElementsByTagNameNS($officeNs, 'settings') ->item(0); - $this->lookForActiveSheet($settings, $spreadsheet, $configNs); - $this->lookForSelectedCells($settings, $spreadsheet, $configNs); + if ($settings !== null) { + $this->lookForActiveSheet($settings, $spreadsheet, $configNs); + $this->lookForSelectedCells($settings, $spreadsheet, $configNs); + } } private function lookForActiveSheet(DOMElement $settings, Spreadsheet $spreadsheet, string $configNs): void @@ -700,9 +746,9 @@ protected function scanElementForText(DOMNode $element) // It's a space // Multiple spaces? - /** @var DOMAttr $cAttr */ - /** @scrutinizer ignore-call */ - $cAttr = $child->attributes->getNamedItem('c'); + $attributes = $child->attributes; + /** @var ?DOMAttr $cAttr */ + $cAttr = ($attributes === null) ? null : $attributes->getNamedItem('c'); $multiplier = self::getMultiplier($cAttr); $str .= str_repeat(' ', $multiplier); } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods/PageSettings.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods/PageSettings.php index 4d2fd99..0e18af5 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods/PageSettings.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods/PageSettings.php @@ -33,6 +33,7 @@ class PageSettings */ private $tableStylesCrossReference = []; + /** @var array */ private $pageLayoutStyles = []; /** @@ -62,9 +63,8 @@ private function setDomNameSpaces(DOMDocument $styleDom): void private function readPageSettingStyles(DOMDocument $styleDom): void { - $styles = $styleDom->getElementsByTagNameNS($this->officeNs, 'automatic-styles') - ->item(0) - ->getElementsByTagNameNS($this->stylesNs, 'page-layout'); + $item0 = $styleDom->getElementsByTagNameNS($this->officeNs, 'automatic-styles')->item(0); + $styles = ($item0 === null) ? [] : $item0->getElementsByTagNameNS($this->stylesNs, 'page-layout'); foreach ($styles as $styleSet) { $styleName = $styleSet->getAttributeNS($this->stylesNs, 'name'); @@ -92,21 +92,20 @@ private function readPageSettingStyles(DOMDocument $styleDom): void 'horizontalCentered' => $centered === 'horizontal' || $centered === 'both', 'verticalCentered' => $centered === 'vertical' || $centered === 'both', // margin size is already stored in inches, so no UOM conversion is required - 'marginLeft' => (float) $marginLeft ?? 0.7, - 'marginRight' => (float) $marginRight ?? 0.7, - 'marginTop' => (float) $marginTop ?? 0.3, - 'marginBottom' => (float) $marginBottom ?? 0.3, - 'marginHeader' => (float) $marginHeader ?? 0.45, - 'marginFooter' => (float) $marginFooter ?? 0.45, + 'marginLeft' => (float) ($marginLeft ?? 0.7), + 'marginRight' => (float) ($marginRight ?? 0.7), + 'marginTop' => (float) ($marginTop ?? 0.3), + 'marginBottom' => (float) ($marginBottom ?? 0.3), + 'marginHeader' => (float) ($marginHeader ?? 0.45), + 'marginFooter' => (float) ($marginFooter ?? 0.45), ]; } } private function readStyleMasterLookup(DOMDocument $styleDom): void { - $styleMasterLookup = $styleDom->getElementsByTagNameNS($this->officeNs, 'master-styles') - ->item(0) - ->getElementsByTagNameNS($this->stylesNs, 'master-page'); + $item0 = $styleDom->getElementsByTagNameNS($this->officeNs, 'master-styles')->item(0); + $styleMasterLookup = ($item0 === null) ? [] : $item0->getElementsByTagNameNS($this->stylesNs, 'master-page'); foreach ($styleMasterLookup as $styleMasterSet) { $styleMasterName = $styleMasterSet->getAttributeNS($this->stylesNs, 'name'); @@ -117,9 +116,8 @@ private function readStyleMasterLookup(DOMDocument $styleDom): void public function readStyleCrossReferences(DOMDocument $contentDom): void { - $styleXReferences = $contentDom->getElementsByTagNameNS($this->officeNs, 'automatic-styles') - ->item(0) - ->getElementsByTagNameNS($this->stylesNs, 'style'); + $item0 = $contentDom->getElementsByTagNameNS($this->officeNs, 'automatic-styles')->item(0); + $styleXReferences = ($item0 === null) ? [] : $item0->getElementsByTagNameNS($this->stylesNs, 'style'); foreach ($styleXReferences as $styleXreferenceSet) { $styleXRefName = $styleXreferenceSet->getAttributeNS($this->stylesNs, 'name'); diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods/Properties.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods/Properties.php index 1547a6b..8c4ccc3 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods/Properties.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods/Properties.php @@ -8,6 +8,7 @@ class Properties { + /** @var Spreadsheet */ private $spreadsheet; public function __construct(Spreadsheet $spreadsheet) @@ -15,7 +16,7 @@ public function __construct(Spreadsheet $spreadsheet) $this->spreadsheet = $spreadsheet; } - public function load(SimpleXMLElement $xml, $namespacesMeta): void + public function load(SimpleXMLElement $xml, array $namespacesMeta): void { $docProps = $this->spreadsheet->getProperties(); $officeProperty = $xml->children($namespacesMeta['office']); @@ -69,9 +70,9 @@ private function setCoreProperties(DocumentProperties $docProps, SimpleXMLElemen } private function setMetaProperties( - $namespacesMeta, + array $namespacesMeta, SimpleXMLElement $propertyValue, - $propertyName, + string $propertyName, DocumentProperties $docProps ): void { $propertyValueAttributes = $propertyValue->attributes($namespacesMeta['meta']); @@ -96,6 +97,10 @@ private function setMetaProperties( } } + /** + * @param mixed $propertyValueAttributes + * @param mixed $propertyValue + */ private function setUserDefinedProperty($propertyValueAttributes, $propertyValue, DocumentProperties $docProps): void { $propertyValueName = ''; diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Security/XmlScanner.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Security/XmlScanner.php index f4cf2db..f8eaf39 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Security/XmlScanner.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Security/XmlScanner.php @@ -13,8 +13,10 @@ class XmlScanner */ private $pattern; + /** @var ?callable */ private $callback; + /** @var ?bool */ private static $libxmlDisableEntityLoaderValue; /** @@ -22,7 +24,7 @@ class XmlScanner */ private static $shutdownRegistered = false; - public function __construct($pattern = 'pattern = $pattern; @@ -35,22 +37,17 @@ public function __construct($pattern = 'disableEntityLoaderCheck(); $xml = $this->toUtf8($xml); @@ -150,7 +151,7 @@ public function scan($xml) throw new Reader\Exception('Detected use of ENTITY in XML, spreadsheet file load() aborted to prevent XXE/XEE attacks'); } - if ($this->callback !== null && is_callable($this->callback)) { + if ($this->callback !== null) { $xml = call_user_func($this->callback, $xml); } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls.php index 5367eff..816e769 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls.php @@ -14,6 +14,7 @@ use PhpOffice\PhpSpreadsheet\Shared\CodePage; use PhpOffice\PhpSpreadsheet\Shared\Date; use PhpOffice\PhpSpreadsheet\Shared\Escher; +use PhpOffice\PhpSpreadsheet\Shared\Escher\DgContainer\SpgrContainer\SpContainer; use PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer\BSE; use PhpOffice\PhpSpreadsheet\Shared\File; use PhpOffice\PhpSpreadsheet\Shared\OLE; @@ -161,14 +162,14 @@ class Xls extends BaseReader /** * Summary Information stream data. * - * @var string + * @var ?string */ private $summaryInformation; /** * Extended Summary Information stream data. * - * @var string + * @var ?string */ private $documentSummaryInformation; @@ -387,7 +388,7 @@ class Xls extends BaseReader /** * The current RC4 decryption object. * - * @var Xls\RC4 + * @var ?Xls\RC4 */ private $rc4Key; @@ -400,10 +401,11 @@ class Xls extends BaseReader /** * The current MD5 context state. + * It is never set in the program, so code which uses it is suspect. * * @var string */ - private $md5Ctxt; + private $md5Ctxt; // @phpstan-ignore-line /** * @var int @@ -428,7 +430,7 @@ public function __construct() */ public function canRead(string $filename): bool { - if (!File::testFileNoThrow($filename)) { + if (File::testFileNoThrow($filename) === false) { return false; } @@ -438,6 +440,9 @@ public function canRead(string $filename): bool // get excel data $ole->read($filename); + if ($ole->wrkbook === null) { + throw new Exception('The filename ' . $filename . ' is not recognised as a Spreadsheet file'); + } return true; } catch (PhpSpreadsheetException $e) { @@ -447,7 +452,7 @@ public function canRead(string $filename): bool public function setCodepage(string $codepage): void { - if (!CodePage::validate($codepage)) { + if (CodePage::validate($codepage) === false) { throw new PhpSpreadsheetException('Unknown codepage: ' . $codepage); } @@ -1088,13 +1093,14 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet $escherWorksheet = $reader->load($this->drawingData); // get all spContainers in one long array, so they can be mapped to OBJ records - $allSpContainers = $escherWorksheet->getDgContainer()->getSpgrContainer()->getAllSpContainers(); + /** @var SpContainer[] */ + $allSpContainers = method_exists($escherWorksheet, 'getDgContainer') ? $escherWorksheet->getDgContainer()->getSpgrContainer()->getAllSpContainers() : []; } // treat OBJ records foreach ($this->objs as $n => $obj) { // the first shape container never has a corresponding OBJ record, hence $n + 1 - if (isset($allSpContainers[$n + 1]) && is_object($allSpContainers[$n + 1])) { + if (isset($allSpContainers[$n + 1])) { $spContainer = $allSpContainers[$n + 1]; // we skip all spContainers that are a part of a group shape since we cannot yet handle those @@ -1103,7 +1109,9 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet } // calculate the width and height of the shape + /** @var int $startRow */ [$startColumn, $startRow] = Coordinate::coordinateFromString($spContainer->getStartCoordinates()); + /** @var int $endRow */ [$endColumn, $endRow] = Coordinate::coordinateFromString($spContainer->getEndCoordinates()); $startOffsetX = $spContainer->getStartOffsetX(); @@ -1145,7 +1153,7 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet } if ($escherWorkbook) { - $BSECollection = $escherWorkbook->getDggContainer()->getBstoreContainer()->getBSECollection(); + $BSECollection = method_exists($escherWorkbook, 'getDggContainer') ? $escherWorkbook->getDggContainer()->getBstoreContainer()->getBSECollection() : []; $BSE = $BSECollection[$BSEindex - 1]; $blipType = $BSE->getBlipType(); @@ -1195,6 +1203,7 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet // treat SHAREDFMLA records if ($this->version == self::XLS_BIFF8) { foreach ($this->sharedFormulaParts as $cell => $baseCell) { + /** @var int $row */ [$column, $row] = Coordinate::coordinateFromString($cell); if (($this->getReadFilter() !== null) && $this->getReadFilter()->readCell($column, $row, $this->phpSheet->getTitle())) { $formula = $this->getFormulaFromStructure($this->sharedFormulas[$baseCell], $cell); @@ -1335,8 +1344,8 @@ private function readRecordData($data, $pos, $len) $recordData = ''; if ($this->encryption == self::MS_BIFF_CRYPTO_RC4) { $oldBlock = floor($this->rc4Pos / self::REKEY_BLOCK); - $block = floor($pos / self::REKEY_BLOCK); - $endBlock = floor(($pos + $len) / self::REKEY_BLOCK); + $block = (int) floor($pos / self::REKEY_BLOCK); + $endBlock = (int) floor(($pos + $len) / self::REKEY_BLOCK); // Spin an RC4 decryptor to the right spot. If we have a decryptor sitting // at a point earlier in the current block, re-use it as we can save some time. @@ -1382,7 +1391,7 @@ private function loadOLE($filename): void // get excel data, $ole->read($filename); // Get workbook data: workbook stream + sheet streams - $this->data = $ole->getStream($ole->wrkbook); + $this->data = $ole->getStream($ole->wrkbook); // @phpstan-ignore-line // Get summary information data $this->summaryInformation = $ole->getStream($ole->summaryInformation); // Get additional document summary information data @@ -1723,7 +1732,7 @@ private function readNote(): void $cellAddress = array_pop($arrayKeys); } - $cellAddress = str_replace('$', '', $cellAddress); + $cellAddress = str_replace('$', '', (string) $cellAddress); $noteLength = self::getUInt2d($recordData, 4); $noteText = trim(substr($recordData, 6)); @@ -3154,11 +3163,11 @@ private function readSheetPr(): void // bit: 6; mask: 0x0040; 0 = outline buttons above outline group $isSummaryBelow = (0x0040 & self::getUInt2d($recordData, 0)) >> 6; - $this->phpSheet->setShowSummaryBelow($isSummaryBelow); + $this->phpSheet->setShowSummaryBelow((bool) $isSummaryBelow); // bit: 7; mask: 0x0080; 0 = outline buttons left of outline group $isSummaryRight = (0x0080 & self::getUInt2d($recordData, 0)) >> 7; - $this->phpSheet->setShowSummaryRight($isSummaryRight); + $this->phpSheet->setShowSummaryRight((bool) $isSummaryRight); // bit: 8; mask: 0x100; 0 = scale printout in percent, 1 = fit printout to number of pages // this corresponds to radio button setting in page setup dialog in Excel @@ -3211,10 +3220,10 @@ private function readVerticalPageBreaks(): void for ($i = 0; $i < $nm; ++$i) { $c = self::getUInt2d($recordData, 2 + 6 * $i); $rf = self::getUInt2d($recordData, 2 + 6 * $i + 2); - $rl = self::getUInt2d($recordData, 2 + 6 * $i + 4); + //$rl = self::getUInt2d($recordData, 2 + 6 * $i + 4); // not sure why two row indexes are necessary? - $this->phpSheet->setBreak([$c + 1, $rf], Worksheet::BREAK_COLUMN); + $this->phpSheet->setBreak([$c + 1, ($rf > 0) ? $rf : 1], Worksheet::BREAK_COLUMN); } } } @@ -4540,7 +4549,7 @@ private function readSelection(): void } } - private function includeCellRangeFiltered($cellRangeAddress) + private function includeCellRangeFiltered(string $cellRangeAddress): bool { $includeCellRange = true; if ($this->getReadFilter() !== null) { @@ -5637,8 +5646,6 @@ private function getNextToken($formulaData, $baseCell = 'A1') break; default: throw new Exception('Unrecognized space type in tAttrSpace token'); - - break; } // offset: 3; size: 1; number of inserted spaces/carriage returns $spacecount = ord($formulaData[3]); @@ -5648,8 +5655,6 @@ private function getNextToken($formulaData, $baseCell = 'A1') break; default: throw new Exception('Unrecognized attribute flag in tAttr token'); - - break; } break; @@ -6500,8 +6505,6 @@ private function getNextToken($formulaData, $baseCell = 'A1') break; default: throw new Exception('Unrecognized function in formula'); - - break; } $data = ['function' => $function, 'args' => $args]; @@ -6870,8 +6873,6 @@ private function getNextToken($formulaData, $baseCell = 'A1') break; default: throw new Exception('Unrecognized function in formula'); - - break; } $data = ['function' => $function, 'args' => $args]; @@ -7004,8 +7005,6 @@ private function getNextToken($formulaData, $baseCell = 'A1') // Unknown cases // don't know how to deal with default: throw new Exception('Unrecognized token ' . sprintf('%02X', $id) . ' in formula'); - - break; } return [ @@ -7413,13 +7412,9 @@ private function readSheetRangeByRefIndex($index) } return $sheetRange; - - break; default: // TODO: external sheet support throw new Exception('Xls reader only supports internal sheets in formulas'); - - break; } } @@ -7821,7 +7816,7 @@ public static function getUInt2d($data, $pos) */ public static function getInt2d($data, $pos) { - return unpack('s', $data[$pos] . $data[$pos + 1])[1]; + return unpack('s', $data[$pos] . $data[$pos + 1])[1]; // @phpstan-ignore-line } /** @@ -7848,7 +7843,7 @@ public static function getInt4d($data, $pos) return ord($data[$pos]) | (ord($data[$pos + 1]) << 8) | (ord($data[$pos + 2]) << 16) | $_ord_24; } - private function parseRichText($is) + private function parseRichText(string $is): RichText { $value = new RichText(); $value->createText($is); @@ -7929,7 +7924,7 @@ private function readCFRule(array $cellRangeAddresses): void // offset: 6; size: 4; Options $options = self::getInt4d($recordData, 6); - $style = new Style(); + $style = new Style(false, true); // non-supervisor, conditional $this->getCFStyleOptions($options, $style); $hasFontRecord = (bool) ((0x04000000 & $options) >> 26); diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php index a79b25e..1c33fd6 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php @@ -16,6 +16,7 @@ use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Namespaces; use PhpOffice\PhpSpreadsheet\Reader\Xlsx\PageSetup; use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Properties as PropertyReader; +use PhpOffice\PhpSpreadsheet\Reader\Xlsx\SharedFormula; use PhpOffice\PhpSpreadsheet\Reader\Xlsx\SheetViewOptions; use PhpOffice\PhpSpreadsheet\Reader\Xlsx\SheetViews; use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Styles; @@ -61,6 +62,11 @@ class Xlsx extends BaseReader /** @var Styles */ private $styleReader; + /** + * @var array + */ + private $sharedFormulae = []; + /** * Create a new Xlsx Reader instance. */ @@ -122,11 +128,14 @@ public static function falseToArray($value): array return is_array($value) ? $value : []; } - private function loadZip(string $filename, string $ns = ''): SimpleXMLElement + private function loadZip(string $filename, string $ns = '', bool $replaceUnclosedBr = false): SimpleXMLElement { $contents = $this->getFromZipArchive($this->zip, $filename); - $rels = simplexml_load_string( - $this->securityScanner->scan($contents), + if ($replaceUnclosedBr) { + $contents = str_replace('
', '
', $contents); + } + $rels = @simplexml_load_string( + $this->getSecurityScannerOrThrow()->scan($contents), 'SimpleXMLElement', Settings::getLibXmlLoaderOptions(), $ns @@ -141,7 +150,7 @@ private function loadZipNonamespace(string $filename, string $ns): SimpleXMLElem { $contents = $this->getFromZipArchive($this->zip, $filename); $rels = simplexml_load_string( - $this->securityScanner->scan($contents), + $this->getSecurityScannerOrThrow()->scan($contents), 'SimpleXMLElement', Settings::getLibXmlLoaderOptions(), ($ns === '' ? $ns : '') @@ -243,6 +252,7 @@ public function listWorksheetInfo($filename) $xmlWorkbook = $this->loadZip($relTarget, $mainNS); if ($xmlWorkbook->sheets) { $dir = dirname($relTarget); + /** @var SimpleXMLElement $eleSheet */ foreach ($xmlWorkbook->sheets->sheet as $eleSheet) { $tmpInfo = [ @@ -258,8 +268,8 @@ public function listWorksheetInfo($filename) $xml = new XMLReader(); $xml->xml( - $this->securityScanner->scanFile( - 'zip://' . File::realpath($filename) . '#' . $fileWorksheetPath + $this->getSecurityScannerOrThrow()->scan( + $this->getFromZipArchive($this->zip, $fileWorksheetPath) ), null, Settings::getLibXmlLoaderOptions() @@ -321,13 +331,13 @@ private static function castToString(?SimpleXMLElement $c): ?string * @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, string $castBaseType, bool $updateSharedCells = true): void { if ($c === null) { return; } $attr = $c->f->attributes(); - $cellDataType = 'f'; + $cellDataType = DataType::TYPE_FORMULA; $value = "={$c->f}"; $calculatedValue = self::$castBaseType($c); @@ -335,17 +345,19 @@ private function castToFormula(?SimpleXMLElement $c, string $r, string &$cellDat if (isset($attr['t']) && strtolower((string) $attr['t']) == 'shared') { $instance = (string) $attr['si']; - if (!isset($sharedFormulas[(string) $attr['si']])) { - $sharedFormulas[$instance] = ['master' => $r, 'formula' => $value]; - } else { - $master = Coordinate::indexesFromString($sharedFormulas[$instance]['master']); + if (!isset($this->sharedFormulae[(string) $attr['si']])) { + $this->sharedFormulae[$instance] = new SharedFormula($r, $value); + } elseif ($updateSharedCells === true) { + // It's only worth the overhead of adjusting the shared formula for this cell if we're actually loading + // the cell, which may not be the case if we're using a read filter. + $master = Coordinate::indexesFromString($this->sharedFormulae[$instance]->master()); $current = Coordinate::indexesFromString($r); $difference = [0, 0]; $difference[0] = $current[0] - $master[0]; $difference[1] = $current[1] - $master[1]; - $value = $this->referenceHelper->updateFormulaReferences($sharedFormulas[$instance]['formula'], 'A1', $difference[0], $difference[1]); + $value = $this->referenceHelper->updateFormulaReferences($this->sharedFormulae[$instance]->formula(), 'A1', $difference[0], $difference[1]); } } } @@ -392,12 +404,18 @@ private function getFromZipArchive(ZipArchive $archive, $fileName = '') // Sadly, some 3rd party xlsx generators don't use consistent case for filenaming // so we need to load case-insensitively from the zip file - // Apache POI fixes $contents = $archive->getFromName($fileName, 0, ZipArchive::FL_NOCASE); + + // Apache POI fixes if ($contents === false) { $contents = $archive->getFromName(substr($fileName, 1), 0, ZipArchive::FL_NOCASE); } + // Has the file been saved with Windoze directory separators rather than unix? + if ($contents === false) { + $contents = $archive->getFromName(str_replace('/', '\\', $fileName), 0, ZipArchive::FL_NOCASE); + } + return ($contents === false) ? '' : $contents; } @@ -444,6 +462,7 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet $colourScheme = self::getAttributes($xmlTheme->themeElements->clrScheme); $colourSchemeName = (string) $colourScheme['name']; + $excel->getTheme()->setThemeColorName($colourSchemeName); $colourScheme = $xmlTheme->themeElements->clrScheme->children($drawingNS); $themeColours = []; @@ -455,25 +474,61 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet if (isset($xmlColour->sysClr)) { $xmlColourData = self::getAttributes($xmlColour->sysClr); $themeColours[$themePos] = (string) $xmlColourData['lastClr']; + $excel->getTheme()->setThemeColor($k, (string) $xmlColourData['lastClr']); } elseif (isset($xmlColour->srgbClr)) { $xmlColourData = self::getAttributes($xmlColour->srgbClr); $themeColours[$themePos] = (string) $xmlColourData['val']; + $excel->getTheme()->setThemeColor($k, (string) $xmlColourData['val']); } } $theme = new Theme($themeName, $colourSchemeName, $themeColours); $this->styleReader->setTheme($theme); + $fontScheme = self::getAttributes($xmlTheme->themeElements->fontScheme); + $fontSchemeName = (string) $fontScheme['name']; + $excel->getTheme()->setThemeFontName($fontSchemeName); + $majorFonts = []; + $minorFonts = []; + $fontScheme = $xmlTheme->themeElements->fontScheme->children($drawingNS); + $majorLatin = self::getAttributes($fontScheme->majorFont->latin)['typeface'] ?? ''; + $majorEastAsian = self::getAttributes($fontScheme->majorFont->ea)['typeface'] ?? ''; + $majorComplexScript = self::getAttributes($fontScheme->majorFont->cs)['typeface'] ?? ''; + $minorLatin = self::getAttributes($fontScheme->minorFont->latin)['typeface'] ?? ''; + $minorEastAsian = self::getAttributes($fontScheme->minorFont->ea)['typeface'] ?? ''; + $minorComplexScript = self::getAttributes($fontScheme->minorFont->cs)['typeface'] ?? ''; + + foreach ($fontScheme->majorFont->font as $xmlFont) { + $fontAttributes = self::getAttributes($xmlFont); + $script = (string) ($fontAttributes['script'] ?? ''); + if (!empty($script)) { + $majorFonts[$script] = (string) ($fontAttributes['typeface'] ?? ''); + } + } + foreach ($fontScheme->minorFont->font as $xmlFont) { + $fontAttributes = self::getAttributes($xmlFont); + $script = (string) ($fontAttributes['script'] ?? ''); + if (!empty($script)) { + $minorFonts[$script] = (string) ($fontAttributes['typeface'] ?? ''); + } + } + $excel->getTheme()->setMajorFontValues($majorLatin, $majorEastAsian, $majorComplexScript, $majorFonts); + $excel->getTheme()->setMinorFontValues($minorLatin, $minorEastAsian, $minorComplexScript, $minorFonts); + break; } } $rels = $this->loadZip(self::INITIAL_FILE, Namespaces::RELATIONSHIPS); - $propertyReader = new PropertyReader($this->securityScanner, $excel->getProperties()); + $propertyReader = new PropertyReader($this->getSecurityScannerOrThrow(), $excel->getProperties()); $chartDetails = []; foreach ($rels->Relationship as $relx) { $rel = self::getAttributes($relx); $relTarget = (string) $rel['Target']; + // issue 3553 + if ($relTarget[0] === '/') { + $relTarget = substr($relTarget, 1); + } $relType = (string) $rel['Type']; $mainNS = self::REL_TO_MAIN[$relType] ?? Namespaces::MAIN; switch ($relType) { @@ -504,26 +559,6 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet $relsWorkbook = $this->loadZip("$dir/_rels/" . basename($relTarget) . '.rels', ''); $relsWorkbook->registerXPathNamespace('rel', Namespaces::RELATIONSHIPS); - $sharedStrings = []; - $relType = "rel:Relationship[@Type='" - //. Namespaces::SHARED_STRINGS - . "$xmlNamespaceBase/sharedStrings" - . "']"; - $xpath = self::getArrayItem($relsWorkbook->xpath($relType)); - - if ($xpath) { - $xmlStrings = $this->loadZip("$dir/$xpath[Target]", $mainNS); - if (isset($xmlStrings->si)) { - foreach ($xmlStrings->si as $val) { - if (isset($val->t)) { - $sharedStrings[] = StringHelper::controlCharacterOOXML2PHP((string) $val->t); - } elseif (isset($val->r)) { - $sharedStrings[] = $this->parseRichText($val); - } - } - } - } - $worksheets = []; $macros = $customUI = null; foreach ($relsWorkbook->Relationship as $elex) { @@ -615,7 +650,7 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet $numFmt = NumberFormat::builtInFormatCode((int) $xf['numFmtId']); } } - $quotePrefix = (bool) ($xf['quotePrefix'] ?? false); + $quotePrefix = (bool) (string) ($xf['quotePrefix'] ?? ''); $style = (object) [ 'numFmt' => $numFmt ?? NumberFormat::FORMAT_GENERAL, @@ -650,7 +685,7 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet } } - $quotePrefix = (bool) ($xf['quotePrefix'] ?? false); + $quotePrefix = (bool) (string) ($xf['quotePrefix'] ?? ''); $cellStyle = (object) [ 'numFmt' => $numFmt, @@ -679,6 +714,27 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet $dxfs = $this->styleReader->dxfs($this->readDataOnly); $styles = $this->styleReader->styles(); + // Read content after setting the styles + $sharedStrings = []; + $relType = "rel:Relationship[@Type='" + //. Namespaces::SHARED_STRINGS + . "$xmlNamespaceBase/sharedStrings" + . "']"; + $xpath = self::getArrayItem($relsWorkbook->xpath($relType)); + + if ($xpath) { + $xmlStrings = $this->loadZip("$dir/$xpath[Target]", $mainNS); + if (isset($xmlStrings->si)) { + foreach ($xmlStrings->si as $val) { + if (isset($val->t)) { + $sharedStrings[] = StringHelper::controlCharacterOOXML2PHP((string) $val->t); + } elseif (isset($val->r)) { + $sharedStrings[] = $this->parseRichText($val); + } + } + } + } + $xmlWorkbook = $this->loadZipNoNamespace($relTarget, $mainNS); $xmlWorkbookNS = $this->loadZip($relTarget, $mainNS); @@ -740,7 +796,8 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet $xmlSheet = $this->loadZipNoNamespace("$dir/$fileWorksheet", $mainNS); $xmlSheetNS = $this->loadZip("$dir/$fileWorksheet", $mainNS); - $sharedFormulas = []; + // Shared Formula table is unique to each Worksheet, so we need to reset it here + $this->sharedFormulae = []; if (isset($eleSheetAttr['state']) && (string) $eleSheetAttr['state'] != '') { $docSheet->setSheetState((string) $eleSheetAttr['state']); @@ -786,8 +843,12 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet $coordinates = Coordinate::coordinateFromString($r); if (!$this->getReadFilter()->readCell($coordinates[0], (int) $coordinates[1], $docSheet->getTitle())) { - if (isset($cAttr->f)) { - $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 'castToError'); + // Normally, just testing for the f attribute should identify this cell as containing a formula + // that we need to read, even though it is outside of the filter range, in case it is a shared formula. + // But in some cases, this attribute isn't set; so we need to delve a level deeper and look at + // whether or not the cell has a child formula element that is shared. + if (isset($cAttr->f) || (isset($c->f, $c->f->attributes()['t']) && strtolower((string) $c->f->attributes()['t']) === 'shared')) { + $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, 'castToError', false); } ++$rowIndex; @@ -819,7 +880,7 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet } } else { // Formula - $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 'castToBoolean'); + $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, 'castToBoolean'); if (isset($c->f['t'])) { $att = $c->f; $docSheet->getCell($r)->setFormulaAttributes($att); @@ -829,7 +890,7 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet break; case 'inlineStr': if (isset($c->f)) { - $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 'castToError'); + $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, 'castToError'); } else { $value = $this->parseRichText($c->is); } @@ -840,7 +901,7 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet $value = self::castToError($c); } else { // Formula - $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 'castToError'); + $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, 'castToError'); } break; @@ -849,7 +910,7 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet $value = self::castToString($c); } else { // Formula - $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 'castToString'); + $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, 'castToString'); if (isset($c->f['t'])) { $attributes = $c->f['t']; $docSheet->getCell($r)->setFormulaAttributes(['t' => (string) $attributes]); @@ -888,6 +949,10 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet // no style index means 0, it seems $cell->setXfIndex(isset($styles[(int) ($cAttr['s'])]) ? (int) ($cAttr['s']) : 0); + // issue 3495 + if ($cell->getDataType() === DataType::TYPE_FORMULA) { + $cell->getStyle()->setQuotePrefix(false); + } } } ++$rowIndex; @@ -895,6 +960,12 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet ++$cIndex; } } + if ($xmlSheetNS && $xmlSheetNS->ignoredErrors) { + foreach ($xmlSheetNS->ignoredErrors->ignoredError as $ignoredErrorx) { + $ignoredError = self::testSimpleXml($ignoredErrorx); + $this->processIgnoredErrors($ignoredError, $docSheet); + } + } if (!$this->readDataOnly && $xmlSheetNS && $xmlSheetNS->sheetProtection) { $protAttr = $xmlSheetNS->sheetProtection->attributes() ?? []; @@ -1029,6 +1100,7 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet // later we will remove from it real vmlComments $unparsedVmlDrawings = $vmlComments; + $vmlDrawingContents = []; // Loop through VML comments foreach ($vmlComments as $relName => $relPath) { @@ -1037,7 +1109,7 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet try { // no namespace okay - processed with Xpath - $vmlCommentsFile = $this->loadZip($relPath, ''); + $vmlCommentsFile = $this->loadZip($relPath, '', true); $vmlCommentsFile->registerXPathNamespace('v', Namespaces::URN_VML); } catch (Throwable $ex) { //Ignore unparsable vmlDrawings. Later they will be moved from $unparsedVmlDrawings to $unparsedLoadedData @@ -1047,6 +1119,7 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet // Locate VML drawings image relations $drowingImages = []; $VMLDrawingsRelations = dirname($relPath) . '/_rels/' . basename($relPath) . '.rels'; + $vmlDrawingContents[$relName] = $this->getSecurityScannerOrThrow()->scan($this->getFromZipArchive($zip, $relPath)); if ($zip->locateName($VMLDrawingsRelations)) { $relsVMLDrawing = $this->loadZip($VMLDrawingsRelations, Namespaces::RELATIONSHIPS); foreach ($relsVMLDrawing->Relationship as $elex) { @@ -1156,7 +1229,7 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet $unparsedVmlDrawing[$rId] = []; $unparsedVmlDrawing[$rId]['filePath'] = self::dirAdd("$dir/$fileWorksheet", $relPath); $unparsedVmlDrawing[$rId]['relFilePath'] = $relPath; - $unparsedVmlDrawing[$rId]['content'] = $this->securityScanner->scan($this->getFromZipArchive($zip, $unparsedVmlDrawing[$rId]['filePath'])); + $unparsedVmlDrawing[$rId]['content'] = $this->getSecurityScannerOrThrow()->scan($this->getFromZipArchive($zip, $unparsedVmlDrawing[$rId]['filePath'])); unset($unparsedVmlDrawing); } } @@ -1519,6 +1592,14 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet } } } + if ($xmlSheet->legacyDrawing && !$this->readDataOnly) { + foreach ($xmlSheet->legacyDrawing as $drawing) { + $drawingRelId = (string) self::getArrayItem(self::getAttributes($drawing, $xmlNamespaceBase), 'id'); + if (isset($vmlDrawingContents[$drawingRelId])) { + $unparsedLoadedData['sheets'][$docSheet->getCodeName()]['legacyDrawing'] = $vmlDrawingContents[$drawingRelId]; + } + } + } // unparsed drawing AlternateContent $xmlAltDrawing = $this->loadZip((string) $fileDrawing, Namespaces::COMPATIBILITY); @@ -1851,7 +1932,7 @@ private function readRibbon(Spreadsheet $excel, string $customUITarget, ZipArchi if ($dataRels) { // exists and not empty if the ribbon have some pictures (other than internal MSO) $UIRels = simplexml_load_string( - $this->securityScanner->scan($dataRels), + $this->getSecurityScannerOrThrow()->scan($dataRels), 'SimpleXMLElement', Settings::getLibXmlLoaderOptions() ); @@ -2025,7 +2106,7 @@ private function readFormControlProperties(Spreadsheet $excel, string $dir, stri $unparsedCtrlProps[$rId] = []; $unparsedCtrlProps[$rId]['filePath'] = self::dirAdd("$dir/$fileWorksheet", $ctrlProp['Target']); $unparsedCtrlProps[$rId]['relFilePath'] = (string) $ctrlProp['Target']; - $unparsedCtrlProps[$rId]['content'] = $this->securityScanner->scan($this->getFromZipArchive($zip, $unparsedCtrlProps[$rId]['filePath'])); + $unparsedCtrlProps[$rId]['content'] = $this->getSecurityScannerOrThrow()->scan($this->getFromZipArchive($zip, $unparsedCtrlProps[$rId]['filePath'])); } unset($unparsedCtrlProps); } @@ -2055,7 +2136,7 @@ private function readPrinterSettings(Spreadsheet $excel, string $dir, string $fi $unparsedPrinterSettings[$rId] = []; $unparsedPrinterSettings[$rId]['filePath'] = self::dirAdd("$dir/$fileWorksheet", $printerSettings['Target']); $unparsedPrinterSettings[$rId]['relFilePath'] = (string) $printerSettings['Target']; - $unparsedPrinterSettings[$rId]['content'] = $this->securityScanner->scan($this->getFromZipArchive($zip, $unparsedPrinterSettings[$rId]['filePath'])); + $unparsedPrinterSettings[$rId]['content'] = $this->getSecurityScannerOrThrow()->scan($this->getFromZipArchive($zip, $unparsedPrinterSettings[$rId]['filePath'])); } unset($unparsedPrinterSettings); } @@ -2192,4 +2273,48 @@ private static function extractPalette(?SimpleXMLElement $sxml): array return $array; } + + private function processIgnoredErrors(SimpleXMLElement $xml, Worksheet $sheet): void + { + $attributes = self::getAttributes($xml); + $sqref = (string) ($attributes['sqref'] ?? ''); + $numberStoredAsText = (string) ($attributes['numberStoredAsText'] ?? ''); + $formula = (string) ($attributes['formula'] ?? ''); + $twoDigitTextYear = (string) ($attributes['twoDigitTextYear'] ?? ''); + $evalError = (string) ($attributes['evalError'] ?? ''); + if (!empty($sqref)) { + $explodedSqref = explode(' ', $sqref); + $pattern1 = '/^([A-Z]{1,3})([0-9]{1,7})(:([A-Z]{1,3})([0-9]{1,7}))?$/'; + foreach ($explodedSqref as $sqref1) { + if (preg_match($pattern1, $sqref1, $matches) === 1) { + $firstRow = $matches[2]; + $firstCol = $matches[1]; + if (array_key_exists(3, $matches)) { + $lastCol = $matches[4]; + $lastRow = $matches[5]; + } else { + $lastCol = $firstCol; + $lastRow = $firstRow; + } + ++$lastCol; + for ($row = $firstRow; $row <= $lastRow; ++$row) { + for ($col = $firstCol; $col !== $lastCol; ++$col) { + if ($numberStoredAsText === '1') { + $sheet->getCell("$col$row")->getIgnoredErrors()->setNumberStoredAsText(true); + } + if ($formula === '1') { + $sheet->getCell("$col$row")->getIgnoredErrors()->setFormula(true); + } + if ($twoDigitTextYear === '1') { + $sheet->getCell("$col$row")->getIgnoredErrors()->setTwoDigitTextYear(true); + } + if ($evalError === '1') { + $sheet->getCell("$col$row")->getIgnoredErrors()->setEvalError(true); + } + } + } + } + } + } + } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Chart.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Chart.php index d42df9a..c5a59f5 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Chart.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Chart.php @@ -4,6 +4,7 @@ use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError; use PhpOffice\PhpSpreadsheet\Chart\Axis; +use PhpOffice\PhpSpreadsheet\Chart\AxisText; use PhpOffice\PhpSpreadsheet\Chart\ChartColor; use PhpOffice\PhpSpreadsheet\Chart\DataSeries; use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues; @@ -76,16 +77,28 @@ public function readChart(SimpleXMLElement $chartElements, $chartName) $yAxis = new Axis(); $autoTitleDeleted = null; $chartNoFill = false; + $chartBorderLines = null; + $chartFillColor = null; $gradientArray = []; $gradientLin = null; $roundedCorners = false; + $gapWidth = null; + $useUpBars = null; + $useDownBars = null; foreach ($chartElementsC as $chartElementKey => $chartElement) { switch ($chartElementKey) { case 'spPr': - $possibleNoFill = $chartElementsC->spPr->children($this->aNamespace); - if (isset($possibleNoFill->noFill)) { + $children = $chartElementsC->spPr->children($this->aNamespace); + if (isset($children->noFill)) { $chartNoFill = true; } + if (isset($children->solidFill)) { + $chartFillColor = $this->readColor($children->solidFill); + } + if (isset($children->ln)) { + $chartBorderLines = new GridLines(); + $this->readLineStyle($chartElementsC, $chartBorderLines); + } break; case 'roundedCorners': @@ -157,6 +170,9 @@ public function readChart(SimpleXMLElement $chartElements, $chartName) $axisColorArray = $this->readColor($sppr->solidFill); $xAxis->setFillParameters($axisColorArray['value'], $axisColorArray['alpha'], $axisColorArray['type']); } + if (isset($chartDetail->spPr->ln->noFill)) { + $xAxis->setNoFill(true); + } } if (isset($chartDetail->majorGridlines)) { $majorGridlines = new GridLines(); @@ -227,6 +243,9 @@ public function readChart(SimpleXMLElement $chartElements, $chartName) $axisColorArray = $this->readColor($sppr->solidFill); $whichAxis->setFillParameters($axisColorArray['value'], $axisColorArray['alpha'], $axisColorArray['type']); } + if (isset($sppr->ln->noFill)) { + $whichAxis->setNoFill(true); + } } if ($whichAxis !== null && isset($chartDetail->majorGridlines)) { $majorGridlines = new GridLines(); @@ -316,6 +335,15 @@ public function readChart(SimpleXMLElement $chartElements, $chartName) break; case 'stockChart': $plotSeries[] = $this->chartDataSeries($chartDetail, $chartDetailKey); + if (isset($chartDetail->upDownBars->gapWidth)) { + $gapWidth = self::getAttribute($chartDetail->upDownBars->gapWidth, 'val', 'integer'); + } + if (isset($chartDetail->upDownBars->upBars)) { + $useUpBars = true; + } + if (isset($chartDetail->upDownBars->downBars)) { + $useDownBars = true; + } $plotAttributes = $this->readChartAttributes($chartDetail); break; @@ -332,6 +360,15 @@ public function readChart(SimpleXMLElement $chartElements, $chartName) if (!empty($gradientArray)) { $plotArea->setGradientFillProperties($gradientArray, $gradientLin); } + if (is_int($gapWidth)) { + $plotArea->setGapWidth($gapWidth); + } + if ($useUpBars === true) { + $plotArea->setUseUpBars(true); + } + if ($useDownBars === true) { + $plotArea->setUseDownBars(true); + } break; case 'plotVisOnly': @@ -350,6 +387,10 @@ public function readChart(SimpleXMLElement $chartElements, $chartName) $legendPos = 'r'; $legendLayout = null; $legendOverlay = false; + $legendBorderLines = null; + $legendFillColor = null; + $legendText = null; + $addLegendText = false; foreach ($chartDetails as $chartDetailKey => $chartDetail) { $chartDetail = Xlsx::testSimpleXml($chartDetail); switch ($chartDetailKey) { @@ -364,10 +405,45 @@ public function readChart(SimpleXMLElement $chartElements, $chartName) case 'layout': $legendLayout = $this->chartLayoutDetails($chartDetail); + break; + case 'spPr': + $children = $chartDetails->spPr->children($this->aNamespace); + if (isset($children->solidFill)) { + $legendFillColor = $this->readColor($children->solidFill); + } + if (isset($children->ln)) { + $legendBorderLines = new GridLines(); + $this->readLineStyle($chartDetails, $legendBorderLines); + } + + break; + case 'txPr': + $children = $chartDetails->txPr->children($this->aNamespace); + $addLegendText = false; + $legendText = new AxisText(); + if (isset($children->p->pPr->defRPr->solidFill)) { + $colorArray = $this->readColor($children->p->pPr->defRPr->solidFill); + $legendText->getFillColorObject()->setColorPropertiesArray($colorArray); + $addLegendText = true; + } + if (isset($children->p->pPr->defRPr->effectLst)) { + $this->readEffects($children->p->pPr->defRPr, $legendText, false); + $addLegendText = true; + } + break; } } $legend = new Legend("$legendPos", $legendLayout, (bool) $legendOverlay); + if ($legendFillColor !== null) { + $legend->getFillColor()->setColorPropertiesArray($legendFillColor); + } + if ($legendBorderLines !== null) { + $legend->setBorderLines($legendBorderLines); + } + if ($addLegendText) { + $legend->setLegendText($legendText); + } break; } @@ -378,6 +454,12 @@ public function readChart(SimpleXMLElement $chartElements, $chartName) if ($chartNoFill) { $chart->setNoFill(true); } + if ($chartFillColor !== null) { + $chart->getFillColor()->setColorPropertiesArray($chartFillColor); + } + if ($chartBorderLines !== null) { + $chart->setBorderLines($chartBorderLines); + } $chart->setRoundedCorners($roundedCorners); if (is_bool($autoTitleDeleted)) { $chart->setAutoTitleDeleted($autoTitleDeleted); @@ -402,6 +484,7 @@ private function chartTitle(SimpleXMLElement $titleDetails): Title { $caption = []; $titleLayout = null; + $titleOverlay = false; foreach ($titleDetails as $titleDetailKey => $chartDetail) { $chartDetail = Xlsx::testSimpleXml($chartDetail); switch ($titleDetailKey) { @@ -424,6 +507,10 @@ private function chartTitle(SimpleXMLElement $titleDetails): Title } } + break; + case 'overlay': + $titleOverlay = self::getAttribute($chartDetail, 'val', 'boolean'); + break; case 'layout': $titleLayout = $this->chartLayoutDetails($chartDetail); @@ -432,7 +519,7 @@ private function chartTitle(SimpleXMLElement $titleDetails): Title } } - return new Title($caption, $titleLayout); + return new Title($caption, $titleLayout, (bool) $titleOverlay); } private function chartLayoutDetails(SimpleXMLElement $chartDetail): ?Layout @@ -1077,6 +1164,37 @@ private function parseRichText(SimpleXMLElement $titleDetailPart): RichText return $value; } + private function parseFont(SimpleXMLElement $titleDetailPart): ?Font + { + if (!isset($titleDetailPart->pPr->defRPr)) { + return null; + } + $fontArray = []; + $fontArray['size'] = self::getAttribute($titleDetailPart->pPr->defRPr, 'sz', 'integer'); + $fontArray['bold'] = self::getAttribute($titleDetailPart->pPr->defRPr, 'b', 'boolean'); + $fontArray['italic'] = self::getAttribute($titleDetailPart->pPr->defRPr, 'i', 'boolean'); + $fontArray['underscore'] = self::getAttribute($titleDetailPart->pPr->defRPr, 'u', 'string'); + $fontArray['strikethrough'] = self::getAttribute($titleDetailPart->pPr->defRPr, 'strike', 'string'); + + if (isset($titleDetailPart->pPr->defRPr->latin)) { + $fontArray['latin'] = self::getAttribute($titleDetailPart->pPr->defRPr->latin, 'typeface', 'string'); + } + if (isset($titleDetailPart->pPr->defRPr->ea)) { + $fontArray['eastAsian'] = self::getAttribute($titleDetailPart->pPr->defRPr->ea, 'typeface', 'string'); + } + if (isset($titleDetailPart->pPr->defRPr->cs)) { + $fontArray['complexScript'] = self::getAttribute($titleDetailPart->pPr->defRPr->cs, 'typeface', 'string'); + } + if (isset($titleDetailPart->pPr->defRPr->solidFill)) { + $fontArray['chartColor'] = new ChartColor($this->readColor($titleDetailPart->pPr->defRPr->solidFill)); + } + $font = new Font(); + $font->setSize(null, true); + $font->applyFromArray($fontArray); + + return $font; + } + /** * @param ?SimpleXMLElement $chartDetail */ @@ -1123,8 +1241,13 @@ private function readChartAttributes($chartDetail): array } if (isset($chartDetail->dLbls->txPr)) { $txpr = $chartDetail->dLbls->txPr->children($this->aNamespace); - if (isset($txpr->p->pPr->defRPr->solidFill)) { - $plotAttributes['labelFontColor'] = new ChartColor($this->readColor($txpr->p->pPr->defRPr->solidFill)); + if (isset($txpr->p)) { + $plotAttributes['labelFont'] = $this->parseFont($txpr->p); + if (isset($txpr->p->pPr->defRPr->effectLst)) { + $labelEffects = new GridLines(); + $this->readEffects($txpr->p->pPr->defRPr, $labelEffects, false); + $plotAttributes['labelEffects'] = $labelEffects; + } } } } @@ -1171,13 +1294,19 @@ private function setChartAttributes(Layout $plotArea, $plotAttributes): void } } - private function readEffects(SimpleXMLElement $chartDetail, ?ChartProperties $chartObject): void + private function readEffects(SimpleXMLElement $chartDetail, ?ChartProperties $chartObject, bool $getSppr = true): void { - if (!isset($chartObject, $chartDetail->spPr)) { + if (!isset($chartObject)) { return; } - $sppr = $chartDetail->spPr->children($this->aNamespace); - + if ($getSppr) { + if (!isset($chartDetail->spPr)) { + return; + } + $sppr = $chartDetail->spPr->children($this->aNamespace); + } else { + $sppr = $chartDetail; + } if (isset($sppr->effectLst->glow)) { $axisGlowSize = (float) self::getAttribute($sppr->effectLst->glow, 'rad', 'integer') / ChartProperties::POINTS_WIDTH_MULTIPLIER; if ($axisGlowSize != 0.0) { @@ -1407,13 +1536,30 @@ private function setAxisProperties(SimpleXMLElement $chartDetail, ?Axis $whichAx } if (isset($chartDetail->txPr)) { $children = $chartDetail->txPr->children($this->aNamespace); + $addAxisText = false; + $axisText = new AxisText(); if (isset($children->bodyPr)) { /** @var string */ $textRotation = self::getAttribute($children->bodyPr, 'rot', 'string'); if (is_numeric($textRotation)) { - $whichAxis->setAxisOption('textRotation', (string) ChartProperties::xmlToAngle($textRotation)); + $axisText->setRotation((int) ChartProperties::xmlToAngle($textRotation)); + $addAxisText = true; + } + } + if (isset($children->p->pPr->defRPr)) { + $font = $this->parseFont($children->p); + if ($font !== null) { + $axisText->setFont($font); + $addAxisText = true; } } + if (isset($children->p->pPr->defRPr->effectLst)) { + $this->readEffects($children->p->pPr->defRPr, $axisText, false); + $addAxisText = true; + } + if ($addAxisText) { + $whichAxis->setAxisText($axisText); + } } } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php index aa6b62b..59bf5b8 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php @@ -163,7 +163,7 @@ private function readConditionalStyles(SimpleXMLElement $xmlSheet): array $conditionals = []; foreach ($xmlSheet->conditionalFormatting as $conditional) { foreach ($conditional->cfRule as $cfRule) { - if (Conditional::isValidConditionType((string) $cfRule['type']) && isset($this->dxfs[(int) ($cfRule['dxfId'])])) { + if (Conditional::isValidConditionType((string) $cfRule['type']) && (!isset($cfRule['dxfId']) || isset($this->dxfs[(int) ($cfRule['dxfId'])]))) { $conditionals[(string) $conditional['sqref']][(int) ($cfRule['priority'])] = $cfRule; } elseif ((string) $cfRule['type'] == Conditional::CONDITION_DATABAR) { $conditionals[(string) $conditional['sqref']][(int) ($cfRule['priority'])] = $cfRule; @@ -197,6 +197,7 @@ private function readStyleRules(array $cfRules, SimpleXMLElement $extLst): array $objConditional = new Conditional(); $objConditional->setConditionType((string) $cfRule['type']); $objConditional->setOperatorType((string) $cfRule['operator']); + $objConditional->setNoFormatSet(!isset($cfRule['dxfId'])); if ((string) $cfRule['text'] != '') { $objConditional->setText((string) $cfRule['text']); @@ -227,7 +228,7 @@ private function readStyleRules(array $cfRules, SimpleXMLElement $extLst): array $objConditional->setDataBar( $this->readDataBarOfConditionalRule($cfRule, $conditionalFormattingRuleExtensions) // @phpstan-ignore-line ); - } else { + } elseif (isset($cfRule['dxfId'])) { $objConditional->setStyle(clone $this->dxfs[(int) ($cfRule['dxfId'])]); } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/DataValidations.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/DataValidations.php index dac7623..210c322 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/DataValidations.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/DataValidations.php @@ -22,6 +22,18 @@ public function __construct(Worksheet $workSheet, SimpleXMLElement $worksheetXml public function load(): void { + foreach ($this->worksheetXml->dataValidations->dataValidation as $dataValidation) { + // Uppercase coordinate + $range = strtoupper((string) $dataValidation['sqref']); + $rangeSet = explode(' ', $range); + foreach ($rangeSet as $range) { + if (preg_match('/^[A-Z]{1,3}\\d{1,7}/', $range, $matches) === 1) { + // Ensure left/top row of range exists, thereby + // adjusting high row/column. + $this->worksheet->getCell($matches[0]); + } + } + } foreach ($this->worksheetXml->dataValidations->dataValidation as $dataValidation) { // Uppercase coordinate $range = strtoupper((string) $dataValidation['sqref']); diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/PageSetup.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/PageSetup.php index fb55cb2..ab57548 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/PageSetup.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/PageSetup.php @@ -151,8 +151,9 @@ private function pageBreaks(SimpleXMLElement $xmlSheet, Worksheet $worksheet): v private function rowBreaks(SimpleXMLElement $xmlSheet, Worksheet $worksheet): void { foreach ($xmlSheet->rowBreaks->brk as $brk) { + $rowBreakMax = isset($brk['max']) ? ((int) $brk['max']) : -1; if ($brk['man']) { - $worksheet->setBreak("A{$brk['id']}", Worksheet::BREAK_ROW); + $worksheet->setBreak("A{$brk['id']}", Worksheet::BREAK_ROW, $rowBreakMax); } } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Properties.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Properties.php index 72addff..0d4701a 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Properties.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Properties.php @@ -73,6 +73,9 @@ public function readExtendedProperties(string $propertyData): void if (isset($xmlCore->Manager)) { $this->docProps->setManager((string) $xmlCore->Manager); } + if (isset($xmlCore->HyperlinkBase)) { + $this->docProps->setHyperlinkBase((string) $xmlCore->HyperlinkBase); + } } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/SharedFormula.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/SharedFormula.php new file mode 100644 index 0000000..fb7a393 --- /dev/null +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/SharedFormula.php @@ -0,0 +1,26 @@ +master = $master; + $this->formula = $formula; + } + + public function master(): string + { + return $this->master; + } + + public function formula(): string + { + return $this->formula; + } +} diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Styles.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Styles.php index 5b089fa..5a360fd 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Styles.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Styles.php @@ -136,6 +136,10 @@ public function readFontStyle(Font $fontStyle, SimpleXMLElement $fontStyleXml): } } } + if (isset($fontStyleXml->scheme)) { + $attr = $this->getStyleAttributes($fontStyleXml->scheme); + $fontStyle->setScheme((string) $attr['val']); + } } private function readNumberFormat(NumberFormat $numfmtStyle, SimpleXMLElement $numfmtStyleXml): void @@ -206,11 +210,21 @@ public function readBorderStyle(Borders $borderStyle, SimpleXMLElement $borderSt $borderStyle->setDiagonalDirection(Borders::DIAGONAL_BOTH); } - $this->readBorder($borderStyle->getLeft(), $borderStyleXml->left); - $this->readBorder($borderStyle->getRight(), $borderStyleXml->right); - $this->readBorder($borderStyle->getTop(), $borderStyleXml->top); - $this->readBorder($borderStyle->getBottom(), $borderStyleXml->bottom); - $this->readBorder($borderStyle->getDiagonal(), $borderStyleXml->diagonal); + if (isset($borderStyleXml->left)) { + $this->readBorder($borderStyle->getLeft(), $borderStyleXml->left); + } + if (isset($borderStyleXml->right)) { + $this->readBorder($borderStyle->getRight(), $borderStyleXml->right); + } + if (isset($borderStyleXml->top)) { + $this->readBorder($borderStyle->getTop(), $borderStyleXml->top); + } + if (isset($borderStyleXml->bottom)) { + $this->readBorder($borderStyle->getBottom(), $borderStyleXml->bottom); + } + if (isset($borderStyleXml->diagonal)) { + $this->readBorder($borderStyle->getDiagonal(), $borderStyleXml->diagonal); + } } private function getAttribute(SimpleXMLElement $xml, string $attribute): string @@ -233,6 +247,8 @@ private function readBorder(Border $border, SimpleXMLElement $borderXml): void $style = $this->getAttribute($borderXml, 'style'); if ($style !== '') { $border->setBorderStyle((string) $style); + } else { + $border->setBorderStyle(Border::BORDER_NONE); } if (isset($borderXml->color)) { $border->getColor()->setARGB($this->readColor($borderXml->color)); @@ -241,10 +257,14 @@ private function readBorder(Border $border, SimpleXMLElement $borderXml): void public function readAlignmentStyle(Alignment $alignment, SimpleXMLElement $alignmentXml): void { - $horizontal = $this->getAttribute($alignmentXml, 'horizontal'); - $alignment->setHorizontal($horizontal); - $vertical = $this->getAttribute($alignmentXml, 'vertical'); - $alignment->setVertical((string) $vertical); + $horizontal = (string) $this->getAttribute($alignmentXml, 'horizontal'); + if ($horizontal !== '') { + $alignment->setHorizontal($horizontal); + } + $vertical = (string) $this->getAttribute($alignmentXml, 'vertical'); + if ($vertical !== '') { + $alignment->setVertical($vertical); + } $textRotation = (int) $this->getAttribute($alignmentXml, 'textRotation'); if ($textRotation > 90) { diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml.php index 565a5af..6be26fc 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml.php @@ -9,6 +9,7 @@ use PhpOffice\PhpSpreadsheet\Cell\DataType; use PhpOffice\PhpSpreadsheet\DefinedName; use PhpOffice\PhpSpreadsheet\Reader\Security\XmlScanner; +use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Namespaces; use PhpOffice\PhpSpreadsheet\Reader\Xml\PageSettings; use PhpOffice\PhpSpreadsheet\Reader\Xml\Properties; use PhpOffice\PhpSpreadsheet\Reader\Xml\Style; @@ -26,6 +27,8 @@ */ class Xml extends BaseReader { + public const NAMESPACES_SS = 'urn:schemas-microsoft-com:office:spreadsheet'; + /** * Formats. * @@ -42,6 +45,7 @@ public function __construct() $this->securityScanner = XmlScanner::getInstance($this); } + /** @var string */ private $fileContents = ''; public static function xmlMappings(): array @@ -73,7 +77,7 @@ public function canRead(string $filename): bool ]; // Open file - $data = file_get_contents($filename); + $data = file_get_contents($filename) ?: ''; // Why? //$data = str_replace("'", '"', $data); // fix headers with single quote @@ -112,7 +116,7 @@ public function trySimpleXMLLoadString($filename) { try { $xml = simplexml_load_string( - $this->securityScanner->scan($this->fileContents ?: file_get_contents($filename)), + $this->getSecurityScannerOrThrow()->scan($this->fileContents ?: file_get_contents($filename)), 'SimpleXMLElement', Settings::getLibXmlLoaderOptions() ); @@ -145,11 +149,9 @@ public function listWorksheetNames($filename) throw new Exception("Problem reading {$filename}"); } - $namespaces = $xml->getNamespaces(true); - - $xml_ss = $xml->children($namespaces['ss']); + $xml_ss = $xml->children(self::NAMESPACES_SS); foreach ($xml_ss->Worksheet as $worksheet) { - $worksheet_ss = self::getAttributes($worksheet, $namespaces['ss']); + $worksheet_ss = self::getAttributes($worksheet, self::NAMESPACES_SS); $worksheetNames[] = (string) $worksheet_ss['Name']; } @@ -177,12 +179,10 @@ public function listWorksheetInfo($filename) throw new Exception("Problem reading {$filename}"); } - $namespaces = $xml->getNamespaces(true); - $worksheetID = 1; - $xml_ss = $xml->children($namespaces['ss']); + $xml_ss = $xml->children(self::NAMESPACES_SS); foreach ($xml_ss->Worksheet as $worksheet) { - $worksheet_ss = self::getAttributes($worksheet, $namespaces['ss']); + $worksheet_ss = self::getAttributes($worksheet, self::NAMESPACES_SS); $tmpInfo = []; $tmpInfo['worksheetName'] = ''; @@ -230,6 +230,19 @@ public function listWorksheetInfo($filename) return $worksheetInfo; } + /** + * Loads Spreadsheet from string. + */ + public function loadSpreadsheetFromString(string $contents): Spreadsheet + { + // Create new Spreadsheet + $spreadsheet = new Spreadsheet(); + $spreadsheet->removeSheetByIndex(0); + + // Load into this instance + return $this->loadIntoExisting($contents, $spreadsheet, true); + } + /** * Loads Spreadsheet from file. */ @@ -244,17 +257,19 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet } /** - * Loads from file into Spreadsheet instance. - * - * @param string $filename + * Loads from file or contents into Spreadsheet instance. * - * @return Spreadsheet + * @param string $filename file name if useContents is false else file contents */ - public function loadIntoExisting($filename, Spreadsheet $spreadsheet) + public function loadIntoExisting(string $filename, Spreadsheet $spreadsheet, bool $useContents = false): Spreadsheet { - File::assertFile($filename); - if (!$this->canRead($filename)) { - throw new Exception($filename . ' is an Invalid Spreadsheet file.'); + if ($useContents) { + $this->fileContents = $filename; + } else { + File::assertFile($filename); + if (!$this->canRead($filename)) { + throw new Exception($filename . ' is an Invalid Spreadsheet file.'); + } } $xml = $this->trySimpleXMLLoadString($filename); @@ -267,14 +282,17 @@ public function loadIntoExisting($filename, Spreadsheet $spreadsheet) (new Properties($spreadsheet))->readProperties($xml, $namespaces); $this->styles = (new Style())->parseStyles($xml, $namespaces); + if (isset($this->styles['Default'])) { + $spreadsheet->getCellXfCollection()[0]->applyFromArray($this->styles['Default']); + } $worksheetID = 0; - $xml_ss = $xml->children($namespaces['ss']); + $xml_ss = $xml->children(self::NAMESPACES_SS); /** @var null|SimpleXMLElement $worksheetx */ foreach ($xml_ss->Worksheet as $worksheetx) { $worksheet = $worksheetx ?? new SimpleXMLElement(''); - $worksheet_ss = self::getAttributes($worksheet, $namespaces['ss']); + $worksheet_ss = self::getAttributes($worksheet, self::NAMESPACES_SS); if ( isset($this->loadSheetsOnly, $worksheet_ss['Name']) && @@ -294,11 +312,15 @@ public function loadIntoExisting($filename, Spreadsheet $spreadsheet) // the worksheet name in line with the formula, not the reverse $spreadsheet->getActiveSheet()->setTitle($worksheetName, false, false); } + if (isset($worksheet_ss['Protected'])) { + $protection = (string) $worksheet_ss['Protected'] === '1'; + $spreadsheet->getActiveSheet()->getProtection()->setSheet($protection); + } // locally scoped defined names if (isset($worksheet->Names[0])) { foreach ($worksheet->Names[0] as $definedName) { - $definedName_ss = self::getAttributes($definedName, $namespaces['ss']); + $definedName_ss = self::getAttributes($definedName, self::NAMESPACES_SS); $name = (string) $definedName_ss['Name']; $definedValue = (string) $definedName_ss['RefersTo']; $convertedValue = AddressHelper::convertFormulaToA1($definedValue); @@ -312,15 +334,35 @@ public function loadIntoExisting($filename, Spreadsheet $spreadsheet) $columnID = 'A'; if (isset($worksheet->Table->Column)) { foreach ($worksheet->Table->Column as $columnData) { - $columnData_ss = self::getAttributes($columnData, $namespaces['ss']); + $columnData_ss = self::getAttributes($columnData, self::NAMESPACES_SS); + $colspan = 0; + if (isset($columnData_ss['Span'])) { + $spanAttr = (string) $columnData_ss['Span']; + if (is_numeric($spanAttr)) { + $colspan = max(0, (int) $spanAttr); + } + } if (isset($columnData_ss['Index'])) { $columnID = Coordinate::stringFromColumnIndex((int) $columnData_ss['Index']); } + $columnWidth = null; if (isset($columnData_ss['Width'])) { $columnWidth = $columnData_ss['Width']; - $spreadsheet->getActiveSheet()->getColumnDimension($columnID)->setWidth($columnWidth / 5.4); } - ++$columnID; + $columnVisible = null; + if (isset($columnData_ss['Hidden'])) { + $columnVisible = ((string) $columnData_ss['Hidden']) !== '1'; + } + while ($colspan >= 0) { + if (isset($columnWidth)) { + $spreadsheet->getActiveSheet()->getColumnDimension($columnID)->setWidth($columnWidth / 5.4); + } + if (isset($columnVisible)) { + $spreadsheet->getActiveSheet()->getColumnDimension($columnID)->setVisible($columnVisible); + } + ++$columnID; + --$colspan; + } } } @@ -329,14 +371,18 @@ public function loadIntoExisting($filename, Spreadsheet $spreadsheet) $additionalMergedCells = 0; foreach ($worksheet->Table->Row as $rowData) { $rowHasData = false; - $row_ss = self::getAttributes($rowData, $namespaces['ss']); + $row_ss = self::getAttributes($rowData, self::NAMESPACES_SS); if (isset($row_ss['Index'])) { $rowID = (int) $row_ss['Index']; } + if (isset($row_ss['Hidden'])) { + $rowVisible = ((string) $row_ss['Hidden']) !== '1'; + $spreadsheet->getActiveSheet()->getRowDimension($rowID)->setVisible($rowVisible); + } $columnID = 'A'; foreach ($rowData->Cell as $cell) { - $cell_ss = self::getAttributes($cell, $namespaces['ss']); + $cell_ss = self::getAttributes($cell, self::NAMESPACES_SS); if (isset($cell_ss['Index'])) { $columnID = Coordinate::stringFromColumnIndex((int) $cell_ss['Index']); } @@ -378,7 +424,7 @@ public function loadIntoExisting($filename, Spreadsheet $spreadsheet) $cellData = $cell->Data; $cellValue = (string) $cellData; $type = DataType::TYPE_NULL; - $cellData_ss = self::getAttributes($cellData, $namespaces['ss']); + $cellData_ss = self::getAttributes($cellData, self::NAMESPACES_SS); if (isset($cellData_ss['Type'])) { $cellDataType = $cellData_ss['Type']; switch ($cellDataType) { @@ -436,7 +482,7 @@ public function loadIntoExisting($filename, Spreadsheet $spreadsheet) } if (isset($cell->Comment)) { - $this->parseCellComment($cell->Comment, $namespaces, $spreadsheet, $columnID, $rowID); + $this->parseCellComment($cell->Comment, $spreadsheet, $columnID, $rowID); } if (isset($cell_ss['StyleID'])) { @@ -465,11 +511,57 @@ public function loadIntoExisting($filename, Spreadsheet $spreadsheet) ++$rowID; } + } - if (isset($namespaces['x'])) { - $xmlX = $worksheet->children($namespaces['x']); - if (isset($xmlX->WorksheetOptions)) { - (new PageSettings($xmlX, $namespaces))->loadPageSettings($spreadsheet); + $dataValidations = new Xml\DataValidations(); + $dataValidations->loadDataValidations($worksheet, $spreadsheet); + $xmlX = $worksheet->children(Namespaces::URN_EXCEL); + if (isset($xmlX->WorksheetOptions)) { + if (isset($xmlX->WorksheetOptions->FreezePanes)) { + $freezeRow = $freezeColumn = 1; + if (isset($xmlX->WorksheetOptions->SplitHorizontal)) { + $freezeRow = (int) $xmlX->WorksheetOptions->SplitHorizontal + 1; + } + if (isset($xmlX->WorksheetOptions->SplitVertical)) { + $freezeColumn = (int) $xmlX->WorksheetOptions->SplitVertical + 1; + } + $spreadsheet->getActiveSheet()->freezePane(Coordinate::stringFromColumnIndex($freezeColumn) . (string) $freezeRow); + } + (new PageSettings($xmlX))->loadPageSettings($spreadsheet); + if (isset($xmlX->WorksheetOptions->TopRowVisible, $xmlX->WorksheetOptions->LeftColumnVisible)) { + $leftTopRow = (string) $xmlX->WorksheetOptions->TopRowVisible; + $leftTopColumn = (string) $xmlX->WorksheetOptions->LeftColumnVisible; + if (is_numeric($leftTopRow) && is_numeric($leftTopColumn)) { + $leftTopCoordinate = Coordinate::stringFromColumnIndex((int) $leftTopColumn + 1) . (string) ($leftTopRow + 1); + $spreadsheet->getActiveSheet()->setTopLeftCell($leftTopCoordinate); + } + } + $rangeCalculated = false; + if (isset($xmlX->WorksheetOptions->Panes->Pane->RangeSelection)) { + if (1 === preg_match('/^R(\d+)C(\d+):R(\d+)C(\d+)$/', (string) $xmlX->WorksheetOptions->Panes->Pane->RangeSelection, $selectionMatches)) { + $selectedCell = Coordinate::stringFromColumnIndex((int) $selectionMatches[2]) + . $selectionMatches[1] + . ':' + . Coordinate::stringFromColumnIndex((int) $selectionMatches[4]) + . $selectionMatches[3]; + $spreadsheet->getActiveSheet()->setSelectedCells($selectedCell); + $rangeCalculated = true; + } + } + if (!$rangeCalculated) { + if (isset($xmlX->WorksheetOptions->Panes->Pane->ActiveRow)) { + $activeRow = (string) $xmlX->WorksheetOptions->Panes->Pane->ActiveRow; + } else { + $activeRow = 0; + } + if (isset($xmlX->WorksheetOptions->Panes->Pane->ActiveCol)) { + $activeColumn = (string) $xmlX->WorksheetOptions->Panes->Pane->ActiveCol; + } else { + $activeColumn = 0; + } + if (is_numeric($activeRow) && is_numeric($activeColumn)) { + $selectedCell = Coordinate::stringFromColumnIndex((int) $activeColumn + 1) . (string) ($activeRow + 1); + $spreadsheet->getActiveSheet()->setSelectedCells($selectedCell); } } } @@ -477,10 +569,14 @@ public function loadIntoExisting($filename, Spreadsheet $spreadsheet) } // Globally scoped defined names - $activeWorksheet = $spreadsheet->setActiveSheetIndex(0); + $activeSheetIndex = 0; + if (isset($xml->ExcelWorkbook->ActiveSheet)) { + $activeSheetIndex = (int) (string) $xml->ExcelWorkbook->ActiveSheet; + } + $activeWorksheet = $spreadsheet->setActiveSheetIndex($activeSheetIndex); if (isset($xml->Names[0])) { foreach ($xml->Names[0] as $definedName) { - $definedName_ss = self::getAttributes($definedName, $namespaces['ss']); + $definedName_ss = self::getAttributes($definedName, self::NAMESPACES_SS); $name = (string) $definedName_ss['Name']; $definedValue = (string) $definedName_ss['RefersTo']; $convertedValue = AddressHelper::convertFormulaToA1($definedValue); @@ -497,12 +593,11 @@ public function loadIntoExisting($filename, Spreadsheet $spreadsheet) protected function parseCellComment( SimpleXMLElement $comment, - array $namespaces, Spreadsheet $spreadsheet, string $columnID, int $rowID ): void { - $commentAttributes = $comment->attributes($namespaces['ss']); + $commentAttributes = $comment->attributes(self::NAMESPACES_SS); $author = 'unknown'; if (isset($commentAttributes->Author)) { $author = (string) $commentAttributes->Author; diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/DataValidations.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/DataValidations.php new file mode 100644 index 0000000..31748cb --- /dev/null +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/DataValidations.php @@ -0,0 +1,177 @@ + DataValidation::OPERATOR_BETWEEN, + 'equal' => DataValidation::OPERATOR_EQUAL, + 'greater' => DataValidation::OPERATOR_GREATERTHAN, + 'greaterorequal' => DataValidation::OPERATOR_GREATERTHANOREQUAL, + 'less' => DataValidation::OPERATOR_LESSTHAN, + 'lessorequal' => DataValidation::OPERATOR_LESSTHANOREQUAL, + 'notbetween' => DataValidation::OPERATOR_NOTBETWEEN, + 'notequal' => DataValidation::OPERATOR_NOTEQUAL, + ]; + + private const TYPE_MAPPINGS = [ + 'textlength' => DataValidation::TYPE_TEXTLENGTH, + ]; + + private int $thisRow = 0; + + private int $thisColumn = 0; + + private function replaceR1C1(array $matches): string + { + return AddressHelper::convertToA1($matches[0], $this->thisRow, $this->thisColumn, false); + } + + public function loadDataValidations(SimpleXMLElement $worksheet, Spreadsheet $spreadsheet): void + { + $xmlX = $worksheet->children(Namespaces::URN_EXCEL); + $sheet = $spreadsheet->getActiveSheet(); + /** @var callable */ + $pregCallback = [$this, 'replaceR1C1']; + foreach ($xmlX->DataValidation as $dataValidation) { + $cells = []; + $validation = new DataValidation(); + + // set defaults + $validation->setShowDropDown(true); + $validation->setShowInputMessage(true); + $validation->setShowErrorMessage(true); + $validation->setShowDropDown(true); + $this->thisRow = 1; + $this->thisColumn = 1; + + foreach ($dataValidation as $tagName => $tagValue) { + $tagValue = (string) $tagValue; + $tagValueLower = strtolower($tagValue); + switch ($tagName) { + case 'Range': + foreach (explode(',', $tagValue) as $range) { + $cell = ''; + if (preg_match('/^R(\d+)C(\d+):R(\d+)C(\d+)$/', (string) $range, $selectionMatches) === 1) { + // range + $firstCell = Coordinate::stringFromColumnIndex((int) $selectionMatches[2]) + . $selectionMatches[1]; + $cell = $firstCell + . ':' + . Coordinate::stringFromColumnIndex((int) $selectionMatches[4]) + . $selectionMatches[3]; + $this->thisRow = (int) $selectionMatches[1]; + $this->thisColumn = (int) $selectionMatches[2]; + $sheet->getCell($firstCell); + } elseif (preg_match('/^R(\d+)C(\d+)$/', (string) $range, $selectionMatches) === 1) { + // cell + $cell = Coordinate::stringFromColumnIndex((int) $selectionMatches[2]) + . $selectionMatches[1]; + $sheet->getCell($cell); + $this->thisRow = (int) $selectionMatches[1]; + $this->thisColumn = (int) $selectionMatches[2]; + } elseif (preg_match('/^C(\d+)$/', (string) $range, $selectionMatches) === 1) { + // column + $firstCell = Coordinate::stringFromColumnIndex((int) $selectionMatches[1]) + . '1'; + $cell = $firstCell + . ':' + . Coordinate::stringFromColumnIndex((int) $selectionMatches[1]) + . ((string) AddressRange::MAX_ROW); + $this->thisColumn = (int) $selectionMatches[1]; + $sheet->getCell($firstCell); + } elseif (preg_match('/^R(\d+)$/', (string) $range, $selectionMatches)) { + // row + $firstCell = 'A' + . $selectionMatches[1]; + $cell = $firstCell + . ':' + . AddressRange::MAX_COLUMN + . $selectionMatches[1]; + $this->thisRow = (int) $selectionMatches[1]; + $sheet->getCell($firstCell); + } + + $validation->setSqref($cell); + $stRange = $sheet->shrinkRangeToFit($cell); + $cells = array_merge($cells, Coordinate::extractAllCellReferencesInRange($stRange)); + } + + break; + case 'Type': + $validation->setType(self::TYPE_MAPPINGS[$tagValueLower] ?? $tagValueLower); + + break; + case 'Qualifier': + $validation->setOperator(self::OPERATOR_MAPPINGS[$tagValueLower] ?? $tagValueLower); + + break; + case 'InputTitle': + $validation->setPromptTitle($tagValue); + + break; + case 'InputMessage': + $validation->setPrompt($tagValue); + + break; + case 'InputHide': + $validation->setShowInputMessage(false); + + break; + case 'ErrorStyle': + $validation->setErrorStyle($tagValueLower); + + break; + case 'ErrorTitle': + $validation->setErrorTitle($tagValue); + + break; + case 'ErrorMessage': + $validation->setError($tagValue); + + break; + case 'ErrorHide': + $validation->setShowErrorMessage(false); + + break; + case 'ComboHide': + $validation->setShowDropDown(false); + + break; + case 'UseBlank': + $validation->setAllowBlank(true); + + break; + case 'CellRangeList': + // FIXME missing FIXME + + break; + case 'Min': + case 'Value': + $tagValue = (string) preg_replace_callback(AddressHelper::R1C1_COORDINATE_REGEX, $pregCallback, $tagValue); + $validation->setFormula1($tagValue); + + break; + case 'Max': + $tagValue = (string) preg_replace_callback(AddressHelper::R1C1_COORDINATE_REGEX, $pregCallback, $tagValue); + $validation->setFormula2($tagValue); + + break; + } + } + + foreach ($cells as $cell) { + $sheet->getCell($cell)->setDataValidation(clone $validation); + } + } + } +} diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/PageSettings.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/PageSettings.php index a12986c..137caba 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/PageSettings.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/PageSettings.php @@ -2,6 +2,7 @@ namespace PhpOffice\PhpSpreadsheet\Reader\Xml; +use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Namespaces; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Worksheet\PageSetup; use SimpleXMLElement; @@ -14,9 +15,9 @@ class PageSettings */ private $printSettings; - public function __construct(SimpleXMLElement $xmlX, array $namespaces) + public function __construct(SimpleXMLElement $xmlX) { - $printSettings = $this->pageSetup($xmlX, $namespaces, $this->getPrintDefaults()); + $printSettings = $this->pageSetup($xmlX, $this->getPrintDefaults()); $this->printSettings = $this->printSetup($xmlX, $printSettings); } @@ -56,34 +57,32 @@ private function getPrintDefaults(): stdClass ]; } - private function pageSetup(SimpleXMLElement $xmlX, array $namespaces, stdClass $printDefaults): stdClass + private function pageSetup(SimpleXMLElement $xmlX, stdClass $printDefaults): stdClass { if (isset($xmlX->WorksheetOptions->PageSetup)) { foreach ($xmlX->WorksheetOptions->PageSetup as $pageSetupData) { foreach ($pageSetupData as $pageSetupKey => $pageSetupValue) { /** @scrutinizer ignore-call */ - $pageSetupAttributes = $pageSetupValue->attributes($namespaces['x']); - if (!$pageSetupAttributes) { - continue; - } - - switch ($pageSetupKey) { - case 'Layout': - $this->setLayout($printDefaults, $pageSetupAttributes); - - break; - case 'Header': - $printDefaults->headerMargin = (float) $pageSetupAttributes->Margin ?: 1.0; - - break; - case 'Footer': - $printDefaults->footerMargin = (float) $pageSetupAttributes->Margin ?: 1.0; - - break; - case 'PageMargins': - $this->setMargins($printDefaults, $pageSetupAttributes); - - break; + $pageSetupAttributes = $pageSetupValue->attributes(Namespaces::URN_EXCEL); + if ($pageSetupAttributes !== null) { + switch ($pageSetupKey) { + case 'Layout': + $this->setLayout($printDefaults, $pageSetupAttributes); + + break; + case 'Header': + $printDefaults->headerMargin = (float) $pageSetupAttributes->Margin ?: 1.0; + + break; + case 'Footer': + $printDefaults->footerMargin = (float) $pageSetupAttributes->Margin ?: 1.0; + + break; + case 'PageMargins': + $this->setMargins($printDefaults, $pageSetupAttributes); + + break; + } } } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Properties.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Properties.php index 9e10526..e216c25 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Properties.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Properties.php @@ -39,7 +39,7 @@ protected function readStandardProperties(SimpleXMLElement $xml): void protected function readCustomProperties(SimpleXMLElement $xml, array $namespaces): void { - if (isset($xml->CustomDocumentProperties)) { + if (isset($xml->CustomDocumentProperties) && is_iterable($xml->CustomDocumentProperties[0])) { $docProps = $this->spreadsheet->getProperties(); foreach ($xml->CustomDocumentProperties[0] as $propertyName => $propertyValue) { @@ -92,6 +92,10 @@ protected function processStandardProperty( case 'Manager': $docProps->setManager($stringValue); + break; + case 'HyperlinkBase': + $docProps->setHyperlinkBase($stringValue); + break; case 'Keywords': $docProps->setKeywords($stringValue); @@ -110,17 +114,10 @@ protected function processCustomProperty( ?SimpleXMLElement $propertyValue, SimpleXMLElement $propertyAttributes ): void { - $propertyType = DocumentProperties::PROPERTY_TYPE_UNKNOWN; - switch ((string) $propertyAttributes) { - case 'string': - $propertyType = DocumentProperties::PROPERTY_TYPE_STRING; - $propertyValue = trim((string) $propertyValue); - - break; case 'boolean': $propertyType = DocumentProperties::PROPERTY_TYPE_BOOLEAN; - $propertyValue = (bool) $propertyValue; + $propertyValue = (bool) (string) $propertyValue; break; case 'integer': @@ -134,9 +131,15 @@ protected function processCustomProperty( break; case 'dateTime.tz': + case 'dateTime.iso8601tz': $propertyType = DocumentProperties::PROPERTY_TYPE_DATE; $propertyValue = trim((string) $propertyValue); + break; + default: + $propertyType = DocumentProperties::PROPERTY_TYPE_STRING; + $propertyValue = trim((string) $propertyValue); + break; } @@ -150,8 +153,6 @@ protected function hex2str(array $hex): string private static function getAttributes(?SimpleXMLElement $simple, string $node): SimpleXMLElement { - return ($simple === null) - ? new SimpleXMLElement('') - : ($simple->attributes($node) ?? new SimpleXMLElement('')); + return ($simple === null) ? new SimpleXMLElement('') : ($simple->attributes($node) ?? new SimpleXMLElement('')); } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style.php index 0e3cd16..698acf6 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style.php @@ -2,6 +2,7 @@ namespace PhpOffice\PhpSpreadsheet\Reader\Xml; +use PhpOffice\PhpSpreadsheet\Style\Protection; use SimpleXMLElement; class Style @@ -15,7 +16,7 @@ class Style public function parseStyles(SimpleXMLElement $xml, array $namespaces): array { - if (!isset($xml->Styles)) { + if (!isset($xml->Styles) || !is_iterable($xml->Styles[0])) { return []; } @@ -30,10 +31,10 @@ public function parseStyles(SimpleXMLElement $xml, array $namespaces): array $styleID = (string) $style_ss['ID']; $this->styles[$styleID] = $this->styles['Default'] ?? []; - $alignment = $border = $font = $fill = $numberFormat = []; + $alignment = $border = $font = $fill = $numberFormat = $protection = []; foreach ($style as $styleType => $styleDatax) { - $styleData = $styleDatax ?? new SimpleXMLElement(''); + $styleData = self::getSxml($styleDatax); $styleAttributes = $styleData->attributes($namespaces['ss']); switch ($styleType) { @@ -64,20 +65,43 @@ public function parseStyles(SimpleXMLElement $xml, array $namespaces): array $numberFormat = $numberFormatStyleParser->parseStyle($styleAttributes); } + break; + case 'Protection': + $locked = $hidden = null; + $styleAttributesP = $styleData->attributes($namespaces['x']); + if (isset($styleAttributes['Protected'])) { + $locked = ((bool) (string) $styleAttributes['Protected']) ? Protection::PROTECTION_PROTECTED : Protection::PROTECTION_UNPROTECTED; + } + if (isset($styleAttributesP['HideFormula'])) { + $hidden = ((bool) (string) $styleAttributesP['HideFormula']) ? Protection::PROTECTION_PROTECTED : Protection::PROTECTION_UNPROTECTED; + } + if ($locked !== null || $hidden !== null) { + $protection['protection'] = []; + if ($locked !== null) { + $protection['protection']['locked'] = $locked; + } + if ($hidden !== null) { + $protection['protection']['hidden'] = $hidden; + } + } + break; } } - $this->styles[$styleID] = array_merge($alignment, $border, $font, $fill, $numberFormat); + $this->styles[$styleID] = array_merge($alignment, $border, $font, $fill, $numberFormat, $protection); } return $this->styles; } - protected static function getAttributes(?SimpleXMLElement $simple, string $node): SimpleXMLElement + private static function getAttributes(?SimpleXMLElement $simple, string $node): SimpleXMLElement + { + return ($simple === null) ? new SimpleXMLElement('') : ($simple->attributes($node) ?? new SimpleXMLElement('')); + } + + private static function getSxml(?SimpleXMLElement $simple): SimpleXMLElement { - return ($simple === null) - ? new SimpleXMLElement('') - : ($simple->attributes($node) ?? new SimpleXMLElement('')); + return ($simple !== null) ? $simple : new SimpleXMLElement(''); } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style/Font.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style/Font.php index 16ab44d..5f82488 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style/Font.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style/Font.php @@ -56,11 +56,11 @@ public function parseStyle(SimpleXMLElement $styleAttributes): array break; case 'Bold': - $style['font']['bold'] = true; + $style['font']['bold'] = $styleAttributeValue === '1'; break; case 'Italic': - $style['font']['italic'] = true; + $style['font']['italic'] = $styleAttributeValue === '1'; break; case 'Underline': diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style/StyleBase.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style/StyleBase.php index fc9ace8..8103a71 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style/StyleBase.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style/StyleBase.php @@ -25,8 +25,6 @@ protected static function identifyFixedStyleValue(array $styleList, string &$sty protected static function getAttributes(?SimpleXMLElement $simple, string $node): SimpleXMLElement { - return ($simple === null) - ? new SimpleXMLElement('') - : ($simple->attributes($node) ?? new SimpleXMLElement('')); + return ($simple === null) ? new SimpleXMLElement('') : ($simple->attributes($node) ?? new SimpleXMLElement('')); } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/ReferenceHelper.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/ReferenceHelper.php index b88199f..90eee53 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/ReferenceHelper.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/ReferenceHelper.php @@ -75,14 +75,11 @@ public static function columnSort($a, $b) * * @return int */ - public static function columnReverseSort($a, $b) + public static function columnReverseSort(string $a, string $b) { return -strcasecmp(strlen($a) . $a, strlen($b) . $b); } - /** @var int */ - private static $scrutinizer0 = 0; - /** * Compare two cell addresses * Intended for use as a Callback function for sorting cell addresses by column and row. @@ -92,16 +89,16 @@ public static function columnReverseSort($a, $b) * * @return int */ - public static function cellSort($a, $b) + public static function cellSort(string $a, string $b) { - $ac = $bc = ''; - $ar = self::$scrutinizer0; - $br = 0; + /** @scrutinizer be-damned */ sscanf($a, '%[A-Z]%d', $ac, $ar); + /** @var int $ar */ + /** @var string $ac */ + /** @scrutinizer be-damned */ sscanf($b, '%[A-Z]%d', $bc, $br); - - $ac = (string) $ac; - $bc = (string) $bc; + /** @var int $br */ + /** @var string $bc */ if ($ar === $br) { return strcasecmp(strlen($ac) . $ac, strlen($bc) . $bc); } @@ -118,16 +115,16 @@ public static function cellSort($a, $b) * * @return int */ - public static function cellReverseSort($a, $b) + public static function cellReverseSort(string $a, string $b) { - $ac = $bc = ''; - $ar = self::$scrutinizer0; - $br = 0; + /** @scrutinizer be-damned */ sscanf($a, '%[A-Z]%d', $ac, $ar); + /** @var int $ar */ + /** @var string $ac */ + /** @scrutinizer be-damned */ sscanf($b, '%[A-Z]%d', $bc, $br); - - $ac = (string) $ac; - $bc = (string) $bc; + /** @var int $br */ + /** @var string $bc */ if ($ar === $br) { return -strcasecmp(strlen($ac) . $ac, strlen($bc) . $bc); } @@ -142,7 +139,7 @@ public static function cellReverseSort($a, $b) * @param int $numberOfColumns Number of columns to insert/delete (negative values indicate deletion) * @param int $numberOfRows Number of rows to insert/delete (negative values indicate deletion) */ - protected function adjustPageBreaks(Worksheet $worksheet, $numberOfColumns, $numberOfRows): void + protected function adjustPageBreaks(Worksheet $worksheet, int $numberOfColumns, int $numberOfRows): void { $aBreaks = $worksheet->getBreaks(); ($numberOfColumns > 0 || $numberOfRows > 0) @@ -171,7 +168,7 @@ protected function adjustPageBreaks(Worksheet $worksheet, $numberOfColumns, $num * * @param Worksheet $worksheet The worksheet that we're editing */ - protected function adjustComments($worksheet): void + protected function adjustComments(Worksheet $worksheet): void { $aComments = $worksheet->getComments(); $aNewComments = []; // the new array of all comments @@ -195,7 +192,7 @@ protected function adjustComments($worksheet): void * @param int $numberOfColumns Number of columns to insert/delete (negative values indicate deletion) * @param int $numberOfRows Number of rows to insert/delete (negative values indicate deletion) */ - protected function adjustHyperlinks($worksheet, $numberOfColumns, $numberOfRows): void + protected function adjustHyperlinks(Worksheet $worksheet, int $numberOfColumns, int $numberOfRows): void { $aHyperlinkCollection = $worksheet->getHyperlinkCollection(); ($numberOfColumns > 0 || $numberOfRows > 0) @@ -220,7 +217,7 @@ protected function adjustHyperlinks($worksheet, $numberOfColumns, $numberOfRows) * @param int $numberOfColumns Number of columns to insert/delete (negative values indicate deletion) * @param int $numberOfRows Number of rows to insert/delete (negative values indicate deletion) */ - protected function adjustConditionalFormatting($worksheet, $numberOfColumns, $numberOfRows): void + protected function adjustConditionalFormatting(Worksheet $worksheet, int $numberOfColumns, int $numberOfRows): void { $aStyles = $worksheet->getConditionalStylesCollection(); ($numberOfColumns > 0 || $numberOfRows > 0) @@ -259,7 +256,7 @@ protected function adjustConditionalFormatting($worksheet, $numberOfColumns, $nu * @param int $numberOfColumns Number of columns to insert/delete (negative values indicate deletion) * @param int $numberOfRows Number of rows to insert/delete (negative values indicate deletion) */ - protected function adjustDataValidations(Worksheet $worksheet, $numberOfColumns, $numberOfRows): void + protected function adjustDataValidations(Worksheet $worksheet, int $numberOfColumns, int $numberOfRows): void { $aDataValidationCollection = $worksheet->getDataValidationCollection(); ($numberOfColumns > 0 || $numberOfRows > 0) @@ -299,7 +296,7 @@ protected function adjustMergeCells(Worksheet $worksheet): void * @param int $numberOfColumns Number of columns to insert/delete (negative values indicate deletion) * @param int $numberOfRows Number of rows to insert/delete (negative values indicate deletion) */ - protected function adjustProtectedCells(Worksheet $worksheet, $numberOfColumns, $numberOfRows): void + protected function adjustProtectedCells(Worksheet $worksheet, int $numberOfColumns, int $numberOfRows): void { $aProtectedCells = $worksheet->getProtectedCells(); ($numberOfColumns > 0 || $numberOfRows > 0) @@ -412,7 +409,7 @@ public function insertNewBefore( $cellCollection = $worksheet->getCellCollection(); $missingCoordinates = array_filter( array_map(function ($row) use ($highestColumn) { - return $highestColumn . $row; + return "{$highestColumn}{$row}"; }, range(1, $highestRow)), function ($coordinate) use ($cellCollection) { return $cellCollection->has($coordinate) === false; @@ -453,9 +450,9 @@ function ($coordinate) use ($cellCollection) { if ($cell->getDataType() === DataType::TYPE_FORMULA) { // Formula should be adjusted $worksheet->getCell($newCoordinate) - ->setValue($this->updateFormulaReferences($cell->getValue(), $beforeCellAddress, $numberOfColumns, $numberOfRows, $worksheet->getTitle())); + ->setValue($this->updateFormulaReferences($cell->getValue(), $beforeCellAddress, $numberOfColumns, $numberOfRows, $worksheet->getTitle(), true)); } else { - // Formula should not be adjusted + // Cell value should not be adjusted $worksheet->getCell($newCoordinate)->setValueExplicit($cell->getValue(), $cell->getDataType()); } @@ -463,10 +460,10 @@ function ($coordinate) use ($cellCollection) { $worksheet->getCellCollection()->delete($coordinate); } else { /* We don't need to update styles for rows/columns before our insertion position, - but we do still need to adjust any formulae in those cells */ + but we do still need to adjust any formulae in those cells */ if ($cell->getDataType() === DataType::TYPE_FORMULA) { // Formula should be adjusted - $cell->setValue($this->updateFormulaReferences($cell->getValue(), $beforeCellAddress, $numberOfColumns, $numberOfRows, $worksheet->getTitle())); + $cell->setValue($this->updateFormulaReferences($cell->getValue(), $beforeCellAddress, $numberOfColumns, $numberOfRows, $worksheet->getTitle(), true)); } } } @@ -518,7 +515,7 @@ function ($coordinate) use ($cellCollection) { // Update worksheet: freeze pane if ($worksheet->getFreezePane()) { - $splitCell = $worksheet->getFreezePane() ?? ''; + $splitCell = $worksheet->getFreezePane(); $topLeftCell = $worksheet->getTopLeftCell() ?? ''; $splitCell = $this->updateCellReference($splitCell); @@ -550,7 +547,7 @@ function ($coordinate) use ($cellCollection) { } // Update workbook: define names - if (count($worksheet->getParent()->getDefinedNames()) > 0) { + if (count($worksheet->getParentOrThrow()->getDefinedNames()) > 0) { $this->updateDefinedNames($worksheet, $beforeCellAddress, $numberOfColumns, $numberOfRows); } @@ -609,7 +606,7 @@ public function updateFormulaReferences( // Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more $column = 100000; $row = 10000000 + (int) trim($match[3], '$'); - $cellIndex = $column . $row; + $cellIndex = "{$column}{$row}"; $newCellTokens[$cellIndex] = preg_quote($toString, '/'); $cellTokens[$cellIndex] = '/(?cellReferenceHelper->updateCellReference($cellReference, $includeAbsoluteReferences); - } elseif (Coordinate::coordinateIsRange($cellReference)) { - // Range - return $this->updateCellRange($cellReference, $includeAbsoluteReferences); } - // Return original - return $cellReference; + // Range + return $this->updateCellRange($cellReference, $includeAbsoluteReferences); } /** @@ -905,7 +900,7 @@ public function updateNamedFormulae(Spreadsheet $spreadsheet, $oldName = '', $ne private function updateDefinedNames(Worksheet $worksheet, string $beforeCellAddress, int $numberOfColumns, int $numberOfRows): void { - foreach ($worksheet->getParent()->getDefinedNames() as $definedName) { + foreach ($worksheet->getParentOrThrow()->getDefinedNames() as $definedName) { if ($definedName->isFormula() === false) { $this->updateNamedRange($definedName, $worksheet, $beforeCellAddress, $numberOfColumns, $numberOfRows); } else { @@ -919,11 +914,18 @@ private function updateNamedRange(DefinedName $definedName, Worksheet $worksheet $cellAddress = $definedName->getValue(); $asFormula = ($cellAddress[0] === '='); if ($definedName->getWorksheet() !== null && $definedName->getWorksheet()->getHashCode() === $worksheet->getHashCode()) { + /** + * If we delete the entire range that is referenced by a Named Range, MS Excel sets the value to #REF! + * PhpSpreadsheet still only does a basic adjustment, so the Named Range will still reference Cells. + * Note that this applies only when deleting columns/rows; subsequent insertion won't fix the #REF! + * TODO Can we work out a method to identify Named Ranges that cease to be valid, so that we can replace + * them with a #REF! + */ if ($asFormula === true) { - $formula = $this->updateFormulaReferences($cellAddress, $beforeCellAddress, $numberOfColumns, $numberOfRows, $worksheet->getTitle()); + $formula = $this->updateFormulaReferences($cellAddress, $beforeCellAddress, $numberOfColumns, $numberOfRows, $worksheet->getTitle(), true); $definedName->setValue($formula); } else { - $definedName->setValue($this->updateCellReference(ltrim($cellAddress, '='))); + $definedName->setValue($this->updateCellReference(ltrim($cellAddress, '='), true)); } } } @@ -931,8 +933,15 @@ private function updateNamedRange(DefinedName $definedName, Worksheet $worksheet private function updateNamedFormula(DefinedName $definedName, Worksheet $worksheet, string $beforeCellAddress, int $numberOfColumns, int $numberOfRows): void { if ($definedName->getWorksheet() !== null && $definedName->getWorksheet()->getHashCode() === $worksheet->getHashCode()) { + /** + * If we delete the entire range that is referenced by a Named Formula, MS Excel sets the value to #REF! + * PhpSpreadsheet still only does a basic adjustment, so the Named Formula will still reference Cells. + * Note that this applies only when deleting columns/rows; subsequent insertion won't fix the #REF! + * TODO Can we work out a method to identify Named Ranges that cease to be valid, so that we can replace + * them with a #REF! + */ $formula = $definedName->getValue(); - $formula = $this->updateFormulaReferences($formula, $beforeCellAddress, $numberOfColumns, $numberOfRows, $worksheet->getTitle()); + $formula = $this->updateFormulaReferences($formula, $beforeCellAddress, $numberOfColumns, $numberOfRows, $worksheet->getTitle(), true); $definedName->setValue($formula); } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/RichText/Run.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/RichText/Run.php index 9c9f807..862cdbf 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/RichText/Run.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/RichText/Run.php @@ -9,7 +9,7 @@ class Run extends TextElement implements ITextElement /** * Font. * - * @var Font + * @var ?Font */ private $font; @@ -58,7 +58,7 @@ public function getHashCode() { return md5( $this->getText() . - $this->font->getHashCode() . + (($this->font === null) ? '' : $this->font->getHashCode()) . __CLASS__ ); } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/RichText/TextElement.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/RichText/TextElement.php index 2373343..ee693a2 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/RichText/TextElement.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/RichText/TextElement.php @@ -47,7 +47,7 @@ public function setText($text) } /** - * Get font. + * Get font. For this class, the return value is always null. * * @return null|\PhpOffice\PhpSpreadsheet\Style\Font */ diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Settings.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Settings.php index 0baf446..d8007fd 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Settings.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Settings.php @@ -155,7 +155,7 @@ public static function getLibXmlDisableEntityLoader(): bool /** * Sets the implementation of cache that should be used for cell collection. */ - public static function setCache(CacheInterface $cache): void + public static function setCache(?CacheInterface $cache): void { self::$cache = $cache; } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Date.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Date.php index 0ae5f1e..4f19673 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Date.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Date.php @@ -160,7 +160,9 @@ private static function validateTimeZone($timeZone) } /** - * @param mixed $value + * @param mixed $value Converts a date/time in ISO-8601 standard format date string to an Excel + * serialized timestamp. + * See https://en.wikipedia.org/wiki/ISO_8601 for details of the ISO-8601 standard format. * * @return float|int */ @@ -182,7 +184,7 @@ public static function convertIsoDate($value) throw new Exception("Invalid string $value supplied for datatype Date"); } - if (preg_match('/^\\d\\d:\\d\\d:\\d\\d/', $value) == 1) { + if (preg_match('/^\\s*\\d?\\d:\\d\\d(:\\d\\d([.]\\d+)?)?\\s*(am|pm)?\\s*$/i', $value) == 1) { $newValue = fmod($newValue, 1.0); } @@ -194,8 +196,8 @@ public static function convertIsoDate($value) * * @param float|int $excelTimestamp MS Excel serialized date/time value * @param null|DateTimeZone|string $timeZone The timezone to assume for the Excel timestamp, - * if you don't want to treat it as a UTC value - * Use the default (UTC) unless you absolutely need a conversion + * if you don't want to treat it as a UTC value + * Use the default (UTC) unless you absolutely need a conversion * * @return DateTime PHP date/time object */ @@ -243,8 +245,8 @@ public static function excelToDateTimeObject($excelTimestamp, $timeZone = null) * * @param float|int $excelTimestamp MS Excel serialized date/time value * @param null|DateTimeZone|string $timeZone The timezone to assume for the Excel timestamp, - * if you don't want to treat it as a UTC value - * Use the default (UTC) unless you absolutely need a conversion + * if you don't want to treat it as a UTC value + * Use the default (UTC) unless you absolutely need a conversion * * @return int Unix timetamp for this date/time */ @@ -375,13 +377,18 @@ public static function isDateTime(Cell $cell, $value = null, bool $dateWithoutTi if ($worksheet !== null && $spreadsheet !== null) { $index = $spreadsheet->getActiveSheetIndex(); $selected = $worksheet->getSelectedCells(); - $result = is_numeric($value ?? $cell->getCalculatedValue()) && - self::isDateTimeFormat( - $worksheet->getStyle( - $cell->getCoordinate() - )->getNumberFormat(), - $dateWithoutTimeOkay - ); + + try { + $result = is_numeric($value ?? $cell->getCalculatedValue()) && + self::isDateTimeFormat( + $worksheet->getStyle( + $cell->getCoordinate() + )->getNumberFormat(), + $dateWithoutTimeOkay + ); + } catch (Exception $e) { + // Result is already false, so no need to actually do anything here + } $worksheet->setSelectedCells($selected); $spreadsheet->setActiveSheetIndex($index); } @@ -390,7 +397,7 @@ public static function isDateTime(Cell $cell, $value = null, bool $dateWithoutTi } /** - * Is a given number format a date/time? + * Is a given NumberFormat code a date/time format code? * * @return bool */ diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher.php index c6d0a6f..466e7e8 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher.php @@ -7,21 +7,21 @@ class Escher /** * Drawing Group Container. * - * @var Escher\DggContainer + * @var ?Escher\DggContainer */ private $dggContainer; /** * Drawing Container. * - * @var Escher\DgContainer + * @var ?Escher\DgContainer */ private $dgContainer; /** * Get Drawing Group Container. * - * @return Escher\DggContainer + * @return ?Escher\DggContainer */ public function getDggContainer() { @@ -43,7 +43,7 @@ public function setDggContainer($dggContainer) /** * Get Drawing Container. * - * @return Escher\DgContainer + * @return ?Escher\DgContainer */ public function getDgContainer() { diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher/DgContainer.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher/DgContainer.php index b0d75d7..51c6860 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher/DgContainer.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher/DgContainer.php @@ -2,50 +2,63 @@ namespace PhpOffice\PhpSpreadsheet\Shared\Escher; +use PhpOffice\PhpSpreadsheet\Exception as SpreadsheetException; + class DgContainer { /** * Drawing index, 1-based. * - * @var int + * @var ?int */ private $dgId; /** * Last shape index in this drawing. * - * @var int + * @var ?int */ private $lastSpId; + /** @var ?DgContainer\SpgrContainer */ private $spgrContainer; - public function getDgId() + public function getDgId(): ?int { return $this->dgId; } - public function setDgId($value): void + public function setDgId(int $value): void { $this->dgId = $value; } - public function getLastSpId() + public function getLastSpId(): ?int { return $this->lastSpId; } - public function setLastSpId($value): void + public function setLastSpId(int $value): void { $this->lastSpId = $value; } - public function getSpgrContainer() + public function getSpgrContainer(): ?DgContainer\SpgrContainer { return $this->spgrContainer; } - public function setSpgrContainer($spgrContainer) + public function getSpgrContainerOrThrow(): DgContainer\SpgrContainer + { + if ($this->spgrContainer !== null) { + return $this->spgrContainer; + } + + throw new SpreadsheetException('spgrContainer is unexpectedly null'); + } + + /** @param DgContainer\SpgrContainer $spgrContainer */ + public function setSpgrContainer($spgrContainer): DgContainer\SpgrContainer { return $this->spgrContainer = $spgrContainer; } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher/DgContainer/SpgrContainer.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher/DgContainer/SpgrContainer.php index 6bdc8f7..260df9c 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher/DgContainer/SpgrContainer.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher/DgContainer/SpgrContainer.php @@ -48,7 +48,7 @@ public function addChild($child): void /** * Get collection of Shape Containers. */ - public function getChildren() + public function getChildren(): array { return $this->children; } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher/DggContainer.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher/DggContainer.php index 36806aa..ba5e798 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher/DggContainer.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher/DggContainer.php @@ -28,7 +28,7 @@ class DggContainer /** * BLIP Store Container. * - * @var DggContainer\BstoreContainer + * @var ?DggContainer\BstoreContainer */ private $bstoreContainer; @@ -109,7 +109,7 @@ public function setCSpSaved($value): void /** * Get BLIP Store Container. * - * @return DggContainer\BstoreContainer + * @return ?DggContainer\BstoreContainer */ public function getBstoreContainer() { diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher/DggContainer/BstoreContainer/BSE.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher/DggContainer/BstoreContainer/BSE.php index d24af3f..328ac6b 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher/DggContainer/BstoreContainer/BSE.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher/DggContainer/BstoreContainer/BSE.php @@ -19,15 +19,16 @@ class BSE /** * The parent BLIP Store Entry Container. + * Property is never currently read. * * @var BstoreContainer */ - private $parent; + private $parent; // @phpstan-ignore-line /** * The BLIP (Big Large Image or Picture). * - * @var BSE\Blip + * @var ?BSE\Blip */ private $blip; @@ -49,7 +50,7 @@ public function setParent(BstoreContainer $parent): void /** * Get the BLIP. * - * @return BSE\Blip + * @return ?BSE\Blip */ public function getBlip() { diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/File.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/File.php index f2fe8ca..737a6eb 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/File.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/File.php @@ -156,7 +156,11 @@ public static function assertFile(string $filename, string $zipMember = ''): voi if ($zipMember !== '') { $zipfile = "zip://$filename#$zipMember"; if (!self::fileExists($zipfile)) { - throw new ReaderException("Could not find zip member $zipfile"); + // Has the file been saved with Windoze directory separators rather than unix? + $zipfile = "zip://$filename#" . str_replace('/', '\\', $zipMember); + if (!self::fileExists($zipfile)) { + throw new ReaderException("Could not find zip member $zipfile"); + } } } } @@ -180,6 +184,14 @@ public static function testFileNoThrow(string $filename, ?string $zipMember = nu return self::validateZipFirst4($filename); } - return self::fileExists("zip://$filename#$zipMember"); + $zipfile = "zip://$filename#$zipMember"; + if (self::fileExists($zipfile)) { + return true; + } + + // Has the file been saved with Windoze directory separators rather than unix? + $zipfile = "zip://$filename#" . str_replace('/', '\\', $zipMember); + + return self::fileExists($zipfile); } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Font.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Font.php index dfe9f77..90c1992 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Font.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Font.php @@ -200,6 +200,23 @@ class Font ], ]; + /** + * Array that can be used to supplement FONT_FILE_NAMES for calculating exact width. + * + * @var array + */ + private static $extraFontArray = []; + + public static function setExtraFontArray(array $extraFontArray): void + { + self::$extraFontArray = $extraFontArray; + } + + public static function getExtraFontArray(): array + { + return self::$extraFontArray; + } + /** * AutoSize method. * @@ -341,7 +358,7 @@ public static function calculateColumnWidth( ?FontStyle $defaultFont = null, bool $filterAdjustment = false, int $indentAdjustment = 0 - ): int { + ): float { // If it is rich text, use plain text if ($cellText instanceof RichText) { $cellText = $cellText->getPlainText(); @@ -363,15 +380,15 @@ public static function calculateColumnWidth( $approximate = self::$autoSizeMethod === self::AUTOSIZE_METHOD_APPROX; $columnWidth = 0; if (!$approximate) { - $columnWidthAdjust = ceil( - self::getTextWidthPixelsExact( - str_repeat('n', 1 * (($filterAdjustment ? 3 : 1) + ($indentAdjustment * 2))), - $font, - 0 - ) * 1.07 - ); - try { + $columnWidthAdjust = ceil( + self::getTextWidthPixelsExact( + str_repeat('n', 1 * (($filterAdjustment ? 3 : 1) + ($indentAdjustment * 2))), + $font, + 0 + ) * 1.07 + ); + // Width of text in pixels excl. padding // and addition because Excel adds some padding, just use approx width of 'n' glyph $columnWidth = self::getTextWidthPixelsExact($cellText, $font, $rotation) + $columnWidthAdjust; @@ -395,18 +412,14 @@ public static function calculateColumnWidth( $columnWidth = Drawing::pixelsToCellDimension((int) $columnWidth, $defaultFont ?? new FontStyle()); // Return - return (int) round($columnWidth, 6); + return round($columnWidth, 4); } /** * Get GD text width in pixels for a string of text in a certain font at a certain rotation angle. */ - public static function getTextWidthPixelsExact(string $text, FontStyle $font, int $rotation = 0): int + public static function getTextWidthPixelsExact(string $text, FontStyle $font, int $rotation = 0): float { - if (!function_exists('imagettfbbox')) { - throw new PhpSpreadsheetException('GD library needs to be enabled'); - } - // font size should really be supplied in pixels in GD2, // but since GD2 seems to assume 72dpi, pixels and points are the same $fontFile = self::getTrueTypeFontFileFromFont($font); @@ -424,7 +437,7 @@ public static function getTextWidthPixelsExact(string $text, FontStyle $font, in $upperLeftCornerX = $textBox[6]; // Consider the rotation when calculating the width - return max($lowerRightCornerX - $upperLeftCornerX, $upperRightCornerX - $lowerLeftCornerX); + return round(max($lowerRightCornerX - $upperLeftCornerX, $upperRightCornerX - $lowerLeftCornerX), 4); } /** @@ -440,29 +453,26 @@ public static function getTextWidthPixelsApprox($columnText, FontStyle $font, $r $fontName = $font->getName(); $fontSize = $font->getSize(); - // Calculate column width in pixels. We assume fixed glyph width. Result varies with font name and size. + // Calculate column width in pixels. + // We assume fixed glyph width, but count double for "fullwidth" characters. + // Result varies with font name and size. switch ($fontName) { - case 'Calibri': - // value 8.26 was found via interpolation by inspecting real Excel files with Calibri 11 font. - $columnWidth = (int) (8.26 * StringHelper::countCharacters($columnText)); - $columnWidth = $columnWidth * $fontSize / 11; // extrapolate from font size - - break; case 'Arial': // value 8 was set because of experience in different exports at Arial 10 font. - $columnWidth = (int) (8 * StringHelper::countCharacters($columnText)); + $columnWidth = (int) (8 * StringHelper::countCharactersDbcs($columnText)); $columnWidth = $columnWidth * $fontSize / 10; // extrapolate from font size break; case 'Verdana': // value 8 was found via interpolation by inspecting real Excel files with Verdana 10 font. - $columnWidth = (int) (8 * StringHelper::countCharacters($columnText)); + $columnWidth = (int) (8 * StringHelper::countCharactersDbcs($columnText)); $columnWidth = $columnWidth * $fontSize / 10; // extrapolate from font size break; default: // just assume Calibri - $columnWidth = (int) (8.26 * StringHelper::countCharacters($columnText)); + // value 8.26 was found via interpolation by inspecting real Excel files with Calibri 11 font. + $columnWidth = (int) (8.26 * StringHelper::countCharactersDbcs($columnText)); $columnWidth = $columnWidth * $fontSize / 11; // extrapolate from font size break; @@ -532,7 +542,8 @@ public static function getTrueTypeFontFileFromFont(FontStyle $font, bool $checkP } $name = $font->getName(); - if (!isset(self::FONT_FILE_NAMES[$name])) { + $fontArray = array_merge(self::FONT_FILE_NAMES, self::$extraFontArray); + if (!isset($fontArray[$name])) { throw new PhpSpreadsheetException('Unknown font name "' . $name . '". Cannot map to TrueType font file'); } $bold = $font->getBold(); @@ -544,17 +555,44 @@ public static function getTrueTypeFontFileFromFont(FontStyle $font, bool $checkP if ($italic) { $index .= 'i'; } - $fontFile = self::FONT_FILE_NAMES[$name][$index]; + $fontFile = $fontArray[$name][$index]; $separator = ''; if (mb_strlen(self::$trueTypeFontPath) > 1 && mb_substr(self::$trueTypeFontPath, -1) !== '/' && mb_substr(self::$trueTypeFontPath, -1) !== '\\') { $separator = DIRECTORY_SEPARATOR; } - $fontFile = self::$trueTypeFontPath . $separator . $fontFile; + $fontFileAbsolute = preg_match('~^([A-Za-z]:)?[/\\\\]~', $fontFile) === 1; + if (!$fontFileAbsolute) { + $fontFile = self::$trueTypeFontPath . $separator . $fontFile; + } // Check if file actually exists - if ($checkPath && !file_exists($fontFile)) { - throw new PhpSpreadsheetException('TrueType Font file not found'); + if ($checkPath && !file_exists($fontFile) && !$fontFileAbsolute) { + $alternateName = $name; + if ($index !== 'x' && $fontArray[$name][$index] !== $fontArray[$name]['x']) { + // Bold but no italic: + // Comic Sans + // Tahoma + // Neither bold nor italic: + // Impact + // Lucida Console + // Lucida Sans Unicode + // Microsoft Sans Serif + // Symbol + if ($index === 'xb') { + $alternateName .= ' Bold'; + } elseif ($index === 'xi') { + $alternateName .= ' Italic'; + } elseif ($fontArray[$name]['xb'] === $fontArray[$name]['xbi']) { + $alternateName .= ' Bold'; + } else { + $alternateName .= ' Bold Italic'; + } + } + $fontFile = self::$trueTypeFontPath . $separator . $alternateName . '.ttf'; + if (!file_exists($fontFile)) { + throw new PhpSpreadsheetException('TrueType Font file not found'); + } } return $fontFile; diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/JAMA/CHANGELOG.TXT b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/JAMA/CHANGELOG.TXT deleted file mode 100644 index 1c18a5d..0000000 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/JAMA/CHANGELOG.TXT +++ /dev/null @@ -1,16 +0,0 @@ -Mar 1, 2005 11:15 AST by PM - -+ For consistency, renamed Math.php to Maths.java, utils to util, - tests to test, docs to doc - - -+ Removed conditional logic from top of Matrix class. - -+ Switched to using hypo function in Maths.php for all php-hypot calls. - NOTE TO SELF: Need to make sure that all decompositions have been - switched over to using the bundled hypo. - -Feb 25, 2005 at 10:00 AST by PM - -+ Recommend using simpler Error.php instead of JAMA_Error.php but - can be persuaded otherwise. - diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/JAMA/LUDecomposition.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/JAMA/LUDecomposition.php deleted file mode 100644 index cc09b64..0000000 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/JAMA/LUDecomposition.php +++ /dev/null @@ -1,286 +0,0 @@ -= n, the LU decomposition is an m-by-n - * unit lower triangular matrix L, an n-by-n upper triangular matrix U, - * and a permutation vector piv of length m so that A(piv,:) = L*U. - * If m < n, then L is m-by-m and U is m-by-n. - * - * The LU decompostion with pivoting always exists, even if the matrix is - * singular, so the constructor will never fail. The primary use of the - * LU decomposition is in the solution of square systems of simultaneous - * linear equations. This will fail if isNonsingular() returns false. - * - * @author Paul Meagher - * @author Bartosz Matosiuk - * @author Michael Bommarito - * - * @version 1.1 - */ -class LUDecomposition -{ - const MATRIX_SINGULAR_EXCEPTION = 'Can only perform operation on singular matrix.'; - const MATRIX_SQUARE_EXCEPTION = 'Mismatched Row dimension'; - - /** - * Decomposition storage. - * - * @var array - */ - private $LU = []; - - /** - * Row dimension. - * - * @var int - */ - private $m; - - /** - * Column dimension. - * - * @var int - */ - private $n; - - /** - * Pivot sign. - * - * @var int - */ - private $pivsign; - - /** - * Internal storage of pivot vector. - * - * @var array - */ - private $piv = []; - - /** - * LU Decomposition constructor. - * - * @param ?Matrix $A Rectangular matrix - */ - public function __construct($A) - { - if ($A instanceof Matrix) { - // Use a "left-looking", dot-product, Crout/Doolittle algorithm. - $this->LU = $A->getArray(); - $this->m = $A->getRowDimension(); - $this->n = $A->getColumnDimension(); - for ($i = 0; $i < $this->m; ++$i) { - $this->piv[$i] = $i; - } - $this->pivsign = 1; - $LUcolj = []; - - // Outer loop. - for ($j = 0; $j < $this->n; ++$j) { - // Make a copy of the j-th column to localize references. - for ($i = 0; $i < $this->m; ++$i) { - $LUcolj[$i] = &$this->LU[$i][$j]; - } - // Apply previous transformations. - for ($i = 0; $i < $this->m; ++$i) { - $LUrowi = $this->LU[$i]; - // Most of the time is spent in the following dot product. - $kmax = min($i, $j); - $s = 0.0; - for ($k = 0; $k < $kmax; ++$k) { - $s += $LUrowi[$k] * $LUcolj[$k]; - } - $LUrowi[$j] = $LUcolj[$i] -= $s; - } - // Find pivot and exchange if necessary. - $p = $j; - for ($i = $j + 1; $i < $this->m; ++$i) { - if (abs($LUcolj[$i]) > abs($LUcolj[$p])) { - $p = $i; - } - } - if ($p != $j) { - for ($k = 0; $k < $this->n; ++$k) { - $t = $this->LU[$p][$k]; - $this->LU[$p][$k] = $this->LU[$j][$k]; - $this->LU[$j][$k] = $t; - } - $k = $this->piv[$p]; - $this->piv[$p] = $this->piv[$j]; - $this->piv[$j] = $k; - $this->pivsign = $this->pivsign * -1; - } - // Compute multipliers. - if (($j < $this->m) && ($this->LU[$j][$j] != 0.0)) { - for ($i = $j + 1; $i < $this->m; ++$i) { - $this->LU[$i][$j] /= $this->LU[$j][$j]; - } - } - } - } else { - throw new CalculationException(Matrix::ARGUMENT_TYPE_EXCEPTION); - } - } - - // function __construct() - - /** - * Get lower triangular factor. - * - * @return Matrix Lower triangular factor - */ - public function getL() - { - $L = []; - for ($i = 0; $i < $this->m; ++$i) { - for ($j = 0; $j < $this->n; ++$j) { - if ($i > $j) { - $L[$i][$j] = $this->LU[$i][$j]; - } elseif ($i == $j) { - $L[$i][$j] = 1.0; - } else { - $L[$i][$j] = 0.0; - } - } - } - - return new Matrix($L); - } - - // function getL() - - /** - * Get upper triangular factor. - * - * @return Matrix Upper triangular factor - */ - public function getU() - { - $U = []; - for ($i = 0; $i < $this->n; ++$i) { - for ($j = 0; $j < $this->n; ++$j) { - if ($i <= $j) { - $U[$i][$j] = $this->LU[$i][$j]; - } else { - $U[$i][$j] = 0.0; - } - } - } - - return new Matrix($U); - } - - // function getU() - - /** - * Return pivot permutation vector. - * - * @return array Pivot vector - */ - public function getPivot() - { - return $this->piv; - } - - // function getPivot() - - /** - * Alias for getPivot. - * - * @see getPivot - * - * @return array Pivot vector - */ - public function getDoublePivot() - { - return $this->getPivot(); - } - - // function getDoublePivot() - - /** - * Is the matrix nonsingular? - * - * @return bool true if U, and hence A, is nonsingular - */ - public function isNonsingular() - { - for ($j = 0; $j < $this->n; ++$j) { - if ($this->LU[$j][$j] == 0) { - return false; - } - } - - return true; - } - - // function isNonsingular() - - /** - * Count determinants. - * - * @return float - */ - public function det() - { - if ($this->m == $this->n) { - $d = $this->pivsign; - for ($j = 0; $j < $this->n; ++$j) { - $d *= $this->LU[$j][$j]; - } - - return $d; - } - - throw new CalculationException(Matrix::MATRIX_DIMENSION_EXCEPTION); - } - - // function det() - - /** - * Solve A*X = B. - * - * @param Matrix $B a Matrix with as many rows as A and any number of columns - * - * @return Matrix X so that L*U*X = B(piv,:) - */ - public function solve(Matrix $B) - { - if ($B->getRowDimension() == $this->m) { - if ($this->isNonsingular()) { - // Copy right hand side with pivoting - $nx = $B->getColumnDimension(); - $X = $B->getMatrix($this->piv, 0, $nx - 1); - // Solve L*Y = B(piv,:) - for ($k = 0; $k < $this->n; ++$k) { - for ($i = $k + 1; $i < $this->n; ++$i) { - for ($j = 0; $j < $nx; ++$j) { - $X->A[$i][$j] -= $X->A[$k][$j] * $this->LU[$i][$k]; - } - } - } - // Solve U*X = Y; - for ($k = $this->n - 1; $k >= 0; --$k) { - for ($j = 0; $j < $nx; ++$j) { - $X->A[$k][$j] /= $this->LU[$k][$k]; - } - for ($i = 0; $i < $k; ++$i) { - for ($j = 0; $j < $nx; ++$j) { - $X->A[$i][$j] -= $X->A[$k][$j] * $this->LU[$i][$k]; - } - } - } - - return $X; - } - - throw new CalculationException(self::MATRIX_SINGULAR_EXCEPTION); - } - - throw new CalculationException(self::MATRIX_SQUARE_EXCEPTION); - } -} diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/JAMA/Matrix.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/JAMA/Matrix.php deleted file mode 100644 index 75e4424..0000000 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/JAMA/Matrix.php +++ /dev/null @@ -1,1167 +0,0 @@ - 0) { - $match = implode(',', array_map('gettype', $args)); - - switch ($match) { - //Rectangular matrix - m x n initialized from 2D array - case 'array': - $this->m = count($args[0]); - $this->n = count($args[0][0]); - $this->A = $args[0]; - - break; - //Square matrix - n x n - case 'integer': - $this->m = $args[0]; - $this->n = $args[0]; - $this->A = array_fill(0, $this->m, array_fill(0, $this->n, 0)); - - break; - //Rectangular matrix - m x n - case 'integer,integer': - $this->m = $args[0]; - $this->n = $args[1]; - $this->A = array_fill(0, $this->m, array_fill(0, $this->n, 0)); - - break; - //Rectangular matrix - m x n initialized from packed array - case 'array,integer': - $this->m = $args[1]; - if ($this->m != 0) { - $this->n = count($args[0]) / $this->m; - } else { - $this->n = 0; - } - if (($this->m * $this->n) == count($args[0])) { - for ($i = 0; $i < $this->m; ++$i) { - for ($j = 0; $j < $this->n; ++$j) { - $this->A[$i][$j] = $args[0][$i + $j * $this->m]; - } - } - } else { - throw new CalculationException(self::ARRAY_LENGTH_EXCEPTION); - } - - break; - default: - throw new CalculationException(self::POLYMORPHIC_ARGUMENT_EXCEPTION); - - break; - } - } else { - throw new CalculationException(self::POLYMORPHIC_ARGUMENT_EXCEPTION); - } - } - - /** - * getArray. - * - * @return array Matrix array - */ - public function getArray() - { - return $this->A; - } - - /** - * getRowDimension. - * - * @return int Row dimension - */ - public function getRowDimension() - { - return $this->m; - } - - /** - * getColumnDimension. - * - * @return int Column dimension - */ - public function getColumnDimension() - { - return $this->n; - } - - /** - * get. - * - * Get the i,j-th element of the matrix. - * - * @param int $i Row position - * @param int $j Column position - * - * @return float|int - */ - public function get($i = null, $j = null) - { - return $this->A[$i][$j]; - } - - /** - * getMatrix. - * - * Get a submatrix - * - * @return Matrix Submatrix - */ - public function getMatrix(...$args) - { - if (count($args) > 0) { - $match = implode(',', array_map('gettype', $args)); - - switch ($match) { - //A($i0...; $j0...) - case 'integer,integer': - [$i0, $j0] = $args; - if ($i0 >= 0) { - $m = $this->m - $i0; - } else { - throw new CalculationException(self::ARGUMENT_BOUNDS_EXCEPTION); - } - if ($j0 >= 0) { - $n = $this->n - $j0; - } else { - throw new CalculationException(self::ARGUMENT_BOUNDS_EXCEPTION); - } - $R = new self($m, $n); - for ($i = $i0; $i < $this->m; ++$i) { - for ($j = $j0; $j < $this->n; ++$j) { - $R->set($i, $j, $this->A[$i][$j]); - } - } - - return $R; - //A($i0...$iF; $j0...$jF) - case 'integer,integer,integer,integer': - [$i0, $iF, $j0, $jF] = $args; - if (($iF > $i0) && ($this->m >= $iF) && ($i0 >= 0)) { - $m = $iF - $i0; - } else { - throw new CalculationException(self::ARGUMENT_BOUNDS_EXCEPTION); - } - if (($jF > $j0) && ($this->n >= $jF) && ($j0 >= 0)) { - $n = $jF - $j0; - } else { - throw new CalculationException(self::ARGUMENT_BOUNDS_EXCEPTION); - } - $R = new self($m + 1, $n + 1); - for ($i = $i0; $i <= $iF; ++$i) { - for ($j = $j0; $j <= $jF; ++$j) { - $R->set($i - $i0, $j - $j0, $this->A[$i][$j]); - } - } - - return $R; - //$R = array of row indices; $C = array of column indices - case 'array,array': - [$RL, $CL] = $args; - if (count($RL) > 0) { - $m = count($RL); - } else { - throw new CalculationException(self::ARGUMENT_BOUNDS_EXCEPTION); - } - if (count($CL) > 0) { - $n = count($CL); - } else { - throw new CalculationException(self::ARGUMENT_BOUNDS_EXCEPTION); - } - $R = new self($m, $n); - for ($i = 0; $i < $m; ++$i) { - for ($j = 0; $j < $n; ++$j) { - $R->set($i, $j, $this->A[$RL[$i]][$CL[$j]]); - } - } - - return $R; - //A($i0...$iF); $CL = array of column indices - case 'integer,integer,array': - [$i0, $iF, $CL] = $args; - if (($iF > $i0) && ($this->m >= $iF) && ($i0 >= 0)) { - $m = $iF - $i0; - } else { - throw new CalculationException(self::ARGUMENT_BOUNDS_EXCEPTION); - } - if (count($CL) > 0) { - $n = count($CL); - } else { - throw new CalculationException(self::ARGUMENT_BOUNDS_EXCEPTION); - } - $R = new self($m, $n); - for ($i = $i0; $i < $iF; ++$i) { - for ($j = 0; $j < $n; ++$j) { - $R->set($i - $i0, $j, $this->A[$i][$CL[$j]]); - } - } - - return $R; - //$RL = array of row indices - case 'array,integer,integer': - [$RL, $j0, $jF] = $args; - if (count($RL) > 0) { - $m = count($RL); - } else { - throw new CalculationException(self::ARGUMENT_BOUNDS_EXCEPTION); - } - if (($jF >= $j0) && ($this->n >= $jF) && ($j0 >= 0)) { - $n = $jF - $j0; - } else { - throw new CalculationException(self::ARGUMENT_BOUNDS_EXCEPTION); - } - $R = new self($m, $n + 1); - for ($i = 0; $i < $m; ++$i) { - for ($j = $j0; $j <= $jF; ++$j) { - $R->set($i, $j - $j0, $this->A[$RL[$i]][$j]); - } - } - - return $R; - default: - throw new CalculationException(self::POLYMORPHIC_ARGUMENT_EXCEPTION); - - break; - } - } else { - throw new CalculationException(self::POLYMORPHIC_ARGUMENT_EXCEPTION); - } - } - - /** - * checkMatrixDimensions. - * - * Is matrix B the same size? - * - * @param Matrix $B Matrix B - * - * @return bool - */ - public function checkMatrixDimensions($B = null) - { - if ($B instanceof self) { - if (($this->m == $B->getRowDimension()) && ($this->n == $B->getColumnDimension())) { - return true; - } - - throw new CalculationException(self::MATRIX_DIMENSION_EXCEPTION); - } - - throw new CalculationException(self::ARGUMENT_TYPE_EXCEPTION); - } - - // function checkMatrixDimensions() - - /** - * set. - * - * Set the i,j-th element of the matrix. - * - * @param int $i Row position - * @param int $j Column position - * @param float|int $c value - */ - public function set($i = null, $j = null, $c = null): void - { - // Optimized set version just has this - $this->A[$i][$j] = $c; - } - - // function set() - - /** - * identity. - * - * Generate an identity matrix. - * - * @param int $m Row dimension - * @param int $n Column dimension - * - * @return Matrix Identity matrix - */ - public function identity($m = null, $n = null) - { - return $this->diagonal($m, $n, 1); - } - - /** - * diagonal. - * - * Generate a diagonal matrix - * - * @param int $m Row dimension - * @param int $n Column dimension - * @param mixed $c Diagonal value - * - * @return Matrix Diagonal matrix - */ - public function diagonal($m = null, $n = null, $c = 1) - { - $R = new self($m, $n); - for ($i = 0; $i < $m; ++$i) { - $R->set($i, $i, $c); - } - - return $R; - } - - /** - * getMatrixByRow. - * - * Get a submatrix by row index/range - * - * @param int $i0 Initial row index - * @param int $iF Final row index - * - * @return Matrix Submatrix - */ - public function getMatrixByRow($i0 = null, $iF = null) - { - if (is_int($i0)) { - if (is_int($iF)) { - return $this->getMatrix($i0, 0, $iF + 1, $this->n); - } - - return $this->getMatrix($i0, 0, $i0 + 1, $this->n); - } - - throw new CalculationException(self::ARGUMENT_TYPE_EXCEPTION); - } - - /** - * getMatrixByCol. - * - * Get a submatrix by column index/range - * - * @param int $j0 Initial column index - * @param int $jF Final column index - * - * @return Matrix Submatrix - */ - public function getMatrixByCol($j0 = null, $jF = null) - { - if (is_int($j0)) { - if (is_int($jF)) { - return $this->getMatrix(0, $j0, $this->m, $jF + 1); - } - - return $this->getMatrix(0, $j0, $this->m, $j0 + 1); - } - - throw new CalculationException(self::ARGUMENT_TYPE_EXCEPTION); - } - - /** - * transpose. - * - * Tranpose matrix - * - * @return Matrix Transposed matrix - */ - public function transpose() - { - $R = new self($this->n, $this->m); - for ($i = 0; $i < $this->m; ++$i) { - for ($j = 0; $j < $this->n; ++$j) { - $R->set($j, $i, $this->A[$i][$j]); - } - } - - return $R; - } - - // function transpose() - - /** - * trace. - * - * Sum of diagonal elements - * - * @return float Sum of diagonal elements - */ - public function trace() - { - $s = 0; - $n = min($this->m, $this->n); - for ($i = 0; $i < $n; ++$i) { - $s += $this->A[$i][$i]; - } - - return $s; - } - - /** - * plus. - * - * A + B - * - * @return Matrix Sum - */ - public function plus(...$args) - { - if (count($args) > 0) { - $match = implode(',', array_map('gettype', $args)); - - switch ($match) { - case 'object': - if ($args[0] instanceof self) { - $M = $args[0]; - } else { - throw new CalculationException(self::ARGUMENT_TYPE_EXCEPTION); - } - - break; - case 'array': - $M = new self($args[0]); - - break; - default: - throw new CalculationException(self::POLYMORPHIC_ARGUMENT_EXCEPTION); - - break; - } - $this->checkMatrixDimensions($M); - for ($i = 0; $i < $this->m; ++$i) { - for ($j = 0; $j < $this->n; ++$j) { - $M->set($i, $j, $M->get($i, $j) + $this->A[$i][$j]); - } - } - - return $M; - } - - throw new CalculationException(self::POLYMORPHIC_ARGUMENT_EXCEPTION); - } - - /** - * plusEquals. - * - * A = A + B - * - * @return $this - */ - public function plusEquals(...$args) - { - if (count($args) > 0) { - $match = implode(',', array_map('gettype', $args)); - - switch ($match) { - case 'object': - if ($args[0] instanceof self) { - $M = $args[0]; - } else { - throw new CalculationException(self::ARGUMENT_TYPE_EXCEPTION); - } - - break; - case 'array': - $M = new self($args[0]); - - break; - default: - throw new CalculationException(self::POLYMORPHIC_ARGUMENT_EXCEPTION); - - break; - } - $this->checkMatrixDimensions($M); - for ($i = 0; $i < $this->m; ++$i) { - for ($j = 0; $j < $this->n; ++$j) { - $validValues = true; - $value = $M->get($i, $j); - [$this->A[$i][$j], $validValues] = $this->validateExtractedValue($this->A[$i][$j], $validValues); - [$value, $validValues] = $this->validateExtractedValue($value, /** @scrutinizer ignore-type */ $validValues); - if ($validValues) { - $this->A[$i][$j] += $value; - } else { - $this->A[$i][$j] = ExcelError::NAN(); - } - } - } - - return $this; - } - - throw new CalculationException(self::POLYMORPHIC_ARGUMENT_EXCEPTION); - } - - /** - * minus. - * - * A - B - * - * @return Matrix Sum - */ - public function minus(...$args) - { - if (count($args) > 0) { - $match = implode(',', array_map('gettype', $args)); - - switch ($match) { - case 'object': - if ($args[0] instanceof self) { - $M = $args[0]; - } else { - throw new CalculationException(self::ARGUMENT_TYPE_EXCEPTION); - } - - break; - case 'array': - $M = new self($args[0]); - - break; - default: - throw new CalculationException(self::POLYMORPHIC_ARGUMENT_EXCEPTION); - - break; - } - $this->checkMatrixDimensions($M); - for ($i = 0; $i < $this->m; ++$i) { - for ($j = 0; $j < $this->n; ++$j) { - $M->set($i, $j, $M->get($i, $j) - $this->A[$i][$j]); - } - } - - return $M; - } - - throw new CalculationException(self::POLYMORPHIC_ARGUMENT_EXCEPTION); - } - - /** - * minusEquals. - * - * A = A - B - * - * @return $this - */ - public function minusEquals(...$args) - { - if (count($args) > 0) { - $match = implode(',', array_map('gettype', $args)); - - switch ($match) { - case 'object': - if ($args[0] instanceof self) { - $M = $args[0]; - } else { - throw new CalculationException(self::ARGUMENT_TYPE_EXCEPTION); - } - - break; - case 'array': - $M = new self($args[0]); - - break; - default: - throw new CalculationException(self::POLYMORPHIC_ARGUMENT_EXCEPTION); - - break; - } - $this->checkMatrixDimensions($M); - for ($i = 0; $i < $this->m; ++$i) { - for ($j = 0; $j < $this->n; ++$j) { - $validValues = true; - $value = $M->get($i, $j); - [$this->A[$i][$j], $validValues] = $this->validateExtractedValue($this->A[$i][$j], $validValues); - [$value, $validValues] = $this->validateExtractedValue($value, /** @scrutinizer ignore-type */ $validValues); - if ($validValues) { - $this->A[$i][$j] -= $value; - } else { - $this->A[$i][$j] = ExcelError::NAN(); - } - } - } - - return $this; - } - - throw new CalculationException(self::POLYMORPHIC_ARGUMENT_EXCEPTION); - } - - /** - * arrayTimes. - * - * Element-by-element multiplication - * Cij = Aij * Bij - * - * @return Matrix Matrix Cij - */ - public function arrayTimes(...$args) - { - if (count($args) > 0) { - $match = implode(',', array_map('gettype', $args)); - - switch ($match) { - case 'object': - if ($args[0] instanceof self) { - $M = $args[0]; - } else { - throw new CalculationException(self::ARGUMENT_TYPE_EXCEPTION); - } - - break; - case 'array': - $M = new self($args[0]); - - break; - default: - throw new CalculationException(self::POLYMORPHIC_ARGUMENT_EXCEPTION); - - break; - } - $this->checkMatrixDimensions($M); - for ($i = 0; $i < $this->m; ++$i) { - for ($j = 0; $j < $this->n; ++$j) { - $M->set($i, $j, $M->get($i, $j) * $this->A[$i][$j]); - } - } - - return $M; - } - - throw new CalculationException(self::POLYMORPHIC_ARGUMENT_EXCEPTION); - } - - /** - * arrayTimesEquals. - * - * Element-by-element multiplication - * Aij = Aij * Bij - * - * @return $this - */ - public function arrayTimesEquals(...$args) - { - if (count($args) > 0) { - $match = implode(',', array_map('gettype', $args)); - - switch ($match) { - case 'object': - if ($args[0] instanceof self) { - $M = $args[0]; - } else { - throw new CalculationException(self::ARGUMENT_TYPE_EXCEPTION); - } - - break; - case 'array': - $M = new self($args[0]); - - break; - default: - throw new CalculationException(self::POLYMORPHIC_ARGUMENT_EXCEPTION); - - break; - } - $this->checkMatrixDimensions($M); - for ($i = 0; $i < $this->m; ++$i) { - for ($j = 0; $j < $this->n; ++$j) { - $validValues = true; - $value = $M->get($i, $j); - [$this->A[$i][$j], $validValues] = $this->validateExtractedValue($this->A[$i][$j], $validValues); - [$value, $validValues] = $this->validateExtractedValue($value, /** @scrutinizer ignore-type */ $validValues); - if ($validValues) { - $this->A[$i][$j] *= $value; - } else { - $this->A[$i][$j] = ExcelError::NAN(); - } - } - } - - return $this; - } - - throw new CalculationException(self::POLYMORPHIC_ARGUMENT_EXCEPTION); - } - - /** - * arrayRightDivide. - * - * Element-by-element right division - * A / B - * - * @return Matrix Division result - */ - public function arrayRightDivide(...$args) - { - if (count($args) > 0) { - $match = implode(',', array_map('gettype', $args)); - - switch ($match) { - case 'object': - if ($args[0] instanceof self) { - $M = $args[0]; - } else { - throw new CalculationException(self::ARGUMENT_TYPE_EXCEPTION); - } - - break; - case 'array': - $M = new self($args[0]); - - break; - default: - throw new CalculationException(self::POLYMORPHIC_ARGUMENT_EXCEPTION); - - break; - } - $this->checkMatrixDimensions($M); - for ($i = 0; $i < $this->m; ++$i) { - for ($j = 0; $j < $this->n; ++$j) { - $validValues = true; - $value = $M->get($i, $j); - [$this->A[$i][$j], $validValues] = $this->validateExtractedValue($this->A[$i][$j], $validValues); - [$value, $validValues] = $this->validateExtractedValue($value, /** @scrutinizer ignore-type */ $validValues); - if ($validValues) { - if ($value == 0) { - // Trap for Divide by Zero error - $M->set($i, $j, /** @scrutinizer ignore-type */ '#DIV/0!'); - } else { - $M->set($i, $j, $this->A[$i][$j] / $value); - } - } else { - $M->set($i, $j, /** @scrutinizer ignore-type */ ExcelError::NAN()); - } - } - } - - return $M; - } - - throw new CalculationException(self::POLYMORPHIC_ARGUMENT_EXCEPTION); - } - - /** - * arrayRightDivideEquals. - * - * Element-by-element right division - * Aij = Aij / Bij - * - * @return Matrix Matrix Aij - */ - public function arrayRightDivideEquals(...$args) - { - if (count($args) > 0) { - $match = implode(',', array_map('gettype', $args)); - - switch ($match) { - case 'object': - if ($args[0] instanceof self) { - $M = $args[0]; - } else { - throw new CalculationException(self::ARGUMENT_TYPE_EXCEPTION); - } - - break; - case 'array': - $M = new self($args[0]); - - break; - default: - throw new CalculationException(self::POLYMORPHIC_ARGUMENT_EXCEPTION); - - break; - } - $this->checkMatrixDimensions($M); - for ($i = 0; $i < $this->m; ++$i) { - for ($j = 0; $j < $this->n; ++$j) { - $this->A[$i][$j] = $this->A[$i][$j] / $M->get($i, $j); - } - } - - return $M; - } - - throw new CalculationException(self::POLYMORPHIC_ARGUMENT_EXCEPTION); - } - - /** - * arrayLeftDivide. - * - * Element-by-element Left division - * A / B - * - * @return Matrix Division result - */ - public function arrayLeftDivide(...$args) - { - if (count($args) > 0) { - $match = implode(',', array_map('gettype', $args)); - - switch ($match) { - case 'object': - if ($args[0] instanceof self) { - $M = $args[0]; - } else { - throw new CalculationException(self::ARGUMENT_TYPE_EXCEPTION); - } - - break; - case 'array': - $M = new self($args[0]); - - break; - default: - throw new CalculationException(self::POLYMORPHIC_ARGUMENT_EXCEPTION); - - break; - } - $this->checkMatrixDimensions($M); - for ($i = 0; $i < $this->m; ++$i) { - for ($j = 0; $j < $this->n; ++$j) { - $M->set($i, $j, $M->get($i, $j) / $this->A[$i][$j]); - } - } - - return $M; - } - - throw new CalculationException(self::POLYMORPHIC_ARGUMENT_EXCEPTION); - } - - /** - * arrayLeftDivideEquals. - * - * Element-by-element Left division - * Aij = Aij / Bij - * - * @return Matrix Matrix Aij - */ - public function arrayLeftDivideEquals(...$args) - { - if (count($args) > 0) { - $match = implode(',', array_map('gettype', $args)); - - switch ($match) { - case 'object': - if ($args[0] instanceof self) { - $M = $args[0]; - } else { - throw new CalculationException(self::ARGUMENT_TYPE_EXCEPTION); - } - - break; - case 'array': - $M = new self($args[0]); - - break; - default: - throw new CalculationException(self::POLYMORPHIC_ARGUMENT_EXCEPTION); - - break; - } - $this->checkMatrixDimensions($M); - for ($i = 0; $i < $this->m; ++$i) { - for ($j = 0; $j < $this->n; ++$j) { - $this->A[$i][$j] = $M->get($i, $j) / $this->A[$i][$j]; - } - } - - return $M; - } - - throw new CalculationException(self::POLYMORPHIC_ARGUMENT_EXCEPTION); - } - - /** - * times. - * - * Matrix multiplication - * - * @return Matrix Product - */ - public function times(...$args) - { - if (count($args) > 0) { - $match = implode(',', array_map('gettype', $args)); - - switch ($match) { - case 'object': - if ($args[0] instanceof self) { - $B = $args[0]; - } else { - throw new CalculationException(self::ARGUMENT_TYPE_EXCEPTION); - } - if ($this->n == $B->m) { - $C = new self($this->m, $B->n); - for ($j = 0; $j < $B->n; ++$j) { - $Bcolj = []; - for ($k = 0; $k < $this->n; ++$k) { - $Bcolj[$k] = $B->A[$k][$j]; - } - for ($i = 0; $i < $this->m; ++$i) { - $Arowi = $this->A[$i]; - $s = 0; - for ($k = 0; $k < $this->n; ++$k) { - $s += $Arowi[$k] * $Bcolj[$k]; - } - $C->A[$i][$j] = $s; - } - } - - return $C; - } - - throw new CalculationException(self::MATRIX_DIMENSION_EXCEPTION); - case 'array': - $B = new self($args[0]); - if ($this->n == $B->m) { - $C = new self($this->m, $B->n); - for ($i = 0; $i < $C->m; ++$i) { - for ($j = 0; $j < $C->n; ++$j) { - $s = '0'; - for ($k = 0; $k < $C->n; ++$k) { - $s += $this->A[$i][$k] * $B->A[$k][$j]; - } - $C->A[$i][$j] = $s; - } - } - - return $C; - } - - throw new CalculationException(self::MATRIX_DIMENSION_EXCEPTION); - case 'integer': - $C = new self($this->A); - for ($i = 0; $i < $C->m; ++$i) { - for ($j = 0; $j < $C->n; ++$j) { - $C->A[$i][$j] *= $args[0]; - } - } - - return $C; - case 'double': - $C = new self($this->m, $this->n); - for ($i = 0; $i < $C->m; ++$i) { - for ($j = 0; $j < $C->n; ++$j) { - $C->A[$i][$j] = $args[0] * $this->A[$i][$j]; - } - } - - return $C; - case 'float': - $C = new self($this->A); - for ($i = 0; $i < $C->m; ++$i) { - for ($j = 0; $j < $C->n; ++$j) { - $C->A[$i][$j] *= $args[0]; - } - } - - return $C; - default: - throw new CalculationException(self::POLYMORPHIC_ARGUMENT_EXCEPTION); - } - } else { - throw new CalculationException(self::POLYMORPHIC_ARGUMENT_EXCEPTION); - } - } - - /** - * power. - * - * A = A ^ B - * - * @return $this - */ - public function power(...$args) - { - if (count($args) > 0) { - $match = implode(',', array_map('gettype', $args)); - - switch ($match) { - case 'object': - if ($args[0] instanceof self) { - $M = $args[0]; - } else { - throw new CalculationException(self::ARGUMENT_TYPE_EXCEPTION); - } - - break; - case 'array': - $M = new self($args[0]); - - break; - default: - throw new CalculationException(self::POLYMORPHIC_ARGUMENT_EXCEPTION); - - break; - } - $this->checkMatrixDimensions($M); - for ($i = 0; $i < $this->m; ++$i) { - for ($j = 0; $j < $this->n; ++$j) { - $validValues = true; - $value = $M->get($i, $j); - [$this->A[$i][$j], $validValues] = $this->validateExtractedValue($this->A[$i][$j], $validValues); - [$value, $validValues] = $this->validateExtractedValue($value, /** @scrutinizer ignore-type */ $validValues); - if ($validValues) { - $this->A[$i][$j] = $this->A[$i][$j] ** $value; - } else { - $this->A[$i][$j] = ExcelError::NAN(); - } - } - } - - return $this; - } - - throw new CalculationException(self::POLYMORPHIC_ARGUMENT_EXCEPTION); - } - - /** - * concat. - * - * A = A & B - * - * @return $this - */ - public function concat(...$args) - { - if (count($args) > 0) { - $match = implode(',', array_map('gettype', $args)); - - switch ($match) { - case 'object': - if ($args[0] instanceof self) { - $M = $args[0]; - } else { - throw new CalculationException(self::ARGUMENT_TYPE_EXCEPTION); - } - - break; - case 'array': - $M = new self($args[0]); - - break; - default: - throw new CalculationException(self::POLYMORPHIC_ARGUMENT_EXCEPTION); - - break; - } - $this->checkMatrixDimensions($M); - for ($i = 0; $i < $this->m; ++$i) { - for ($j = 0; $j < $this->n; ++$j) { - // @phpstan-ignore-next-line - $this->A[$i][$j] = trim($this->A[$i][$j], '"') . trim($M->get($i, $j), '"'); - } - } - - return $this; - } - - throw new CalculationException(self::POLYMORPHIC_ARGUMENT_EXCEPTION); - } - - /** - * Solve A*X = B. - * - * @param Matrix $B Right hand side - * - * @return Matrix ... Solution if A is square, least squares solution otherwise - */ - public function solve(self $B) - { - if ($this->m == $this->n) { - $LU = new LUDecomposition($this); - - return $LU->solve($B); - } - $QR = new QRDecomposition($this); - - return $QR->solve($B); - } - - /** - * Matrix inverse or pseudoinverse. - * - * @return Matrix ... Inverse(A) if A is square, pseudoinverse otherwise. - */ - public function inverse() - { - return $this->solve($this->identity($this->m, $this->m)); - } - - /** - * det. - * - * Calculate determinant - * - * @return float Determinant - */ - public function det() - { - $L = new LUDecomposition($this); - - return $L->det(); - } - - /** - * @param mixed $value - */ - private function validateExtractedValue($value, bool $validValues): array - { - if (!is_numeric($value) && is_array($value)) { - $value = Functions::flattenArray($value)[0]; - } - if ((is_string($value)) && (strlen($value) > 0) && (!is_numeric($value))) { - $value = trim($value, '"'); - $validValues &= FormattedNumber::convertToNumberIfFormatted($value); - } - - return [$value, $validValues]; - } -} diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/JAMA/QRDecomposition.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/JAMA/QRDecomposition.php deleted file mode 100644 index 9b51f41..0000000 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/JAMA/QRDecomposition.php +++ /dev/null @@ -1,245 +0,0 @@ -= n, the QR decomposition is an m-by-n - * orthogonal matrix Q and an n-by-n upper triangular matrix R so that - * A = Q*R. - * - * The QR decompostion always exists, even if the matrix does not have - * full rank, so the constructor will never fail. The primary use of the - * QR decomposition is in the least squares solution of nonsquare systems - * of simultaneous linear equations. This will fail if isFullRank() - * returns false. - * - * @author Paul Meagher - * - * @version 1.1 - */ -class QRDecomposition -{ - const MATRIX_RANK_EXCEPTION = 'Can only perform operation on full-rank matrix.'; - - /** - * Array for internal storage of decomposition. - * - * @var array - */ - private $QR = []; - - /** - * Row dimension. - * - * @var int - */ - private $m; - - /** - * Column dimension. - * - * @var int - */ - private $n; - - /** - * Array for internal storage of diagonal of R. - * - * @var array - */ - private $Rdiag = []; - - /** - * QR Decomposition computed by Householder reflections. - * - * @param Matrix $A Rectangular matrix - */ - public function __construct(Matrix $A) - { - // Initialize. - $this->QR = $A->getArray(); - $this->m = $A->getRowDimension(); - $this->n = $A->getColumnDimension(); - // Main loop. - for ($k = 0; $k < $this->n; ++$k) { - // Compute 2-norm of k-th column without under/overflow. - $nrm = 0.0; - for ($i = $k; $i < $this->m; ++$i) { - $nrm = hypo($nrm, $this->QR[$i][$k]); - } - if ($nrm != 0.0) { - // Form k-th Householder vector. - if ($this->QR[$k][$k] < 0) { - $nrm = -$nrm; - } - for ($i = $k; $i < $this->m; ++$i) { - $this->QR[$i][$k] /= $nrm; - } - $this->QR[$k][$k] += 1.0; - // Apply transformation to remaining columns. - for ($j = $k + 1; $j < $this->n; ++$j) { - $s = 0.0; - for ($i = $k; $i < $this->m; ++$i) { - $s += $this->QR[$i][$k] * $this->QR[$i][$j]; - } - $s = -$s / $this->QR[$k][$k]; - for ($i = $k; $i < $this->m; ++$i) { - $this->QR[$i][$j] += $s * $this->QR[$i][$k]; - } - } - } - $this->Rdiag[$k] = -$nrm; - } - } - - // function __construct() - - /** - * Is the matrix full rank? - * - * @return bool true if R, and hence A, has full rank, else false - */ - public function isFullRank() - { - for ($j = 0; $j < $this->n; ++$j) { - if ($this->Rdiag[$j] == 0) { - return false; - } - } - - return true; - } - - // function isFullRank() - - /** - * Return the Householder vectors. - * - * @return Matrix Lower trapezoidal matrix whose columns define the reflections - */ - public function getH() - { - $H = []; - for ($i = 0; $i < $this->m; ++$i) { - for ($j = 0; $j < $this->n; ++$j) { - if ($i >= $j) { - $H[$i][$j] = $this->QR[$i][$j]; - } else { - $H[$i][$j] = 0.0; - } - } - } - - return new Matrix($H); - } - - // function getH() - - /** - * Return the upper triangular factor. - * - * @return Matrix upper triangular factor - */ - public function getR() - { - $R = []; - for ($i = 0; $i < $this->n; ++$i) { - for ($j = 0; $j < $this->n; ++$j) { - if ($i < $j) { - $R[$i][$j] = $this->QR[$i][$j]; - } elseif ($i == $j) { - $R[$i][$j] = $this->Rdiag[$i]; - } else { - $R[$i][$j] = 0.0; - } - } - } - - return new Matrix($R); - } - - // function getR() - - /** - * Generate and return the (economy-sized) orthogonal factor. - * - * @return Matrix orthogonal factor - */ - public function getQ() - { - $Q = []; - for ($k = $this->n - 1; $k >= 0; --$k) { - for ($i = 0; $i < $this->m; ++$i) { - $Q[$i][$k] = 0.0; - } - $Q[$k][$k] = 1.0; - for ($j = $k; $j < $this->n; ++$j) { - if ($this->QR[$k][$k] != 0) { - $s = 0.0; - for ($i = $k; $i < $this->m; ++$i) { - $s += $this->QR[$i][$k] * $Q[$i][$j]; - } - $s = -$s / $this->QR[$k][$k]; - for ($i = $k; $i < $this->m; ++$i) { - $Q[$i][$j] += $s * $this->QR[$i][$k]; - } - } - } - } - - return new Matrix($Q); - } - - // function getQ() - - /** - * Least squares solution of A*X = B. - * - * @param Matrix $B a Matrix with as many rows as A and any number of columns - * - * @return Matrix matrix that minimizes the two norm of Q*R*X-B - */ - public function solve(Matrix $B) - { - if ($B->getRowDimension() == $this->m) { - if ($this->isFullRank()) { - // Copy right hand side - $nx = $B->getColumnDimension(); - $X = $B->getArray(); - // Compute Y = transpose(Q)*B - for ($k = 0; $k < $this->n; ++$k) { - for ($j = 0; $j < $nx; ++$j) { - $s = 0.0; - for ($i = $k; $i < $this->m; ++$i) { - $s += $this->QR[$i][$k] * $X[$i][$j]; - } - $s = -$s / $this->QR[$k][$k]; - for ($i = $k; $i < $this->m; ++$i) { - $X[$i][$j] += $s * $this->QR[$i][$k]; - } - } - } - // Solve R*X = Y; - for ($k = $this->n - 1; $k >= 0; --$k) { - for ($j = 0; $j < $nx; ++$j) { - $X[$k][$j] /= $this->Rdiag[$k]; - } - for ($i = 0; $i < $k; ++$i) { - for ($j = 0; $j < $nx; ++$j) { - $X[$i][$j] -= $X[$k][$j] * $this->QR[$i][$k]; - } - } - } - $X = new Matrix($X); - - return $X->getMatrix(0, $this->n - 1, 0, $nx); - } - - throw new CalculationException(self::MATRIX_RANK_EXCEPTION); - } - - throw new CalculationException(Matrix::MATRIX_DIMENSION_EXCEPTION); - } -} diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/JAMA/utils/Maths.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/JAMA/utils/Maths.php deleted file mode 100644 index 49877b2..0000000 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/JAMA/utils/Maths.php +++ /dev/null @@ -1,31 +0,0 @@ - abs($b)) { - $r = $b / $a; - $r = abs($a) * sqrt(1 + $r * $r); - } elseif ($b != 0) { - $r = $a / $b; - $r = abs($b) * sqrt(1 + $r * $r); - } else { - $r = 0.0; - } - - return $r; -} diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE.php index 815b1c1..c14afb2 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE.php @@ -116,7 +116,7 @@ class OLE */ public function read($filename) { - $fh = fopen($filename, 'rb'); + $fh = @fopen($filename, 'rb'); if ($fh === false) { throw new ReaderException("Can't open file $filename"); } @@ -239,7 +239,12 @@ public function getStream($blockIdOrPps) $path .= '&blockId=' . $blockIdOrPps; } - return fopen($path, 'rb'); + $resource = fopen($path, 'rb'); + if ($resource === false) { + throw new Exception("Unable to open stream $path"); + } + + return $resource; } /** @@ -251,8 +256,7 @@ public function getStream($blockIdOrPps) */ private static function readInt1($fileHandle) { - // @phpstan-ignore-next-line - [, $tmp] = unpack('c', fread($fileHandle, 1)); + [, $tmp] = unpack('c', fread($fileHandle, 1) ?: '') ?: [0, 0]; return $tmp; } @@ -266,14 +270,17 @@ private static function readInt1($fileHandle) */ private static function readInt2($fileHandle) { - // @phpstan-ignore-next-line - [, $tmp] = unpack('v', fread($fileHandle, 2)); + [, $tmp] = unpack('v', fread($fileHandle, 2) ?: '') ?: [0, 0]; return $tmp; } + private const SIGNED_4OCTET_LIMIT = 2147483648; + + private const SIGNED_4OCTET_SUBTRACT = 2 * self::SIGNED_4OCTET_LIMIT; + /** - * Reads an unsigned long (4 octets). + * Reads long (4 octets), interpreted as if signed on 32-bit system. * * @param resource $fileHandle file handle * @@ -281,8 +288,10 @@ private static function readInt2($fileHandle) */ private static function readInt4($fileHandle) { - // @phpstan-ignore-next-line - [, $tmp] = unpack('V', fread($fileHandle, 4)); + [, $tmp] = unpack('V', fread($fileHandle, 4) ?: '') ?: [0, 0]; + if ($tmp >= self::SIGNED_4OCTET_LIMIT) { + $tmp -= self::SIGNED_4OCTET_SUBTRACT; + } return $tmp; } @@ -300,7 +309,7 @@ public function readPpsWks($blockId) $fh = $this->getStream($blockId); for ($pos = 0; true; $pos += 128) { fseek($fh, $pos, SEEK_SET); - $nameUtf16 = fread($fh, 64); + $nameUtf16 = (string) fread($fh, 64); $nameLength = self::readInt2($fh); $nameUtf16 = substr($nameUtf16, 0, $nameLength - 2); // Simple conversion from UTF-16LE to ISO-8859-1 @@ -330,15 +339,15 @@ public function readPpsWks($blockId) $pps->NextPps = self::readInt4($fh); $pps->DirPps = self::readInt4($fh); fseek($fh, 20, SEEK_CUR); - $pps->Time1st = self::OLE2LocalDate(fread($fh, 8)); - $pps->Time2nd = self::OLE2LocalDate(fread($fh, 8)); + $pps->Time1st = self::OLE2LocalDate((string) fread($fh, 8)); + $pps->Time2nd = self::OLE2LocalDate((string) fread($fh, 8)); $pps->startBlock = self::readInt4($fh); $pps->Size = self::readInt4($fh); $pps->No = count($this->_list); $this->_list[] = $pps; // check if the PPS tree (starting from root) is complete - if (isset($this->root) && $this->ppsTreeComplete($this->root->No)) { + if (isset($this->root) && $this->ppsTreeComplete($this->root->No)) { //* @phpstan-ignore-line break; } } @@ -448,7 +457,7 @@ public function getData($index, $position, $length) return ''; } $fh = $this->getStream($this->_list[$index]); - $data = stream_get_contents($fh, $length, $position); + $data = (string) stream_get_contents($fh, $length, $position); fclose($fh); return $data; @@ -540,7 +549,7 @@ public static function OLE2LocalDate($oleTimestamp) } // convert to units of 100 ns since 1601: - $unpackedTimestamp = unpack('v4', $oleTimestamp); + $unpackedTimestamp = unpack('v4', $oleTimestamp) ?: []; $timestampHigh = (float) $unpackedTimestamp[4] * 65536 + (float) $unpackedTimestamp[3]; $timestampLow = (float) $unpackedTimestamp[2] * 65536 + (float) $unpackedTimestamp[1]; diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE/ChainedBlockStream.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE/ChainedBlockStream.php index ee93c05..5d5babc 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE/ChainedBlockStream.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE/ChainedBlockStream.php @@ -6,6 +6,9 @@ class ChainedBlockStream { + /** @var mixed */ + public $context; + /** * The OLE container of the file that is being read. * @@ -48,7 +51,7 @@ class ChainedBlockStream */ public function stream_open($path, $mode, $options, &$openedPath) // @codingStandardsIgnoreLine { - if ($mode != 'r') { + if ($mode[0] !== 'r') { if ($options & STREAM_REPORT_ERRORS) { trigger_error('Only reading is supported', E_USER_WARNING); } @@ -119,7 +122,7 @@ public function stream_read($count) // @codingStandardsIgnoreLine if ($this->stream_eof()) { return false; } - $s = substr($this->data, $this->pos, $count); + $s = substr($this->data, (int) $this->pos, $count); $this->pos += $count; return $s; @@ -160,7 +163,7 @@ public function stream_seek($offset, $whence) // @codingStandardsIgnoreLine $this->pos = $offset; } elseif ($whence == SEEK_CUR && -$offset <= $this->pos) { $this->pos += $offset; - // @phpstan-ignore-next-line + // @phpstan-ignore-next-line } elseif ($whence == SEEK_END && -$offset <= count(/** @scrutinizer ignore-type */ $this->data)) { $this->pos = strlen($this->data) + $offset; } else { diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE/PPS.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE/PPS.php index d3d86f5..2740a1b 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE/PPS.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE/PPS.php @@ -88,7 +88,7 @@ class PPS /** * Starting block (small or big) for this PPS's data inside the container. * - * @var int + * @var ?int */ public $startBlock; @@ -104,7 +104,7 @@ class PPS * * @var string */ - public $_data; + public $_data = ''; /** * Array of child PPS's (only used by Root and Dir PPS's). @@ -123,34 +123,30 @@ class PPS /** * The constructor. * - * @param int $No The PPS index - * @param string $name The PPS name - * @param int $type The PPS type. Dir, Root or File - * @param int $prev The index of the previous PPS - * @param int $next The index of the next PPS - * @param int $dir The index of it's first child if this is a Dir or Root PPS + * @param ?int $No The PPS index + * @param ?string $name The PPS name + * @param ?int $type The PPS type. Dir, Root or File + * @param ?int $prev The index of the previous PPS + * @param ?int $next The index of the next PPS + * @param ?int $dir The index of it's first child if this is a Dir or Root PPS * @param null|float|int $time_1st A timestamp * @param null|float|int $time_2nd A timestamp - * @param string $data The (usually binary) source data of the PPS + * @param ?string $data The (usually binary) source data of the PPS * @param array $children Array containing children PPS for this PPS */ public function __construct($No, $name, $type, $prev, $next, $dir, $time_1st, $time_2nd, $data, $children) { - $this->No = $No; - $this->Name = $name; - $this->Type = $type; - $this->PrevPps = $prev; - $this->NextPps = $next; - $this->DirPps = $dir; + $this->No = (int) $No; + $this->Name = (string) $name; + $this->Type = (int) $type; + $this->PrevPps = (int) $prev; + $this->NextPps = (int) $next; + $this->DirPps = (int) $dir; $this->Time1st = $time_1st ?? 0; $this->Time2nd = $time_2nd ?? 0; - $this->_data = $data; + $this->_data = (string) $data; $this->children = $children; - if ($data != '') { - $this->Size = strlen($data); - } else { - $this->Size = 0; - } + $this->Size = strlen((string) $data); } /** @@ -160,9 +156,9 @@ public function __construct($No, $name, $type, $prev, $next, $dir, $time_1st, $t */ public function getDataLen() { - if (!isset($this->_data)) { - return 0; - } + //if (!isset($this->_data)) { + // return 0; + //} return strlen($this->_data); } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE/PPS/Root.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE/PPS/Root.php index 3fe8af2..e1cbf8c 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE/PPS/Root.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE/PPS/Root.php @@ -36,12 +36,12 @@ class Root extends PPS private $fileHandle; /** - * @var int + * @var ?int */ private $smallBlockSize; /** - * @var int + * @var ?int */ private $bigBlockSize; diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLERead.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLERead.php index b3e35c5..fcc9639 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLERead.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLERead.php @@ -6,6 +6,7 @@ class OLERead { + /** @var string */ private $data = ''; // Size of a sector = 512 bytes @@ -34,10 +35,13 @@ class OLERead const START_BLOCK_POS = 0x74; const SIZE_POS = 0x78; + /** @var int */ public $wrkbook; + /** @var int */ public $summaryInformation; + /** @var int */ public $documentSummaryInformation; /** @@ -99,7 +103,7 @@ public function read(string $filename): void // Get the file identifier // Don't bother reading the whole file until we know it's a valid OLE file - $this->data = file_get_contents($filename, false, null, 0, 8); + $this->data = (string) file_get_contents($filename, false, null, 0, 8); // Check OLE identifier $identifierOle = pack('CCCCCCCC', 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1); @@ -108,7 +112,7 @@ public function read(string $filename): void } // Get the file data - $this->data = file_get_contents($filename); + $this->data = (string) file_get_contents($filename); // Total number of sectors used for the SAT $this->numBigBlockDepotBlocks = self::getInt4d($this->data, self::NUM_BIG_BLOCK_DEPOT_BLOCKS_POS); @@ -130,7 +134,7 @@ public function read(string $filename): void $bbdBlocks = $this->numBigBlockDepotBlocks; - if ($this->numExtensionBlocks != 0) { + if ($this->numExtensionBlocks !== 0) { $bbdBlocks = (self::BIG_BLOCK_SIZE - self::BIG_BLOCK_DEPOT_BLOCKS_POS) / 4; } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/StringHelper.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/StringHelper.php index 30bd8c5..c6c198e 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/StringHelper.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/StringHelper.php @@ -451,6 +451,18 @@ public static function countCharacters(string $textValue, string $encoding = 'UT return mb_strlen($textValue, $encoding); } + /** + * Get character count using mb_strwidth rather than mb_strlen. + * + * @param string $encoding Encoding + * + * @return int Character count + */ + public static function countCharactersDbcs(string $textValue, string $encoding = 'UTF-8'): int + { + return mb_strwidth($textValue, $encoding); + } + /** * Get a substring of a UTF-8 encoded string. * diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Trend/BestFit.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Trend/BestFit.php index b2b0d94..a8d7c93 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Trend/BestFit.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Trend/BestFit.php @@ -53,39 +53,55 @@ abstract class BestFit */ protected $yBestFitValues = []; + /** @var float */ protected $goodnessOfFit = 1; + /** @var float */ protected $stdevOfResiduals = 0; + /** @var float */ protected $covariance = 0; + /** @var float */ protected $correlation = 0; + /** @var float */ protected $SSRegression = 0; + /** @var float */ protected $SSResiduals = 0; + /** @var float */ protected $DFResiduals = 0; + /** @var float */ protected $f = 0; + /** @var float */ protected $slope = 0; + /** @var float */ protected $slopeSE = 0; + /** @var float */ protected $intersect = 0; + /** @var float */ protected $intersectSE = 0; + /** @var float */ protected $xOffset = 0; + /** @var float */ protected $yOffset = 0; + /** @return bool */ public function getError() { return $this->error; } + /** @return string */ public function getBestFitType() { return $this->bestFitType; @@ -344,6 +360,16 @@ private static function scrutinizerLooseCompare($x, $y): bool return $x == $y; } + /** + * @param float $sumX + * @param float $sumY + * @param float $sumX2 + * @param float $sumY2 + * @param float $sumXY + * @param float $meanX + * @param float $meanY + * @param bool|int $const + */ protected function calculateGoodnessOfFit($sumX, $sumY, $sumX2, $sumY2, $sumXY, $meanX, $meanY, $const): void { $SSres = $SScov = $SStot = $SSsex = 0.0; @@ -399,6 +425,7 @@ protected function calculateGoodnessOfFit($sumX, $sumY, $sumX2, $sumY2, $sumXY, } } + /** @return float|int */ private function sumSquares(array $values) { return array_sum( diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Trend/PolynomialBestFit.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Trend/PolynomialBestFit.php index ea40e29..222a423 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Trend/PolynomialBestFit.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Trend/PolynomialBestFit.php @@ -2,7 +2,7 @@ namespace PhpOffice\PhpSpreadsheet\Shared\Trend; -use PhpOffice\PhpSpreadsheet\Shared\JAMA\Matrix; +use Matrix\Matrix; // Phpstan and Scrutinizer seem to have legitimate complaints. // $this->slope is specified where an array is expected in several places. @@ -108,6 +108,7 @@ public function getSlope($dp = 0) if ($dp != 0) { $coefficients = []; // Scrutinizer is correct - $this->slope is float, not array. + //* @phpstan-ignore-next-line foreach ($this->slope as $coefficient) { $coefficients[] = round($coefficient, $dp); } @@ -119,6 +120,11 @@ public function getSlope($dp = 0) return $this->slope; } + /** + * @param int $dp + * + * @return array + */ public function getCoefficients($dp = 0) { // Phpstan and Scrutinizer are both correct - getSlope returns float, not array. @@ -167,8 +173,8 @@ private function polynomialRegression($order, $yValues, $xValues): void $C = $matrixA->solve($matrixB); $coefficients = []; - for ($i = 0; $i < $C->getRowDimension(); ++$i) { - $r = $C->get($i, 0); + for ($i = 0; $i < $C->rows; ++$i) { + $r = $C->getValue($i + 1, 1); // row and column are origin-1 if (abs($r) <= 10 ** (-9)) { $r = 0; } @@ -176,6 +182,8 @@ private function polynomialRegression($order, $yValues, $xValues): void } $this->intersect = array_shift($coefficients); + // Phpstan (and maybe Scrutinizer) are correct + //* @phpstan-ignore-next-line $this->slope = $coefficients; $this->calculateGoodnessOfFit($x_sum, $y_sum, $xx_sum, $yy_sum, $xy_sum, 0, 0, 0); diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Trend/Trend.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Trend/Trend.php index 929f59b..117848c 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Trend/Trend.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Trend/Trend.php @@ -48,6 +48,14 @@ class Trend */ private static $trendCache = []; + /** + * @param string $trendType + * @param array $yValues + * @param array $xValues + * @param bool $const + * + * @return mixed + */ public static function calculate($trendType = self::TREND_BEST_FIT, $yValues = [], $xValues = [], $const = true) { // Calculate number of points in each dataset @@ -72,7 +80,6 @@ public static function calculate($trendType = self::TREND_BEST_FIT, $yValues = [ case self::TREND_POWER: if (!isset(self::$trendCache[$key])) { $className = '\PhpOffice\PhpSpreadsheet\Shared\Trend\\' . $trendType . 'BestFit'; - // @phpstan-ignore-next-line self::$trendCache[$key] = new $className($yValues, $xValues, $const); } @@ -96,6 +103,7 @@ public static function calculate($trendType = self::TREND_BEST_FIT, $yValues = [ $bestFitValue = []; foreach (self::$trendTypes as $trendMethod) { $className = '\PhpOffice\PhpSpreadsheet\Shared\Trend\\' . $trendType . 'BestFit'; + //* @phpstan-ignore-next-line $bestFit[$trendMethod] = new $className($yValues, $xValues, $const); $bestFitValue[$trendMethod] = $bestFit[$trendMethod]->getGoodnessOfFit(); } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/XMLWriter.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/XMLWriter.php index 65bd7ec..d9f403d 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/XMLWriter.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/XMLWriter.php @@ -2,6 +2,8 @@ namespace PhpOffice\PhpSpreadsheet\Shared; +use PhpOffice\PhpSpreadsheet\Exception as SpreadsheetException; + class XMLWriter extends \XMLWriter { /** @var bool */ @@ -62,6 +64,13 @@ public function __destruct() } } + public function __wakeup(): void + { + $this->tempFileName = ''; + + throw new SpreadsheetException('Unserialize not permitted'); + } + /** * Get written data. * diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Xls.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Xls.php index 2c3198b..a675834 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Xls.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Xls.php @@ -21,7 +21,7 @@ class Xls public static function sizeCol(Worksheet $worksheet, $col = 'A') { // default font of the workbook - $font = $worksheet->getParent()->getDefaultStyle()->getFont(); + $font = $worksheet->getParentOrThrow()->getDefaultStyle()->getFont(); $columnDimensions = $worksheet->getColumnDimensions(); @@ -64,7 +64,7 @@ public static function sizeCol(Worksheet $worksheet, $col = 'A') public static function sizeRow(Worksheet $worksheet, $row = 1) { // default font of the workbook - $font = $worksheet->getParent()->getDefaultStyle()->getFont(); + $font = $worksheet->getParentOrThrow()->getDefaultStyle()->getFont(); $rowDimensions = $worksheet->getRowDimensions(); diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Spreadsheet.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Spreadsheet.php index 1432ba4..1109085 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Spreadsheet.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Spreadsheet.php @@ -203,6 +203,14 @@ class Spreadsheet implements JsonSerializable */ private $tabRatio = 600; + /** @var Theme */ + private $theme; + + public function getTheme(): Theme + { + return $this->theme; + } + /** * The workbook has macros ? * @@ -476,6 +484,7 @@ public function __construct() { $this->uniqueID = uniqid('', true); $this->calculationEngine = new Calculation($this); + $this->theme = new Theme(); // Initialise worksheet collection and add one worksheet $this->workSheetCollection = []; @@ -643,7 +652,7 @@ public function addSheet(Worksheet $worksheet, $sheetIndex = null) } } - if ($worksheet->getParent() === null) { // @phpstan-ignore-line + if ($worksheet->getParent() === null) { $worksheet->rebindParent($this); } @@ -871,7 +880,7 @@ public function addExternalSheet(Worksheet $worksheet, $sheetIndex = null) $countCellXfs = count($this->cellXfCollection); // copy all the shared cellXfs from the external workbook and append them to the current - foreach ($worksheet->getParent()->getCellXfCollection() as $cellXf) { + foreach ($worksheet->getParentOrThrow()->getCellXfCollection() as $cellXf) { $this->addCellXf(clone $cellXf); } @@ -1654,4 +1663,26 @@ public function jsonSerialize(): mixed { throw new Exception('Spreadsheet objects cannot be json encoded'); } + + public function resetThemeFonts(): void + { + $majorFontLatin = $this->theme->getMajorFontLatin(); + $minorFontLatin = $this->theme->getMinorFontLatin(); + foreach ($this->cellXfCollection as $cellStyleXf) { + $scheme = $cellStyleXf->getFont()->getScheme(); + if ($scheme === 'major') { + $cellStyleXf->getFont()->setName($majorFontLatin)->setScheme($scheme); + } elseif ($scheme === 'minor') { + $cellStyleXf->getFont()->setName($minorFontLatin)->setScheme($scheme); + } + } + foreach ($this->cellStyleXfCollection as $cellStyleXf) { + $scheme = $cellStyleXf->getFont()->getScheme(); + if ($scheme === 'major') { + $cellStyleXf->getFont()->setName($majorFontLatin)->setScheme($scheme); + } elseif ($scheme === 'minor') { + $cellStyleXf->getFont()->setName($minorFontLatin)->setScheme($scheme); + } + } + } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Border.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Border.php index c6fb51f..568e1e0 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Border.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Border.php @@ -21,6 +21,7 @@ class Border extends Supervisor const BORDER_SLANTDASHDOT = 'slantDashDot'; const BORDER_THICK = 'thick'; const BORDER_THIN = 'thin'; + const BORDER_OMIT = 'omit'; // should be used only for Conditional /** * Border style. @@ -48,7 +49,7 @@ class Border extends Supervisor * Leave this value at default unless you understand exactly what * its ramifications are */ - public function __construct($isSupervisor = false) + public function __construct($isSupervisor = false, bool $isConditional = false) { // Supervisor? parent::__construct($isSupervisor); @@ -60,6 +61,9 @@ public function __construct($isSupervisor = false) if ($isSupervisor) { $this->color->bindParent($this, 'color'); } + if ($isConditional) { + $this->borderStyle = self::BORDER_OMIT; + } } /** diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Borders.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Borders.php index 56a5270..a1247e8 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Borders.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Borders.php @@ -96,27 +96,27 @@ class Borders extends Supervisor * Leave this value at default unless you understand exactly what * its ramifications are */ - public function __construct($isSupervisor = false) + public function __construct($isSupervisor = false, bool $isConditional = false) { // Supervisor? parent::__construct($isSupervisor); // Initialise values - $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->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->diagonalDirection = self::DIAGONAL_NONE; // Specially for supervisor if ($isSupervisor) { // Initialize pseudo-borders - $this->allBorders = new Border(true); - $this->outline = new Border(true); - $this->inside = new Border(true); - $this->vertical = new Border(true); - $this->horizontal = new Border(true); + $this->allBorders = new Border(true, $isConditional); + $this->outline = new Border(true, $isConditional); + $this->inside = new Border(true, $isConditional); + $this->vertical = new Border(true, $isConditional); + $this->horizontal = new Border(true, $isConditional); // bind parent if we are a supervisor $this->left->bindParent($this, 'left'); diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Color.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Color.php index 3c002b2..282defc 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Color.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Color.php @@ -362,23 +362,8 @@ public static function changeBrightness($hexColourValue, $adjustPercentage) $green = self::getGreen($hexColourValue, false); /** @var int $blue */ $blue = self::getBlue($hexColourValue, false); - if ($adjustPercentage > 0) { - $red += (255 - $red) * $adjustPercentage; - $green += (255 - $green) * $adjustPercentage; - $blue += (255 - $blue) * $adjustPercentage; - } else { - $red += $red * $adjustPercentage; - $green += $green * $adjustPercentage; - $blue += $blue * $adjustPercentage; - } - - $rgb = strtoupper( - str_pad(dechex((int) $red), 2, '0', 0) . - str_pad(dechex((int) $green), 2, '0', 0) . - str_pad(dechex((int) $blue), 2, '0', 0) - ); - return (($rgba) ? 'FF' : '') . $rgb; + return (($rgba) ? 'FF' : '') . RgbTint::rgbAndTintToRgb($red, $green, $blue, $adjustPercentage); } /** diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Conditional.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Conditional.php index 019c064..36069b0 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Conditional.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Conditional.php @@ -115,6 +115,9 @@ class Conditional implements IComparable */ private $style; + /** @var bool */ + private $noFormatSet = false; + /** * Create a new Conditional. */ @@ -124,6 +127,18 @@ public function __construct() $this->style = new Style(false, true); } + public function getNoFormatSet(): bool + { + return $this->noFormatSet; + } + + public function setNoFormatSet(bool $noFormatSet): self + { + $this->noFormatSet = $noFormatSet; + + return $this; + } + /** * Get Condition type. * @@ -233,7 +248,7 @@ public function getConditions() /** * Set Conditions. * - * @param bool|float|int|string|(bool|float|int|string)[] $conditions Condition + * @param (bool|float|int|string)[]|bool|float|int|string $conditions Condition * * @return $this */ diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/CellMatcher.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/CellMatcher.php index 0f6f523..3e5f760 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/CellMatcher.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/CellMatcher.php @@ -193,7 +193,7 @@ protected function conditionCellAdjustment(array $matches) } if (!empty($matches[4])) { - $worksheet = $this->worksheet->getParent()->getSheetByName(trim($matches[4], "'")); + $worksheet = $this->worksheet->getParentOrThrow()->getSheetByName(trim($matches[4], "'")); if ($worksheet === null) { return $this->wrapValue(null); } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalDataBar.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalDataBar.php index f7a2eee..c5c36ae 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalDataBar.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalDataBar.php @@ -36,7 +36,7 @@ public function getShowValue() /** * @param bool $showValue */ - public function setShowValue($showValue) + public function setShowValue($showValue): self { $this->showValue = $showValue; @@ -48,7 +48,7 @@ public function getMinimumConditionalFormatValueObject(): ?ConditionalFormatValu return $this->minimumConditionalFormatValueObject; } - public function setMinimumConditionalFormatValueObject(ConditionalFormatValueObject $minimumConditionalFormatValueObject) + public function setMinimumConditionalFormatValueObject(ConditionalFormatValueObject $minimumConditionalFormatValueObject): self { $this->minimumConditionalFormatValueObject = $minimumConditionalFormatValueObject; @@ -60,7 +60,7 @@ public function getMaximumConditionalFormatValueObject(): ?ConditionalFormatValu return $this->maximumConditionalFormatValueObject; } - public function setMaximumConditionalFormatValueObject(ConditionalFormatValueObject $maximumConditionalFormatValueObject) + public function setMaximumConditionalFormatValueObject(ConditionalFormatValueObject $maximumConditionalFormatValueObject): self { $this->maximumConditionalFormatValueObject = $maximumConditionalFormatValueObject; @@ -84,7 +84,7 @@ public function getConditionalFormattingRuleExt(): ?ConditionalFormattingRuleExt return $this->conditionalFormattingRuleExt; } - public function setConditionalFormattingRuleExt(ConditionalFormattingRuleExtension $conditionalFormattingRuleExt) + public function setConditionalFormattingRuleExt(ConditionalFormattingRuleExtension $conditionalFormattingRuleExt): self { $this->conditionalFormattingRuleExt = $conditionalFormattingRuleExt; diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalDataBarExtension.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalDataBarExtension.php index c709cf3..7807138 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalDataBarExtension.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalDataBarExtension.php @@ -51,7 +51,7 @@ class ConditionalDataBarExtension 'tint' => null, ]; - public function getXmlAttributes() + public function getXmlAttributes(): array { $ret = []; foreach (['minLength', 'maxLength', 'direction', 'axisPosition'] as $attrKey) { @@ -68,7 +68,7 @@ public function getXmlAttributes() return $ret; } - public function getXmlElements() + public function getXmlElements(): array { $ret = []; $elms = ['borderColor', 'negativeFillColor', 'negativeBorderColor']; @@ -200,7 +200,7 @@ public function getMaximumConditionalFormatValueObject() return $this->maximumConditionalFormatValueObject; } - public function setMaximumConditionalFormatValueObject(ConditionalFormatValueObject $maximumConditionalFormatValueObject) + public function setMaximumConditionalFormatValueObject(ConditionalFormatValueObject $maximumConditionalFormatValueObject): self { $this->maximumConditionalFormatValueObject = $maximumConditionalFormatValueObject; @@ -215,7 +215,7 @@ public function getMinimumConditionalFormatValueObject() return $this->minimumConditionalFormatValueObject; } - public function setMinimumConditionalFormatValueObject(ConditionalFormatValueObject $minimumConditionalFormatValueObject) + public function setMinimumConditionalFormatValueObject(ConditionalFormatValueObject $minimumConditionalFormatValueObject): self { $this->minimumConditionalFormatValueObject = $minimumConditionalFormatValueObject; diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormatValueObject.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormatValueObject.php index 107969b..4c13444 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormatValueObject.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormatValueObject.php @@ -4,15 +4,20 @@ class ConditionalFormatValueObject { + /** @var mixed */ private $type; + /** @var mixed */ private $value; + /** @var mixed */ private $cellFormula; /** * ConditionalFormatValueObject constructor. * + * @param mixed $type + * @param mixed $value * @param null|mixed $cellFormula */ public function __construct($type, $value = null, $cellFormula = null) @@ -33,7 +38,7 @@ public function getType() /** * @param mixed $type */ - public function setType($type) + public function setType($type): self { $this->type = $type; @@ -51,7 +56,7 @@ public function getValue() /** * @param mixed $value */ - public function setValue($value) + public function setValue($value): self { $this->value = $value; @@ -69,7 +74,7 @@ public function getCellFormula() /** * @param mixed $cellFormula */ - public function setCellFormula($cellFormula) + public function setCellFormula($cellFormula): self { $this->cellFormula = $cellFormula; diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormattingRuleExtension.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormattingRuleExtension.php index 34c9cbc..0cdbc36 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormattingRuleExtension.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormattingRuleExtension.php @@ -10,6 +10,8 @@ class ConditionalFormattingRuleExtension const CONDITION_EXTENSION_DATABAR = 'dataBar'; /** attributes */ + + /** @var string */ private $id; /** @var string Conditional Formatting Rule */ @@ -26,7 +28,7 @@ class ConditionalFormattingRuleExtension /** * ConditionalFormattingRuleExtension constructor. */ - public function __construct($id = null, string $cfRule = self::CONDITION_EXTENSION_DATABAR) + public function __construct(?string $id = null, string $cfRule = self::CONDITION_EXTENSION_DATABAR) { if (null === $id) { $this->id = '{' . $this->generateUuid() . '}'; @@ -36,7 +38,7 @@ public function __construct($id = null, string $cfRule = self::CONDITION_EXTENSI $this->cfRule = $cfRule; } - private function generateUuid() + private function generateUuid(): string { $chars = str_split('xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'); @@ -51,7 +53,7 @@ private function generateUuid() return implode('', /** @scrutinizer ignore-type */ $chars); } - public static function parseExtLstXml($extLstXml) + public static function parseExtLstXml(?SimpleXMLElement $extLstXml): array { $conditionalFormattingRuleExtensions = []; $conditionalFormattingRuleExtensionXml = null; @@ -96,6 +98,9 @@ private static function parseExtDataBarAttributesFromXml( SimpleXMLElement $dataBarXml ): void { $dataBarAttribute = $dataBarXml->attributes(); + if ($dataBarAttribute === null) { + return; + } if ($dataBarAttribute->minLength) { $extDataBarObj->setMinLength((int) $dataBarAttribute->minLength); } @@ -119,20 +124,32 @@ private static function parseExtDataBarAttributesFromXml( } } + /** @param array|SimpleXMLElement $ns */ private static function parseExtDataBarElementChildrenFromXml(ConditionalDataBarExtension $extDataBarObj, SimpleXMLElement $dataBarXml, $ns): void { if ($dataBarXml->borderColor) { - $extDataBarObj->setBorderColor((string) $dataBarXml->borderColor->attributes()['rgb']); + $attributes = $dataBarXml->borderColor->attributes(); + if ($attributes !== null) { + $extDataBarObj->setBorderColor((string) $attributes['rgb']); + } } if ($dataBarXml->negativeFillColor) { - $extDataBarObj->setNegativeFillColor((string) $dataBarXml->negativeFillColor->attributes()['rgb']); + $attributes = $dataBarXml->negativeFillColor->attributes(); + if ($attributes !== null) { + $extDataBarObj->setNegativeFillColor((string) $attributes['rgb']); + } } if ($dataBarXml->negativeBorderColor) { - $extDataBarObj->setNegativeBorderColor((string) $dataBarXml->negativeBorderColor->attributes()['rgb']); + $attributes = $dataBarXml->negativeBorderColor->attributes(); + if ($attributes !== null) { + $extDataBarObj->setNegativeBorderColor((string) $attributes['rgb']); + } } if ($dataBarXml->axisColor) { $axisColorAttr = $dataBarXml->axisColor->attributes(); - $extDataBarObj->setAxisColor((string) $axisColorAttr['rgb'], (string) $axisColorAttr['theme'], (string) $axisColorAttr['tint']); + if ($axisColorAttr !== null) { + $extDataBarObj->setAxisColor((string) $axisColorAttr['rgb'], (string) $axisColorAttr['theme'], (string) $axisColorAttr['tint']); + } } $cfvoIndex = 0; foreach ($dataBarXml->cfvo as $cfvo) { diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Font.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Font.php index 3d7bc1b..a8eeaa9 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Font.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Font.php @@ -107,6 +107,9 @@ class Font extends Supervisor */ public $colorIndex; + /** @var string */ + protected $scheme = ''; + /** * Create a new Font. * @@ -231,6 +234,12 @@ public function applyFromArray(array $styleArray) if (isset($styleArray['size'])) { $this->setSize($styleArray['size']); } + if (isset($styleArray['chartColor'])) { + $this->chartColor = $styleArray['chartColor']; + } + if (isset($styleArray['scheme'])) { + $this->setScheme($styleArray['scheme']); + } } return $this; @@ -278,13 +287,11 @@ public function getComplexScript(): string } /** - * Set Name. + * Set Name and turn off Scheme. * * @param string $fontname - * - * @return $this */ - public function setName($fontname) + public function setName($fontname): self { if ($fontname == '') { $fontname = 'Calibri'; @@ -296,7 +303,7 @@ public function setName($fontname) $this->name = $fontname; } - return $this; + return $this->setScheme(''); } public function setLatin(string $fontname): self @@ -634,6 +641,13 @@ public function setChartColor(array $colorArray): self return $this; } + public function setChartColorFromObject(?ChartColor $chartColor): self + { + $this->chartColor = $chartColor; + + return $this; + } + /** * Get Underline. * @@ -774,6 +788,7 @@ public function getHashCode() $this->underline . ($this->strikethrough ? 't' : 'f') . $this->color->getHashCode() . + $this->scheme . implode( '*', [ @@ -802,6 +817,7 @@ protected function exportArray1(): array $this->exportArray2($exportedArray, 'italic', $this->getItalic()); $this->exportArray2($exportedArray, 'latin', $this->getLatin()); $this->exportArray2($exportedArray, 'name', $this->getName()); + $this->exportArray2($exportedArray, 'scheme', $this->getScheme()); $this->exportArray2($exportedArray, 'size', $this->getSize()); $this->exportArray2($exportedArray, 'strikethrough', $this->getStrikethrough()); $this->exportArray2($exportedArray, 'strikeType', $this->getStrikeType()); @@ -812,4 +828,27 @@ protected function exportArray1(): array return $exportedArray; } + + public function getScheme(): string + { + if ($this->isSupervisor) { + return $this->getSharedComponent()->getScheme(); + } + + return $this->scheme; + } + + public function setScheme(string $scheme): self + { + if ($scheme === '' || $scheme === 'major' || $scheme === 'minor') { + if ($this->isSupervisor) { + $styleArray = $this->getStyleArray(['scheme' => $scheme]); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->scheme = $scheme; + } + } + + return $this; + } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat.php index c2b11a6..b605cff 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat.php @@ -79,10 +79,14 @@ class NumberFormat extends Supervisor self::FORMAT_DATE_TIME8, ]; - const FORMAT_CURRENCY_USD_SIMPLE = '"$"#,##0.00_-'; - const FORMAT_CURRENCY_USD = '$#,##0_-'; - const FORMAT_CURRENCY_EUR_SIMPLE = '#,##0.00_-"€"'; - const FORMAT_CURRENCY_EUR = '#,##0_-"€"'; + /** @deprecated 1.28 use FORMAT_CURRENCY_USD_INTEGER instead */ + const FORMAT_CURRENCY_USD_SIMPLE = '"$"#,##0_-'; + const FORMAT_CURRENCY_USD_INTEGER = '$#,##0_-'; + const FORMAT_CURRENCY_USD = '$#,##0.00_-'; + /** @deprecated 1.28 use FORMAT_CURRENCY_EUR_INTEGER instead */ + const FORMAT_CURRENCY_EUR_SIMPLE = '#,##0_-"€"'; + const FORMAT_CURRENCY_EUR_INTEGER = '#,##0_-[$€]'; + const FORMAT_CURRENCY_EUR = '#,##0.00_-[$€]'; const FORMAT_ACCOUNTING_USD = '_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)'; const FORMAT_ACCOUNTING_EUR = '_("€"* #,##0.00_);_("€"* \(#,##0.00\);_("€"* "-"??_);_(@_)'; @@ -213,7 +217,7 @@ public function getFormatCode() * * @return $this */ - public function setFormatCode($formatCode) + public function setFormatCode(string $formatCode) { if ($formatCode == '') { $formatCode = self::FORMAT_GENERAL; @@ -247,11 +251,11 @@ public function getBuiltInFormatCode() /** * Set Built-In Format Code. * - * @param int $formatCodeIndex + * @param int $formatCodeIndex Id of the built-in format code to use * * @return $this */ - public function setBuiltInFormatCode($formatCodeIndex) + public function setBuiltInFormatCode(int $formatCodeIndex) { if ($this->isSupervisor) { $styleArray = $this->getStyleArray(['formatCode' => self::builtInFormatCode($formatCodeIndex)]); @@ -432,7 +436,8 @@ public function getHashCode() * Convert a value in a pre-defined format to a PHP string. * * @param mixed $value Value to format - * @param string $format Format code, see = self::FORMAT_* + * @param string $format Format code: see = self::FORMAT_* for predefined values; + * or can be any valid MS Excel custom format string * @param array $callBack Callback function for additional formatting of string * * @return string Formatted string diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Formatter.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Formatter.php index be195a8..41a1715 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Formatter.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Formatter.php @@ -2,38 +2,63 @@ namespace PhpOffice\PhpSpreadsheet\Style\NumberFormat; +use PhpOffice\PhpSpreadsheet\Calculation\Calculation; +use PhpOffice\PhpSpreadsheet\Reader\Xls\Color\BIFF8; +use PhpOffice\PhpSpreadsheet\RichText\RichText; use PhpOffice\PhpSpreadsheet\Style\Color; use PhpOffice\PhpSpreadsheet\Style\NumberFormat; class Formatter { - private static function splitFormatCompare($value, $cond, $val, $dfcond, $dfval) - { - if (!$cond) { - $cond = $dfcond; - $val = $dfval; + /** + * Matches any @ symbol that isn't enclosed in quotes. + */ + private const SYMBOL_AT = '/@(?=(?:[^"]*"[^"]*")*[^"]*\Z)/miu'; + + /** + * Matches any ; symbol that isn't enclosed in quotes, for a "section" split. + */ + private const SECTION_SPLIT = '/;(?=(?:[^"]*"[^"]*")*[^"]*\Z)/miu'; + + /** + * @param mixed $value + * @param mixed $comparisonValue + * @param mixed $defaultComparisonValue + */ + private static function splitFormatComparison( + $value, + ?string $condition, + $comparisonValue, + string $defaultCondition, + $defaultComparisonValue + ): bool { + if (!$condition) { + $condition = $defaultCondition; + $comparisonValue = $defaultComparisonValue; } - switch ($cond) { + + switch ($condition) { case '>': - return $value > $val; + return $value > $comparisonValue; case '<': - return $value < $val; + return $value < $comparisonValue; case '<=': - return $value <= $val; + return $value <= $comparisonValue; case '<>': - return $value != $val; + return $value != $comparisonValue; case '=': - return $value == $val; + return $value == $comparisonValue; } - return $value >= $val; + return $value >= $comparisonValue; } - private static function splitFormat($sections, $value) + /** @param mixed $value */ + private static function splitFormatForSectionSelection(array $sections, $value): array { // Extract the relevant section depending on whether number is positive, negative, or zero? // Text not supported yet. @@ -42,30 +67,35 @@ private static function splitFormat($sections, $value) // 2 sections: [POSITIVE/ZERO/TEXT] [NEGATIVE] // 3 sections: [POSITIVE/TEXT] [NEGATIVE] [ZERO] // 4 sections: [POSITIVE] [NEGATIVE] [ZERO] [TEXT] - $cnt = count($sections); - $color_regex = '/\\[(' . implode('|', Color::NAMED_COLORS) . ')\\]/mui'; + $sectionCount = count($sections); + // Colour could be a named colour, or a numeric index entry in the colour-palette + $color_regex = '/\\[(' . implode('|', Color::NAMED_COLORS) . '|color\\s*(\\d+))\\]/mui'; $cond_regex = '/\\[(>|>=|<|<=|=|<>)([+-]?\\d+([.]\\d+)?)\\]/'; $colors = ['', '', '', '', '']; - $condops = ['', '', '', '', '']; - $condvals = [0, 0, 0, 0, 0]; - for ($idx = 0; $idx < $cnt; ++$idx) { + $conditionOperations = ['', '', '', '', '']; + $conditionComparisonValues = [0, 0, 0, 0, 0]; + for ($idx = 0; $idx < $sectionCount; ++$idx) { if (preg_match($color_regex, $sections[$idx], $matches)) { - $colors[$idx] = $matches[0]; + if (isset($matches[2])) { + $colors[$idx] = '#' . BIFF8::lookup((int) $matches[2] + 7)['rgb']; + } else { + $colors[$idx] = $matches[0]; + } $sections[$idx] = (string) preg_replace($color_regex, '', $sections[$idx]); } if (preg_match($cond_regex, $sections[$idx], $matches)) { - $condops[$idx] = $matches[1]; - $condvals[$idx] = $matches[2]; + $conditionOperations[$idx] = $matches[1]; + $conditionComparisonValues[$idx] = $matches[2]; $sections[$idx] = (string) preg_replace($cond_regex, '', $sections[$idx]); } } $color = $colors[0]; $format = $sections[0]; $absval = $value; - switch ($cnt) { + switch ($sectionCount) { case 2: $absval = abs($value); - if (!self::splitFormatCompare($value, $condops[0], $condvals[0], '>=', 0)) { + if (!self::splitFormatComparison($value, $conditionOperations[0], $conditionComparisonValues[0], '>=', 0)) { $color = $colors[1]; $format = $sections[1]; } @@ -74,8 +104,8 @@ private static function splitFormat($sections, $value) case 3: case 4: $absval = abs($value); - if (!self::splitFormatCompare($value, $condops[0], $condvals[0], '>', 0)) { - if (self::splitFormatCompare($value, $condops[1], $condvals[1], '<', 0)) { + if (!self::splitFormatComparison($value, $conditionOperations[0], $conditionComparisonValues[0], '>', 0)) { + if (self::splitFormatComparison($value, $conditionOperations[1], $conditionComparisonValues[1], '<', 0)) { $color = $colors[1]; $format = $sections[1]; } else { @@ -93,23 +123,33 @@ private static function splitFormat($sections, $value) /** * Convert a value in a pre-defined format to a PHP string. * - * @param mixed $value Value to format - * @param string $format Format code, see = NumberFormat::FORMAT_* + * @param null|bool|float|int|RichText|string $value Value to format + * @param string $format Format code: see = self::FORMAT_* for predefined values; + * or can be any valid MS Excel custom format string * @param array $callBack Callback function for additional formatting of string * * @return string Formatted string */ public static function toFormattedString($value, $format, $callBack = null) { - // For now we do not treat strings although section 4 of a format code affects strings + if (is_bool($value)) { + return $value ? Calculation::getTRUE() : Calculation::getFALSE(); + } + // For now we do not treat strings in sections, although section 4 of a format code affects strings + // Process a single block format code containing @ for text substitution + if (preg_match(self::SECTION_SPLIT, $format) === 0 && preg_match(self::SYMBOL_AT, $format) === 1) { + return str_replace('"', '', preg_replace(self::SYMBOL_AT, (string) $value, $format) ?? ''); + } + + // If we have a text value, return it "as is" if (!is_numeric($value)) { - return $value; + return (string) $value; } // For 'General' format code, we just pass the value although this is not entirely the way Excel does it, // it seems to round numbers to a total of 10 digits. if (($format === NumberFormat::FORMAT_GENERAL) || ($format === NumberFormat::FORMAT_TEXT)) { - return $value; + return (string) $value; } // Ignore square-$-brackets prefix in format string, like "[$-411]ge.m.d", "[$-010419]0%", etc @@ -127,26 +167,29 @@ function ($matches) { $format = (string) preg_replace('/(\\\(((.)(?!((AM\/PM)|(A\/P))))|([^ ])))(?=(?:[^"]|"[^"]*")*$)/ui', '"${2}"', $format); // Get the sections, there can be up to four sections, separated with a semi-colon (but only if not a quoted literal) - $sections = preg_split('/(;)(?=(?:[^"]|"[^"]*")*$)/u', $format); + $sections = preg_split(self::SECTION_SPLIT, $format) ?: []; - [$colors, $format, $value] = self::splitFormat($sections, $value); + [$colors, $format, $value] = self::splitFormatForSectionSelection($sections, $value); // In Excel formats, "_" is used to add spacing, // The following character indicates the size of the spacing, which we can't do in HTML, so we just use a standard space $format = (string) preg_replace('/_.?/ui', ' ', $format); // Let's begin inspecting the format and converting the value to a formatted string - - // Check for date/time characters (not inside quotes) - if (preg_match('/(\[\$[A-Z]*-[0-9A-F]*\])*[hmsdy](?=(?:[^"]|"[^"]*")*$)/miu', $format, $matches)) { + if ( + // Check for date/time characters (not inside quotes) + (preg_match('/(\[\$[A-Z]*-[0-9A-F]*\])*[hmsdy](?=(?:[^"]|"[^"]*")*$)/miu', $format)) + // A date/time with a decimal time shouldn't have a digit placeholder before the decimal point + && (preg_match('/[0\?#]\.(?![^\[]*\])/miu', $format) === 0) + ) { // datetime format $value = DateFormatter::format($value, $format); } else { if (substr($format, 0, 1) === '"' && substr($format, -1, 1) === '"' && substr_count($format, '"') === 2) { $value = substr($format, 1, -1); } elseif (preg_match('/[0#, ]%/', $format)) { - // % number format - $value = PercentageFormatter::format($value, $format); + // % number format - avoid weird '-0' problem + $value = PercentageFormatter::format(0 + (float) $value, $format); } else { $value = NumberFormatter::format($value, $format); } @@ -158,8 +201,6 @@ function ($matches) { $value = $writerInstance->$function($value, $colors); } - $value = str_replace(chr(0x00), '.', $value); - - return $value; + return str_replace(chr(0x00), '.', $value); } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/FractionFormatter.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/FractionFormatter.php index d1fc89f..fdcf983 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/FractionFormatter.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/FractionFormatter.php @@ -26,23 +26,28 @@ public static function format($value, string $format): string $decimalLength = strlen($decimalPart); $decimalDivisor = 10 ** $decimalLength; - /** @var float */ - $GCD = MathTrig\Gcd::evaluate($decimalPart, $decimalDivisor); - /** @var float */ - $decimalPartx = $decimalPart; + preg_match('/(#?.*\?)\/(\?+|\d+)/', $format, $matches); + $formatIntegerPart = $matches[1]; - $adjustedDecimalPart = $decimalPartx / $GCD; - $adjustedDecimalDivisor = $decimalDivisor / $GCD; + if (is_numeric($matches[2])) { + $fractionDivisor = 100 / (int) $matches[2]; + } else { + /** @var float */ + $fractionDivisor = MathTrig\Gcd::evaluate((int) $decimalPart, $decimalDivisor); + } + + $adjustedDecimalPart = (int) round((int) $decimalPart / $fractionDivisor, 0); + $adjustedDecimalDivisor = $decimalDivisor / $fractionDivisor; - if ((strpos($format, '0') !== false)) { + if ((strpos($formatIntegerPart, '0') !== false)) { return "{$sign}{$integerPart} {$adjustedDecimalPart}/{$adjustedDecimalDivisor}"; - } elseif ((strpos($format, '#') !== false)) { + } elseif ((strpos($formatIntegerPart, '#') !== false)) { if ($integerPart == 0) { return "{$sign}{$adjustedDecimalPart}/{$adjustedDecimalDivisor}"; } return "{$sign}{$integerPart} {$adjustedDecimalPart}/{$adjustedDecimalDivisor}"; - } elseif ((substr($format, 0, 3) == '? ?')) { + } elseif ((substr($formatIntegerPart, 0, 3) == '? ?')) { if ($integerPart == 0) { $integerPart = ''; } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/NumberFormatter.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/NumberFormatter.php index 989f33a..c035345 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/NumberFormatter.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/NumberFormatter.php @@ -164,7 +164,10 @@ private static function formatStraightNumericValue($value, string $format, array if (preg_match('/[0#]E[+-]0/i', $format)) { // Scientific format - return sprintf('%5.2E', $valueFloat); + $decimals = strlen($right); + $size = $decimals + 3; + + return sprintf("%{$size}.{$decimals}E", $valueFloat); } elseif (preg_match('/0([^\d\.]+)0/', $format) || substr_count($format, '.') > 1) { if ($valueFloat == floor($valueFloat) && substr_count($format, '.') === 1) { $value *= 10 ** strlen(explode('.', $format)[1]); @@ -183,6 +186,7 @@ private static function formatStraightNumericValue($value, string $format, array } $sprintf_pattern = "%0$minWidth." . strlen($right) . 'f'; + /** @var float */ $valueFloat = $value; $value = sprintf($sprintf_pattern, round($valueFloat, strlen($right))); @@ -198,51 +202,42 @@ public static function format($value, string $format): string // The "_" in this string has already been stripped out, // so this test is never true. Furthermore, testing // on Excel shows this format uses Euro symbol, not "EUR". - //if ($format === NumberFormat::FORMAT_CURRENCY_EUR_SIMPLE) { - // return 'EUR ' . sprintf('%1.2f', $value); - //} - - // Some non-number strings are quoted, so we'll get rid of the quotes, likewise any positional * symbols - $format = self::makeString(str_replace(['"', '*'], '', $format)); + // if ($format === NumberFormat::FORMAT_CURRENCY_EUR_SIMPLE) { + // return 'EUR ' . sprintf('%1.2f', $value); + // } - // Find out if we need thousands separator - // This is indicated by a comma enclosed by a digit placeholder: - // #,# or 0,0 - $useThousands = (bool) preg_match('/(#,#|0,0)/', $format); - if ($useThousands) { - $format = self::pregReplace('/0,0/', '00', $format); - $format = self::pregReplace('/#,#/', '##', $format); - } + $baseFormat = $format; - // Scale thousands, millions,... - // This is indicated by a number of commas after a digit placeholder: - // #, or 0.0,, - $scale = 1; // same as no scale - $matches = []; - if (preg_match('/(#|0)(,+)/', $format, $matches)) { - $scale = 1000 ** strlen($matches[2]); + $useThousands = self::areThousandsRequired($format); + $scale = self::scaleThousandsMillions($format); - // strip the commas - $format = self::pregReplace('/0,+/', '0', $format); - $format = self::pregReplace('/#,+/', '#', $format); - } - if (preg_match('/#?.*\?\/\?/', $format, $m)) { + if (preg_match('/[#\?0]?.*[#\?0]\/(\?+|\d+|#)/', $format)) { + // It's a dirty hack; but replace # and 0 digit placeholders with ? + $format = (string) preg_replace('/[#0]+\//', '?/', $format); + $format = (string) preg_replace('/\/[#0]+/', '/?', $format); $value = FractionFormatter::format($value, $format); } else { // Handle the number itself - // scale number $value = $value / $scale; - // Strip # - $format = self::pregReplace('/\\#/', '0', $format); - // Remove locale code [$-###] + $paddingPlaceholder = (strpos($format, '?') !== false); + + // Replace # or ? with 0 + $format = self::pregReplace('/[\\#\?](?=(?:[^"]*"[^"]*")*[^"]*\Z)/', '0', $format); + // Remove locale code [$-###] for an LCID $format = self::pregReplace('/\[\$\-.*\]/', '', $format); $n = '/\\[[^\\]]+\\]/'; $m = self::pregReplace($n, '', $format); + + // Some non-number strings are quoted, so we'll get rid of the quotes, likewise any positional * symbols + $format = self::makeString(str_replace(['"', '*'], '', $format)); if (preg_match(self::NUMBER_REGEX, $m, $matches)) { // There are placeholders for digits, so inject digits from the value into the mask $value = self::formatStraightNumericValue($value, $format, $matches, $useThousands); + if ($paddingPlaceholder === true) { + $value = self::padValue($value, $baseFormat); + } } elseif ($format !== NumberFormat::FORMAT_GENERAL) { // Yes, I know that this is basically just a hack; // if there's no placeholders for digits, just return the format mask "as is" @@ -260,6 +255,13 @@ public static function format($value, string $format): string $value = self::pregReplace('/\[\$([^\]]*)\]/u', $currencyCode, (string) $value); } + if ( + (strpos((string) $value, '0.') !== false) && + ((strpos($baseFormat, '#.') !== false) || (strpos($baseFormat, '?.') !== false)) + ) { + $value = preg_replace('/(\b)0\.|([^\d])0\./', '${2}.', (string) $value); + } + return (string) $value; } @@ -275,4 +277,50 @@ private static function pregReplace(string $pattern, string $replacement, string { return self::makeString(preg_replace($pattern, $replacement, $subject) ?? ''); } + + public static function padValue(string $value, string $baseFormat): string + { + /** @phpstan-ignore-next-line */ + [$preDecimal, $postDecimal] = preg_split('/\.(?=(?:[^"]*"[^"]*")*[^"]*\Z)/miu', $baseFormat . '.?'); + + $length = strlen($value); + if (strpos($postDecimal, '?') !== false) { + $value = str_pad(rtrim($value, '0. '), $length, ' ', STR_PAD_RIGHT); + } + if (strpos($preDecimal, '?') !== false) { + $value = str_pad(ltrim($value, '0, '), $length, ' ', STR_PAD_LEFT); + } + + return $value; + } + + /** + * Find out if we need thousands separator + * This is indicated by a comma enclosed by a digit placeholders: #, 0 or ? + */ + public static function areThousandsRequired(string &$format): bool + { + $useThousands = (bool) preg_match('/([#\?0]),([#\?0])/', $format); + if ($useThousands) { + $format = self::pregReplace('/([#\?0]),([#\?0])/', '${1}${2}', $format); + } + + return $useThousands; + } + + /** + * Scale thousands, millions,... + * This is indicated by a number of commas after a digit placeholder: #, or 0.0,, or ?,. + */ + public static function scaleThousandsMillions(string &$format): int + { + $scale = 1; // same as no scale + if (preg_match('/(#|0|\?)(,+)/', $format, $matches)) { + $scale = 1000 ** strlen($matches[2]); + // strip the commas + $format = self::pregReplace('/([#\?0]),+/', '${1}', $format); + } + + return $scale; + } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/PercentageFormatter.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/PercentageFormatter.php index 74f3877..55b5971 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/PercentageFormatter.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/PercentageFormatter.php @@ -6,6 +6,7 @@ class PercentageFormatter extends BaseFormatter { + /** @param float|int $value */ public static function format($value, string $format): string { if ($format === NumberFormat::FORMAT_PERCENTAGE) { diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Accounting.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Accounting.php new file mode 100644 index 0000000..c300286 --- /dev/null +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Accounting.php @@ -0,0 +1,102 @@ +setCurrencyCode($currencyCode); + $this->setThousandsSeparator($thousandsSeparator); + $this->setDecimals($decimals); + $this->setCurrencySymbolPosition($currencySymbolPosition); + $this->setCurrencySymbolSpacing($currencySymbolSpacing); + $this->setLocale($locale); + } + + /** + * @throws Exception if the Intl extension and ICU version don't support Accounting formats + */ + protected function getLocaleFormat(): string + { + if (version_compare(PHP_VERSION, '7.4.1', '<')) { + throw new Exception('The Intl extension does not support Accounting Formats below PHP 7.4.1'); + } + + if ($this->icuVersion() < 53.0) { + throw new Exception('The Intl extension does not support Accounting Formats without ICU 53'); + } + + // Scrutinizer does not recognize CURRENCY_ACCOUNTING + $formatter = new Locale($this->fullLocale, NumberFormatter::CURRENCY_ACCOUNTING); + $mask = $formatter->format(); + if ($this->decimals === 0) { + $mask = (string) preg_replace('/\.0+/miu', '', $mask); + } + + return str_replace('¤', $this->formatCurrencyCode(), $mask); + } + + private function icuVersion(): float + { + [$major, $minor] = explode('.', INTL_ICU_VERSION); + + return (float) "{$major}.{$minor}"; + } + + private function formatCurrencyCode(): string + { + if ($this->locale === null) { + return $this->currencyCode . '*'; + } + + return "[\${$this->currencyCode}-{$this->locale}]"; + } + + public function format(): string + { + if ($this->localeFormat !== null) { + return $this->localeFormat; + } + + return sprintf( + '_-%s%s%s0%s%s%s_-', + $this->currencySymbolPosition === self::LEADING_SYMBOL ? $this->formatCurrencyCode() : null, + ( + $this->currencySymbolPosition === self::LEADING_SYMBOL && + $this->currencySymbolSpacing === self::SYMBOL_WITH_SPACING + ) ? "\u{a0}" : '', + $this->thousandsSeparator ? '#,##' : null, + $this->decimals > 0 ? '.' . str_repeat('0', $this->decimals) : null, + ( + $this->currencySymbolPosition === self::TRAILING_SYMBOL && + $this->currencySymbolSpacing === self::SYMBOL_WITH_SPACING + ) ? "\u{a0}" : '', + $this->currencySymbolPosition === self::TRAILING_SYMBOL ? $this->formatCurrencyCode() : null + ); + } +} diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Currency.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Currency.php new file mode 100644 index 0000000..2fcd108 --- /dev/null +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Currency.php @@ -0,0 +1,112 @@ +setCurrencyCode($currencyCode); + $this->setThousandsSeparator($thousandsSeparator); + $this->setDecimals($decimals); + $this->setCurrencySymbolPosition($currencySymbolPosition); + $this->setCurrencySymbolSpacing($currencySymbolSpacing); + $this->setLocale($locale); + } + + public function setCurrencyCode(string $currencyCode): void + { + $this->currencyCode = $currencyCode; + } + + public function setCurrencySymbolPosition(bool $currencySymbolPosition = self::LEADING_SYMBOL): void + { + $this->currencySymbolPosition = $currencySymbolPosition; + } + + public function setCurrencySymbolSpacing(bool $currencySymbolSpacing = self::SYMBOL_WITHOUT_SPACING): void + { + $this->currencySymbolSpacing = $currencySymbolSpacing; + } + + protected function getLocaleFormat(): string + { + $formatter = new Locale($this->fullLocale, NumberFormatter::CURRENCY); + $mask = $formatter->format(); + if ($this->decimals === 0) { + $mask = (string) preg_replace('/\.0+/miu', '', $mask); + } + + return str_replace('¤', $this->formatCurrencyCode(), $mask); + } + + private function formatCurrencyCode(): string + { + if ($this->locale === null) { + return $this->currencyCode; + } + + return "[\${$this->currencyCode}-{$this->locale}]"; + } + + public function format(): string + { + if ($this->localeFormat !== null) { + return $this->localeFormat; + } + + return sprintf( + '%s%s%s0%s%s%s', + $this->currencySymbolPosition === self::LEADING_SYMBOL ? $this->formatCurrencyCode() : null, + ( + $this->currencySymbolPosition === self::LEADING_SYMBOL && + $this->currencySymbolSpacing === self::SYMBOL_WITH_SPACING + ) ? "\u{a0}" : '', + $this->thousandsSeparator ? '#,##' : null, + $this->decimals > 0 ? '.' . str_repeat('0', $this->decimals) : null, + ( + $this->currencySymbolPosition === self::TRAILING_SYMBOL && + $this->currencySymbolSpacing === self::SYMBOL_WITH_SPACING + ) ? "\u{a0}" : '', + $this->currencySymbolPosition === self::TRAILING_SYMBOL ? $this->formatCurrencyCode() : null + ); + } +} diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Date.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Date.php new file mode 100644 index 0000000..61ac117 --- /dev/null +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Date.php @@ -0,0 +1,125 @@ +separators = $this->padSeparatorArray( + is_array($separators) ? $separators : [$separators], + count($formatBlocks) - 1 + ); + $this->formatBlocks = array_map([$this, 'mapFormatBlocks'], $formatBlocks); + } + + private function mapFormatBlocks(string $value): string + { + // Any date masking codes are returned as lower case values + if (in_array(mb_strtolower($value), self::DATE_BLOCKS, true)) { + return mb_strtolower($value); + } + + // Wrap any string literals in quotes, so that they're clearly defined as string literals + return $this->wrapLiteral($value); + } + + public function format(): string + { + return implode('', array_map([$this, 'intersperse'], $this->formatBlocks, $this->separators)); + } +} diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/DateTime.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/DateTime.php new file mode 100644 index 0000000..292c1ef --- /dev/null +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/DateTime.php @@ -0,0 +1,50 @@ + + */ + protected array $formatBlocks; + + /** + * @param null|string|string[] $separators + * If you want to use only a single format block, then pass a null as the separator argument + * @param DateTimeWizard|string ...$formatBlocks + */ + public function __construct($separators, ...$formatBlocks) + { + $this->separators = $this->padSeparatorArray( + is_array($separators) ? $separators : [$separators], + count($formatBlocks) - 1 + ); + $this->formatBlocks = array_map([$this, 'mapFormatBlocks'], $formatBlocks); + } + + /** + * @param DateTimeWizard|string $value + */ + private function mapFormatBlocks($value): string + { + // Any date masking codes are returned as lower case values + if (is_object($value)) { + // We can't explicitly test for Stringable until PHP >= 8.0 + return $value; + } + + // Wrap any string literals in quotes, so that they're clearly defined as string literals + return $this->wrapLiteral($value); + } + + public function format(): string + { + return implode('', array_map([$this, 'intersperse'], $this->formatBlocks, $this->separators)); + } +} diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/DateTimeWizard.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/DateTimeWizard.php new file mode 100644 index 0000000..b14a619 --- /dev/null +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/DateTimeWizard.php @@ -0,0 +1,44 @@ += "; + + protected function padSeparatorArray(array $separators, int $count): array + { + $lastSeparator = array_pop($separators); + + return $separators + array_fill(0, $count, $lastSeparator); + } + + protected function escapeSingleCharacter(string $value): string + { + if (strpos(self::NO_ESCAPING_NEEDED, $value) !== false) { + return $value; + } + + return "\\{$value}"; + } + + protected function wrapLiteral(string $value): string + { + if (mb_strlen($value, 'UTF-8') === 1) { + return $this->escapeSingleCharacter($value); + } + + // Wrap any other string literals in quotes, so that they're clearly defined as string literals + return '"' . str_replace('"', '""', $value) . '"'; + } + + protected function intersperse(string $formatBlock, ?string $separator): string + { + return "{$formatBlock}{$separator}"; + } + + public function __toString(): string + { + return $this->format(); + } +} diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Duration.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Duration.php new file mode 100644 index 0000000..b81f77a --- /dev/null +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Duration.php @@ -0,0 +1,153 @@ + self::DAYS_DURATION, + self::HOURS_DURATION => self::HOURS_SHORT, + self::MINUTES_DURATION => self::MINUTES_LONG, + self::SECONDS_DURATION => self::SECONDS_LONG, + ]; + + protected const DURATION_DEFAULTS = [ + self::HOURS_LONG => self::HOURS_DURATION, + self::HOURS_SHORT => self::HOURS_DURATION, + self::MINUTES_LONG => self::MINUTES_DURATION, + self::MINUTES_SHORT => self::MINUTES_DURATION, + self::SECONDS_LONG => self::SECONDS_DURATION, + self::SECONDS_SHORT => self::SECONDS_DURATION, + ]; + + public const SEPARATOR_COLON = ':'; + public const SEPARATOR_SPACE_NONBREAKING = "\u{a0}"; + public const SEPARATOR_SPACE = ' '; + + public const DURATION_DEFAULT = [ + self::HOURS_DURATION, + self::MINUTES_LONG, + self::SECONDS_LONG, + ]; + + /** + * @var string[] + */ + protected array $separators; + + /** + * @var string[] + */ + protected array $formatBlocks; + + protected bool $durationIsSet = false; + + /** + * @param null|string|string[] $separators + * If you want to use the same separator for all format blocks, then it can be passed as a string literal; + * if you wish to use different separators, then they should be passed as an array. + * If you want to use only a single format block, then pass a null as the separator argument + */ + public function __construct($separators = self::SEPARATOR_COLON, string ...$formatBlocks) + { + $separators ??= self::SEPARATOR_COLON; + $formatBlocks = (count($formatBlocks) === 0) ? self::DURATION_DEFAULT : $formatBlocks; + + $this->separators = $this->padSeparatorArray( + is_array($separators) ? $separators : [$separators], + count($formatBlocks) - 1 + ); + $this->formatBlocks = array_map([$this, 'mapFormatBlocks'], $formatBlocks); + + if ($this->durationIsSet === false) { + // We need at least one duration mask, so if none has been set we change the first mask element + // to a duration. + $this->formatBlocks[0] = self::DURATION_DEFAULTS[mb_strtolower($this->formatBlocks[0])]; + } + } + + private function mapFormatBlocks(string $value): string + { + // Any duration masking codes are returned as lower case values + if (in_array(mb_strtolower($value), self::DURATION_BLOCKS, true)) { + if (array_key_exists(mb_strtolower($value), self::DURATION_MASKS)) { + if ($this->durationIsSet) { + // We should only have a single duration mask, the first defined in the mask set, + // so convert any additional duration masks to standard time masks. + $value = self::DURATION_MASKS[mb_strtolower($value)]; + } + $this->durationIsSet = true; + } + + return mb_strtolower($value); + } + + // Wrap any string literals in quotes, so that they're clearly defined as string literals + return $this->wrapLiteral($value); + } + + public function format(): string + { + return implode('', array_map([$this, 'intersperse'], $this->formatBlocks, $this->separators)); + } +} diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Locale.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Locale.php new file mode 100644 index 0000000..9f03362 --- /dev/null +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Locale.php @@ -0,0 +1,37 @@ +[a-z]{2})([-_](?P