From ba8039b9261617df0654bdd8287e8d6dad9d477a Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Fri, 7 Nov 2025 18:07:50 +0000
Subject: [PATCH] Version v0.16.0-dev
---
VERSION | 2 +-
asset/css/action-link-and-button-link.less | 26 +
asset/css/balls.less | 40 +-
asset/css/compat.less | 63 +-
asset/css/controls.less | 13 +-
asset/css/empty-state.less | 5 +-
asset/css/icinga-icons.less | 45 +-
asset/css/item-layout.less | 177 +
asset/css/list/item-list.less | 83 +-
asset/css/list/item-table.less | 162 +-
asset/css/list/list-item.less | 68 +-
asset/css/mixin/mixins.less | 5 +
asset/css/schedule-element.less | 58 +-
asset/css/search-bar.less | 40 +-
asset/css/search-base.less | 82 +-
asset/css/search-editor.less | 130 +-
asset/css/suggestion-element.less | 29 +
asset/css/variables.less | 33 +-
asset/js/iterator.js | 96 +
asset/js/widget/BaseInput.js | 15 +-
asset/js/widget/FilterInput.js | 18 +-
asset/js/widget/SearchEditor.js | 2 +-
asset/js/widget/TermInput.js | 17 +-
.../font/icinga-icons/fonts/Icinga-Icons.svg | 3 +
.../font/icinga-icons/fonts/Icinga-Icons.ttf | Bin 4316 -> 4824 bytes
.../font/icinga-icons/fonts/Icinga-Icons.woff | Bin 4392 -> 4900 bytes
asset/static/font/icinga-icons/selection.json | 2 +-
.../font/icinga-icons/src/add-inside.svg | 1 +
.../font/icinga-icons/src/insert-group.svg | 1 +
asset/static/font/icinga-icons/src/wrap.svg | 1 +
asset/static/font/icinga-icons/style.css | 9 +
composer.lock | 630 +-
vendor/autoload.php | 7 +-
vendor/brick/math/composer.json | 14 +-
vendor/brick/math/src/BigDecimal.php | 347 +-
vendor/brick/math/src/BigInteger.php | 403 +-
vendor/brick/math/src/BigNumber.php | 428 +-
vendor/brick/math/src/BigRational.php | 206 +-
.../src/Exception/DivisionByZeroException.php | 14 +-
.../Exception/IntegerOverflowException.php | 8 +-
.../math/src/Exception/MathException.php | 2 -
.../src/Exception/NegativeNumberException.php | 2 +-
.../src/Exception/NumberFormatException.php | 19 +-
.../Exception/RoundingNecessaryException.php | 6 +-
vendor/brick/math/src/Internal/Calculator.php | 235 +-
.../Internal/Calculator/BcMathCalculator.php | 69 +-
.../src/Internal/Calculator/GmpCalculator.php | 74 +-
.../Internal/Calculator/NativeCalculator.php | 141 +-
.../math/src/Internal/CalculatorRegistry.php | 73 +
vendor/brick/math/src/RoundingMode.php | 31 +-
vendor/composer/InstalledVersions.php | 45 +-
vendor/composer/autoload_classmap.php | 7 +-
vendor/composer/autoload_files.php | 3 +-
vendor/composer/autoload_psr4.php | 9 +-
vendor/composer/autoload_real.php | 10 +-
vendor/composer/autoload_static.php | 53 +-
vendor/composer/installed.json | 594 +-
vendor/composer/installed.php | 157 +-
vendor/composer/platform_check.php | 9 +-
.../cweagans/composer-patches/composer.json | 30 -
.../composer-patches/src/PatchEvent.php | 70 -
.../composer-patches/src/PatchEvents.php | 30 -
.../cweagans/composer-patches/src/Patches.php | 599 --
.../collections/.doctrine-project.json | 32 -
vendor/doctrine/collections/composer.json | 18 +-
.../doctrine/collections/docs/composer.json | 5 +
.../Expr/ClosureExpressionVisitor.php | 269 -
.../Common/Collections/Expr/Comparison.php | 74 -
.../Common/Collections/ExpressionBuilder.php | 181 -
.../AbstractLazyCollection.php | 77 +-
.../Collections => src}/ArrayCollection.php | 142 +-
.../Common/Collections => src}/Collection.php | 52 +-
.../Common/Collections => src}/Criteria.php | 133 +-
.../src/Expr/ClosureExpressionVisitor.php | 270 +
.../collections/src/Expr/Comparison.php | 62 +
.../Expr/CompositeExpression.php | 29 +-
.../Collections => src}/Expr/Expression.php | 2 +
.../Expr/ExpressionVisitor.php | 22 +-
.../Common/Collections => src}/Expr/Value.php | 9 +-
.../collections/src/ExpressionBuilder.php | 128 +
vendor/doctrine/collections/src/Order.php | 11 +
.../ReadableCollection.php | 93 +-
.../Common/Collections => src}/Selectable.php | 12 +-
.../cron-expression/composer.json | 9 +-
.../src/Cron/AbstractField.php | 11 +-
.../src/Cron/CronExpression.php | 4 +-
.../src/Cron/DayOfWeekField.php | 4 +-
.../cron-expression/src/Cron/FieldFactory.php | 2 +-
.../cron-expression/src/Cron/HoursField.php | 11 +-
vendor/ipl/html/composer.json | 3 +-
vendor/ipl/html/src/Attribute.php | 47 +-
vendor/ipl/html/src/Attributes.php | 24 +-
vendor/ipl/html/src/BaseHtmlElement.php | 66 +-
.../src/Contract/DecorableFormElement.php | 32 +
.../html/src/Contract/DecorationResult.php | 35 +
.../html/src/Contract/DecoratorOptions.php | 40 +
.../Contract/DecoratorOptionsInterface.php | 18 +
.../Contract/DefaultFormElementDecoration.php | 39 +
vendor/ipl/html/src/Contract/Form.php | 87 +
.../ipl/html/src/Contract/FormDecoration.php | 40 +
vendor/ipl/html/src/Contract/FormElement.php | 4 +-
.../src/Contract/FormElementDecoration.php | 43 +
.../src/Contract/FormElementDecorator.php | 2 +
vendor/ipl/html/src/Contract/FormElements.php | 103 +
.../src/Contract/HtmlElementInterface.php | 90 +
vendor/ipl/html/src/Contract/MutableHtml.php | 90 +
vendor/ipl/html/src/Form.php | 143 +-
.../src/FormDecoration/DecoratorChain.php | 368 ++
.../FormDecoration/DescriptionDecorator.php | 100 +
.../src/FormDecoration/ErrorsDecorator.php | 64 +
.../src/FormDecoration/FieldsetDecorator.php | 36 +
.../FormDecoration/FormDecorationResult.php | 54 +
.../FormElementDecorationResult.php | 96 +
.../src/FormDecoration/HtmlTagDecorator.php | 217 +
.../src/FormDecoration/LabelDecorator.php | 105 +
.../FormDecoration/RenderElementDecorator.php | 18 +
.../src/FormDecoration/Transformation.php | 39 +
.../src/FormDecorator/CallbackDecorator.php | 3 +
.../html/src/FormDecorator/DdDtDecorator.php | 6 +-
.../src/FormDecorator/DecoratorInterface.php | 4 +-
.../html/src/FormDecorator/DivDecorator.php | 3 +
.../html/src/FormElement/BaseFormElement.php | 80 +-
.../html/src/FormElement/FieldsetElement.php | 15 +-
.../ipl/html/src/FormElement/FileElement.php | 6 +-
.../ipl/html/src/FormElement/FormElements.php | 245 +-
.../ipl/html/src/FormElement/RadioElement.php | 10 +
.../html/src/FormElement/SelectElement.php | 2 +-
.../ipl/html/src/FormElement/TextElement.php | 36 +
vendor/ipl/html/src/HtmlDocument.php | 106 +-
vendor/ipl/orm/composer.json | 2 +-
vendor/ipl/orm/src/Compat/FilterProcessor.php | 17 +-
vendor/ipl/orm/src/Relation/BelongsToMany.php | 29 +-
vendor/ipl/orm/src/Resolver.php | 5 +-
vendor/ipl/scheduler/src/RRule.php | 5 +-
vendor/ipl/sql/src/Connection.php | 20 +
vendor/ipl/sql/src/Test/SharedDatabases.php | 175 +
vendor/ipl/sql/src/Test/TestConnection.php | 49 +
vendor/ipl/validator/composer.json | 6 +-
vendor/ipl/validator/src/BetweenValidator.php | 29 +-
.../ipl/validator/src/CallbackValidator.php | 2 +-
vendor/ipl/validator/src/CidrValidator.php | 4 +
.../ipl/validator/src/DateTimeValidator.php | 6 +-
.../src/DeferredInArrayValidator.php | 6 +-
.../validator/src/EmailAddressValidator.php | 5 +-
vendor/ipl/validator/src/FileValidator.php | 37 +-
.../validator/src/GreaterThanValidator.php | 17 +-
.../ipl/validator/src/HostnameValidator.php | 4 +-
vendor/ipl/validator/src/InArrayValidator.php | 14 +-
.../ipl/validator/src/LessThanValidator.php | 17 +-
.../ipl/validator/src/PrivateKeyValidator.php | 7 +-
.../validator/src/StringLengthValidator.php | 35 +-
vendor/ipl/validator/src/ValidatorChain.php | 26 +-
.../ipl/validator/src/X509CertValidator.php | 6 +-
.../static/font/icinga-icons/selection.json | 2 +-
vendor/ipl/web/composer.json | 4 +-
vendor/ipl/web/src/Common/BaseItemList.php | 54 +-
vendor/ipl/web/src/Common/BaseItemTable.php | 3 +
vendor/ipl/web/src/Common/BaseListItem.php | 5 +-
.../web/src/Common/BaseOrderedItemList.php | 1 +
.../web/src/Common/BaseOrderedListItem.php | 1 +
.../ipl/web/src/Common/BaseTableRowItem.php | 4 +-
.../ipl/web/src/Common/CsrfCounterMeasure.php | 55 +
vendor/ipl/web/src/Common/ItemRenderer.php | 92 +
vendor/ipl/web/src/Compat/CompatForm.php | 69 +
.../FormDecorator/CheckboxDecorator.php | 52 +
.../FormDecorator/DescriptionDecorator.php | 34 +
.../Compat/FormDecorator/LabelDecorator.php | 74 +
vendor/ipl/web/src/Compat/SearchControls.php | 61 +-
.../ipl/web/src/Control/PaginationControl.php | 67 +-
.../web/src/Control/SearchBar/Suggestions.php | 27 +-
.../ipl/web/src/Control/SearchBar/Terms.php | 8 +-
vendor/ipl/web/src/Control/SearchEditor.php | 112 +-
vendor/ipl/web/src/Control/SortControl.php | 62 +-
.../src/FormDecorator/IcingaFormDecorator.php | 6 +
.../web/src/FormElement/ScheduleElement.php | 129 +-
.../ScheduleElement/AnnuallyFields.php | 27 +-
.../ScheduleElement/MonthlyFields.php | 3 +-
.../ScheduleElement/WeeklyFields.php | 3 +-
.../web/src/FormElement/SearchSuggestions.php | 279 +
.../web/src/FormElement/SuggestionElement.php | 86 +
vendor/ipl/web/src/FormElement/TermInput.php | 21 +-
.../FormElement/TermInput/TermContainer.php | 21 +-
.../FormElement/TermInput/TermSuggestions.php | 279 +-
vendor/ipl/web/src/Layout/Controls.php | 2 +-
.../ipl/web/src/Layout/DetailedItemLayout.php | 27 +
.../src/Layout/DetailedItemTableLayout.php | 19 +
.../ipl/web/src/Layout/HeaderItemLayout.php | 17 +
vendor/ipl/web/src/Layout/ItemLayout.php | 478 ++
vendor/ipl/web/src/Layout/ItemTableLayout.php | 125 +
.../ipl/web/src/Layout/MinimalItemLayout.php | 30 +
.../web/src/Layout/MinimalItemTableLayout.php | 29 +
vendor/ipl/web/src/Widget/Ball.php | 102 +
vendor/ipl/web/src/Widget/ButtonLink.php | 45 +-
vendor/ipl/web/src/Widget/ContinueWith.php | 5 +
vendor/ipl/web/src/Widget/ItemList.php | 191 +
vendor/ipl/web/src/Widget/ItemTable.php | 76 +
.../Widget/ItemTable/ItemTableRenderer.php | 26 +
vendor/ipl/web/src/Widget/ItemTableRow.php | 46 +
vendor/ipl/web/src/Widget/ListItem.php | 46 +
vendor/ipl/web/src/Widget/StateBall.php | 56 +-
vendor/ramsey/collection/LICENSE | 2 +-
vendor/ramsey/collection/composer.json | 133 +-
.../ramsey/collection/src/AbstractArray.php | 65 +-
.../collection/src/AbstractCollection.php | 281 +-
vendor/ramsey/collection/src/AbstractSet.php | 21 +-
.../ramsey/collection/src/ArrayInterface.php | 6 +-
vendor/ramsey/collection/src/Collection.php | 25 +-
.../collection/src/CollectionInterface.php | 112 +-
.../collection/src/DoubleEndedQueue.php | 133 +-
.../src/DoubleEndedQueueInterface.php | 43 +-
...rException.php => CollectionException.php} | 7 +-
.../Exception/CollectionMismatchException.php | 4 +-
.../Exception/InvalidArgumentException.php | 4 +-
...eption.php => InvalidPropertyOrMethod.php} | 8 +-
.../src/Exception/NoSuchElementException.php | 4 +-
.../src/Exception/OutOfBoundsException.php | 4 +-
.../UnsupportedOperationException.php | 4 +-
vendor/ramsey/collection/src/GenericArray.php | 2 +-
.../ramsey/collection/src/Map/AbstractMap.php | 113 +-
.../collection/src/Map/AbstractTypedMap.php | 24 +-
.../src/Map/AssociativeArrayMap.php | 3 +-
.../collection/src/Map/MapInterface.php | 59 +-
.../collection/src/Map/NamedParameterMap.php | 22 +-
vendor/ramsey/collection/src/Map/TypedMap.php | 47 +-
.../collection/src/Map/TypedMapInterface.php | 3 +-
vendor/ramsey/collection/src/Queue.php | 105 +-
.../ramsey/collection/src/QueueInterface.php | 23 +-
vendor/ramsey/collection/src/Set.php | 20 +-
vendor/ramsey/collection/src/Sort.php | 31 +
.../ramsey/collection/src/Tool/TypeTrait.php | 48 +-
.../src/Tool/ValueExtractorTrait.php | 76 +-
.../src/Tool/ValueToStringTrait.php | 16 +-
vendor/ramsey/uuid/LICENSE | 2 +-
vendor/ramsey/uuid/composer.json | 141 +-
vendor/ramsey/uuid/src/BinaryUtils.php | 33 +-
.../uuid/src/Builder/BuilderCollection.php | 19 +-
.../uuid/src/Builder/DefaultUuidBuilder.php | 4 +-
.../uuid/src/Builder/DegradedUuidBuilder.php | 34 +-
.../uuid/src/Builder/FallbackBuilder.php | 22 +-
.../uuid/src/Builder/UuidBuilderInterface.php | 7 +-
.../ramsey/uuid/src/Codec/CodecInterface.php | 32 +-
.../ramsey/uuid/src/Codec/GuidStringCodec.php | 31 +-
.../uuid/src/Codec/OrderedTimeCodec.php | 62 +-
vendor/ramsey/uuid/src/Codec/StringCodec.php | 59 +-
.../src/Codec/TimestampFirstCombCodec.php | 39 +-
.../uuid/src/Codec/TimestampLastCombCodec.php | 25 +-
.../Converter/Number/BigNumberConverter.php | 19 +-
.../Number/DegradedNumberConverter.php | 6 +-
.../Number/GenericNumberConverter.php | 27 +-
.../Converter/NumberConverterInterface.php | 32 +-
.../Converter/Time/BigNumberTimeConverter.php | 13 +-
.../Converter/Time/DegradedTimeConverter.php | 6 +-
.../Converter/Time/GenericTimeConverter.php | 66 +-
.../src/Converter/Time/PhpTimeConverter.php | 75 +-
.../src/Converter/Time/UnixTimeConverter.php | 92 +
.../src/Converter/TimeConverterInterface.php | 27 +-
vendor/ramsey/uuid/src/DegradedUuid.php | 6 +-
.../uuid/src/DeprecatedUuidInterface.php | 61 +-
.../uuid/src/DeprecatedUuidMethodsTrait.php | 194 +-
.../src/Exception/DceSecurityException.php | 3 +-
.../Exception/InvalidUuidStringException.php | 4 +-
.../uuid/src/Exception/NameException.php | 3 +-
.../src/Exception/RandomSourceException.php | 4 +-
vendor/ramsey/uuid/src/FeatureSet.php | 176 +-
.../uuid/src/Fields/FieldsInterface.php | 9 +-
.../src/Fields/SerializableFieldsTrait.php | 19 +-
.../uuid/src/Generator/CombGenerator.php | 67 +-
.../src/Generator/DceSecurityGenerator.php | 55 +-
.../DceSecurityGeneratorInterface.php | 27 +-
.../src/Generator/DefaultNameGenerator.php | 24 +-
.../src/Generator/DefaultTimeGenerator.php | 59 +-
.../src/Generator/NameGeneratorFactory.php | 3 +-
.../src/Generator/NameGeneratorInterface.php | 9 +-
.../src/Generator/PeclUuidNameGenerator.php | 32 +-
.../src/Generator/PeclUuidRandomGenerator.php | 2 +-
.../src/Generator/PeclUuidTimeGenerator.php | 5 +-
.../src/Generator/RandomBytesGenerator.php | 9 +-
.../src/Generator/RandomGeneratorFactory.php | 3 +-
.../Generator/RandomGeneratorInterface.php | 2 +-
.../uuid/src/Generator/RandomLibAdapter.php | 17 +-
.../src/Generator/TimeGeneratorFactory.php | 33 +-
.../src/Generator/TimeGeneratorInterface.php | 13 +-
.../uuid/src/Generator/UnixTimeGenerator.php | 165 +
vendor/ramsey/uuid/src/Guid/Fields.php | 76 +-
vendor/ramsey/uuid/src/Guid/Guid.php | 24 +-
vendor/ramsey/uuid/src/Guid/GuidBuilder.php | 41 +-
.../uuid/src/Lazy/LazyUuidFromString.php | 367 +-
.../uuid/src/Math/BrickMathCalculator.php | 18 +-
.../uuid/src/Math/CalculatorInterface.php | 25 +-
vendor/ramsey/uuid/src/Math/RoundingMode.php | 181 +-
vendor/ramsey/uuid/src/Nonstandard/Fields.php | 31 +-
vendor/ramsey/uuid/src/Nonstandard/Uuid.php | 7 +-
.../uuid/src/Nonstandard/UuidBuilder.php | 44 +-
vendor/ramsey/uuid/src/Nonstandard/UuidV6.php | 74 +-
.../Dce/SystemDceSecurityProvider.php | 80 +-
.../Provider/DceSecurityProviderInterface.php | 3 +-
.../Provider/Node/FallbackNodeProvider.php | 21 +-
.../Provider/Node/NodeProviderCollection.php | 19 +-
.../src/Provider/Node/RandomNodeProvider.php | 24 +-
.../src/Provider/Node/StaticNodeProvider.php | 19 +-
.../src/Provider/Node/SystemNodeProvider.php | 93 +-
.../src/Provider/Time/FixedTimeProvider.php | 23 +-
vendor/ramsey/uuid/src/Rfc4122/Fields.php | 120 +-
.../uuid/src/Rfc4122/FieldsInterface.php | 58 +-
vendor/ramsey/uuid/src/Rfc4122/MaxTrait.php | 40 +
vendor/ramsey/uuid/src/Rfc4122/MaxUuid.php | 28 +
vendor/ramsey/uuid/src/Rfc4122/NilTrait.php | 9 +-
vendor/ramsey/uuid/src/Rfc4122/NilUuid.php | 7 +-
vendor/ramsey/uuid/src/Rfc4122/TimeTrait.php | 53 +
.../ramsey/uuid/src/Rfc4122/UuidBuilder.php | 89 +-
.../ramsey/uuid/src/Rfc4122/UuidInterface.php | 14 +-
vendor/ramsey/uuid/src/Rfc4122/UuidV1.php | 60 +-
vendor/ramsey/uuid/src/Rfc4122/UuidV2.php | 80 +-
vendor/ramsey/uuid/src/Rfc4122/UuidV3.php | 23 +-
vendor/ramsey/uuid/src/Rfc4122/UuidV4.php | 22 +-
vendor/ramsey/uuid/src/Rfc4122/UuidV5.php | 23 +-
vendor/ramsey/uuid/src/Rfc4122/UuidV6.php | 29 +
vendor/ramsey/uuid/src/Rfc4122/UuidV7.php | 58 +
vendor/ramsey/uuid/src/Rfc4122/UuidV8.php | 60 +
vendor/ramsey/uuid/src/Rfc4122/Validator.php | 16 +-
.../ramsey/uuid/src/Rfc4122/VariantTrait.php | 77 +-
.../ramsey/uuid/src/Rfc4122/VersionTrait.php | 53 +-
vendor/ramsey/uuid/src/Type/Decimal.php | 44 +-
vendor/ramsey/uuid/src/Type/Hexadecimal.php | 77 +-
vendor/ramsey/uuid/src/Type/Integer.php | 125 +-
.../ramsey/uuid/src/Type/NumberInterface.php | 2 +-
vendor/ramsey/uuid/src/Type/Time.php | 58 +-
vendor/ramsey/uuid/src/Type/TypeInterface.php | 8 +-
vendor/ramsey/uuid/src/Uuid.php | 430 +-
vendor/ramsey/uuid/src/UuidFactory.php | 239 +-
.../ramsey/uuid/src/UuidFactoryInterface.php | 227 +-
vendor/ramsey/uuid/src/UuidInterface.php | 51 +-
.../uuid/src/Validator/GenericValidator.php | 8 +-
.../uuid/src/Validator/ValidatorInterface.php | 8 +-
vendor/ramsey/uuid/src/functions.php | 96 +-
vendor/symfony/polyfill-ctype/Ctype.php | 232 -
vendor/symfony/polyfill-ctype/LICENSE | 19 -
vendor/symfony/polyfill-ctype/bootstrap.php | 50 -
vendor/symfony/polyfill-ctype/bootstrap80.php | 46 -
vendor/symfony/polyfill-ctype/composer.json | 38 -
vendor/symfony/polyfill-php80/Php80.php | 115 -
vendor/symfony/polyfill-php80/PhpToken.php | 106 -
.../Resources/stubs/Attribute.php | 31 -
.../Resources/stubs/PhpToken.php | 16 -
.../Resources/stubs/Stringable.php | 20 -
.../Resources/stubs/UnhandledMatchError.php | 16 -
.../Resources/stubs/ValueError.php | 16 -
vendor/symfony/polyfill-php80/bootstrap.php | 42 -
.../LICENSE | 2 +-
vendor/symfony/polyfill-php84/Php84.php | 217 +
.../Resources/stubs/Deprecated.php | 25 +
.../Resources/stubs/ReflectionConstant.php | 158 +
vendor/symfony/polyfill-php84/bootstrap.php | 82 +
vendor/symfony/polyfill-php84/bootstrap82.php | 20 +
.../composer.json | 10 +-
vendor/webmozart/assert/LICENSE | 20 -
vendor/webmozart/assert/composer.json | 43 -
vendor/webmozart/assert/src/Assert.php | 2080 -------
.../assert/src/InvalidArgumentException.php | 16 -
vendor/webmozart/assert/src/Mixin.php | 5089 -----------------
360 files changed, 12150 insertions(+), 16362 deletions(-)
create mode 100644 asset/css/action-link-and-button-link.less
create mode 100644 asset/css/item-layout.less
create mode 100644 asset/css/suggestion-element.less
create mode 100644 asset/js/iterator.js
create mode 100644 asset/static/font/icinga-icons/src/add-inside.svg
create mode 100644 asset/static/font/icinga-icons/src/insert-group.svg
create mode 100644 asset/static/font/icinga-icons/src/wrap.svg
create mode 100644 vendor/brick/math/src/Internal/CalculatorRegistry.php
delete mode 100644 vendor/cweagans/composer-patches/composer.json
delete mode 100644 vendor/cweagans/composer-patches/src/PatchEvent.php
delete mode 100644 vendor/cweagans/composer-patches/src/PatchEvents.php
delete mode 100644 vendor/cweagans/composer-patches/src/Patches.php
delete mode 100644 vendor/doctrine/collections/.doctrine-project.json
create mode 100644 vendor/doctrine/collections/docs/composer.json
delete mode 100644 vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/ClosureExpressionVisitor.php
delete mode 100644 vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Comparison.php
delete mode 100644 vendor/doctrine/collections/lib/Doctrine/Common/Collections/ExpressionBuilder.php
rename vendor/doctrine/collections/{lib/Doctrine/Common/Collections => src}/AbstractLazyCollection.php (79%)
rename vendor/doctrine/collections/{lib/Doctrine/Common/Collections => src}/ArrayCollection.php (73%)
rename vendor/doctrine/collections/{lib/Doctrine/Common/Collections => src}/Collection.php (71%)
rename vendor/doctrine/collections/{lib/Doctrine/Common/Collections => src}/Criteria.php (54%)
create mode 100644 vendor/doctrine/collections/src/Expr/ClosureExpressionVisitor.php
create mode 100644 vendor/doctrine/collections/src/Expr/Comparison.php
rename vendor/doctrine/collections/{lib/Doctrine/Common/Collections => src}/Expr/CompositeExpression.php (66%)
rename vendor/doctrine/collections/{lib/Doctrine/Common/Collections => src}/Expr/Expression.php (89%)
rename vendor/doctrine/collections/{lib/Doctrine/Common/Collections => src}/Expr/ExpressionVisitor.php (64%)
rename vendor/doctrine/collections/{lib/Doctrine/Common/Collections => src}/Expr/Value.php (70%)
create mode 100644 vendor/doctrine/collections/src/ExpressionBuilder.php
create mode 100644 vendor/doctrine/collections/src/Order.php
rename vendor/doctrine/collections/{lib/Doctrine/Common/Collections => src}/ReadableCollection.php (70%)
rename vendor/doctrine/collections/{lib/Doctrine/Common/Collections => src}/Selectable.php (72%)
create mode 100644 vendor/ipl/html/src/Contract/DecorableFormElement.php
create mode 100644 vendor/ipl/html/src/Contract/DecorationResult.php
create mode 100644 vendor/ipl/html/src/Contract/DecoratorOptions.php
create mode 100644 vendor/ipl/html/src/Contract/DecoratorOptionsInterface.php
create mode 100644 vendor/ipl/html/src/Contract/DefaultFormElementDecoration.php
create mode 100644 vendor/ipl/html/src/Contract/Form.php
create mode 100644 vendor/ipl/html/src/Contract/FormDecoration.php
create mode 100644 vendor/ipl/html/src/Contract/FormElementDecoration.php
create mode 100644 vendor/ipl/html/src/Contract/FormElements.php
create mode 100644 vendor/ipl/html/src/Contract/HtmlElementInterface.php
create mode 100644 vendor/ipl/html/src/Contract/MutableHtml.php
create mode 100644 vendor/ipl/html/src/FormDecoration/DecoratorChain.php
create mode 100644 vendor/ipl/html/src/FormDecoration/DescriptionDecorator.php
create mode 100644 vendor/ipl/html/src/FormDecoration/ErrorsDecorator.php
create mode 100644 vendor/ipl/html/src/FormDecoration/FieldsetDecorator.php
create mode 100644 vendor/ipl/html/src/FormDecoration/FormDecorationResult.php
create mode 100644 vendor/ipl/html/src/FormDecoration/FormElementDecorationResult.php
create mode 100644 vendor/ipl/html/src/FormDecoration/HtmlTagDecorator.php
create mode 100644 vendor/ipl/html/src/FormDecoration/LabelDecorator.php
create mode 100644 vendor/ipl/html/src/FormDecoration/RenderElementDecorator.php
create mode 100644 vendor/ipl/html/src/FormDecoration/Transformation.php
create mode 100644 vendor/ipl/sql/src/Test/SharedDatabases.php
create mode 100644 vendor/ipl/web/src/Common/ItemRenderer.php
mode change 100644 => 100755 vendor/ipl/web/src/Compat/CompatForm.php
create mode 100644 vendor/ipl/web/src/Compat/FormDecorator/CheckboxDecorator.php
create mode 100644 vendor/ipl/web/src/Compat/FormDecorator/DescriptionDecorator.php
create mode 100755 vendor/ipl/web/src/Compat/FormDecorator/LabelDecorator.php
create mode 100644 vendor/ipl/web/src/FormElement/SearchSuggestions.php
create mode 100644 vendor/ipl/web/src/FormElement/SuggestionElement.php
create mode 100644 vendor/ipl/web/src/Layout/DetailedItemLayout.php
create mode 100644 vendor/ipl/web/src/Layout/DetailedItemTableLayout.php
create mode 100644 vendor/ipl/web/src/Layout/HeaderItemLayout.php
create mode 100644 vendor/ipl/web/src/Layout/ItemLayout.php
create mode 100644 vendor/ipl/web/src/Layout/ItemTableLayout.php
create mode 100644 vendor/ipl/web/src/Layout/MinimalItemLayout.php
create mode 100644 vendor/ipl/web/src/Layout/MinimalItemTableLayout.php
create mode 100644 vendor/ipl/web/src/Widget/Ball.php
create mode 100644 vendor/ipl/web/src/Widget/ItemList.php
create mode 100644 vendor/ipl/web/src/Widget/ItemTable.php
create mode 100644 vendor/ipl/web/src/Widget/ItemTable/ItemTableRenderer.php
create mode 100644 vendor/ipl/web/src/Widget/ItemTableRow.php
create mode 100644 vendor/ipl/web/src/Widget/ListItem.php
rename vendor/ramsey/collection/src/Exception/{InvalidSortOrderException.php => CollectionException.php} (73%)
rename vendor/ramsey/collection/src/Exception/{ValueExtractionException.php => InvalidPropertyOrMethod.php} (58%)
create mode 100644 vendor/ramsey/collection/src/Sort.php
create mode 100644 vendor/ramsey/uuid/src/Converter/Time/UnixTimeConverter.php
create mode 100644 vendor/ramsey/uuid/src/Generator/UnixTimeGenerator.php
create mode 100644 vendor/ramsey/uuid/src/Rfc4122/MaxTrait.php
create mode 100644 vendor/ramsey/uuid/src/Rfc4122/MaxUuid.php
create mode 100644 vendor/ramsey/uuid/src/Rfc4122/TimeTrait.php
create mode 100644 vendor/ramsey/uuid/src/Rfc4122/UuidV6.php
create mode 100644 vendor/ramsey/uuid/src/Rfc4122/UuidV7.php
create mode 100644 vendor/ramsey/uuid/src/Rfc4122/UuidV8.php
delete mode 100644 vendor/symfony/polyfill-ctype/Ctype.php
delete mode 100644 vendor/symfony/polyfill-ctype/LICENSE
delete mode 100644 vendor/symfony/polyfill-ctype/bootstrap.php
delete mode 100644 vendor/symfony/polyfill-ctype/bootstrap80.php
delete mode 100644 vendor/symfony/polyfill-ctype/composer.json
delete mode 100644 vendor/symfony/polyfill-php80/Php80.php
delete mode 100644 vendor/symfony/polyfill-php80/PhpToken.php
delete mode 100644 vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php
delete mode 100644 vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php
delete mode 100644 vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php
delete mode 100644 vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php
delete mode 100644 vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php
delete mode 100644 vendor/symfony/polyfill-php80/bootstrap.php
rename vendor/symfony/{polyfill-php80 => polyfill-php84}/LICENSE (95%)
create mode 100644 vendor/symfony/polyfill-php84/Php84.php
create mode 100644 vendor/symfony/polyfill-php84/Resources/stubs/Deprecated.php
create mode 100644 vendor/symfony/polyfill-php84/Resources/stubs/ReflectionConstant.php
create mode 100644 vendor/symfony/polyfill-php84/bootstrap.php
create mode 100644 vendor/symfony/polyfill-php84/bootstrap82.php
rename vendor/symfony/{polyfill-php80 => polyfill-php84}/composer.json (74%)
delete mode 100644 vendor/webmozart/assert/LICENSE
delete mode 100644 vendor/webmozart/assert/composer.json
delete mode 100644 vendor/webmozart/assert/src/Assert.php
delete mode 100644 vendor/webmozart/assert/src/InvalidArgumentException.php
delete mode 100644 vendor/webmozart/assert/src/Mixin.php
diff --git a/VERSION b/VERSION
index 5f1dd0a..8347ddf 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-v0.15.1
+v0.16.0-dev
diff --git a/asset/css/action-link-and-button-link.less b/asset/css/action-link-and-button-link.less
new file mode 100644
index 0000000..d654f66
--- /dev/null
+++ b/asset/css/action-link-and-button-link.less
@@ -0,0 +1,26 @@
+.action-link {
+ color: var(--control-color, @control-color);
+}
+
+.button-link {
+ .action-link();
+ .rounded-corners(3px);
+
+ background: var(--default-input-bg, @default-input-bg);
+ display: inline-block;
+ padding: 0.25em 0.5em;
+
+ &:hover {
+ background: var(--default-input-hover-bg, @default-input-hover-bg);
+ text-decoration: none;
+ }
+
+ &[aria-disabled="true"] {
+ background: none;
+ border: 1px solid var(--control-disabled-color, @control-disabled-color);
+ color: var(--control-disabled-color, @control-disabled-color);
+ cursor: not-allowed;
+
+ .user-select(none);
+ }
+}
diff --git a/asset/css/balls.less b/asset/css/balls.less
index f3afae3..70ef391 100644
--- a/asset/css/balls.less
+++ b/asset/css/balls.less
@@ -2,18 +2,27 @@
.ball {
border-radius: 50%;
- display: inline-block;
- text-align: center;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
}
.ball-size-xs {
height: 1/3em;
width: 1/3em;
+
+ i.icon, span {
+ display: none;
+ }
}
.ball-size-s {
height: 0.5em;
width: 0.5em;
+
+ i.icon, span {
+ display: none;
+ }
}
.ball-size-m {
@@ -21,10 +30,14 @@
width: 0.75em;
line-height: 0;
- i.icon:before {
+ i.icon::before {
font-size: .75 - @ball-pad * 2;
line-height: 1em;
}
+
+ span {
+ display: none;
+ }
}
.ball-size-ml {
@@ -35,11 +48,15 @@
i.icon {
line-height: 0.3;
- &:before {
+ &::before {
font-size: 0.8 - @ball-pad * 2;
line-height: 1 - @ball-pad * 2;
}
}
+
+ span {
+ display: none;
+ }
}
.ball-size-l {
@@ -47,7 +64,7 @@
width: 1.5em;
line-height: 1em;
- i.icon:before {
+ i.icon::before, span {
font-size: 1 - @ball-pad * 2;
line-height: 1.5 - @ball-pad * 2;
}
@@ -57,7 +74,7 @@
width: 2em;
height: 2em;
- i.icon:before {
+ i.icon::before, span {
line-height: 2 - @ball-pad * 2;
}
}
@@ -75,7 +92,7 @@
.state-ball {
.ball();
- &.state-pending:not(.ball-size-l):not(.ball-size-xl) {
+ &.state-pending:not(.ball-size-l, .ball-size-xl) {
.ball-solid(var(--state-pending, @state-pending));
}
@@ -84,7 +101,7 @@
.ball-outline(var(--state-pending, @state-pending));
}
- &.state-up:not(.ball-size-l):not(.ball-size-xl) {
+ &.state-up:not(.ball-size-l, .ball-size-xl) {
.ball-solid(var(--state-up, @state-up));
}
@@ -97,7 +114,7 @@
.ball-solid(var(--state-down, @state-down));
}
- &.state-ok:not(.ball-size-l):not(.ball-size-xl) {
+ &.state-ok:not(.ball-size-l, .ball-size-xl) {
.ball-solid(var(--state-ok, @state-ok));
}
@@ -124,7 +141,6 @@
i.icon {
text-align: center;
- display: block;
&::before {
margin-right: 0;
@@ -133,13 +149,13 @@
// Specific icon styles
&.ball-size-l i {
- &.fa-sitemap:before {
+ &.fa-sitemap::before {
font-size: 8px; // px to ignore browser min font-size
}
}
&.ball-size-xl i {
- &.fa-sitemap:before {
+ &.fa-sitemap::before {
font-size: .857em;
line-height: (2 - @ball-pad * 2) / .857;
}
diff --git a/asset/css/compat.less b/asset/css/compat.less
index 1188c7e..c4772ac 100644
--- a/asset/css/compat.less
+++ b/asset/css/compat.less
@@ -2,10 +2,15 @@
.icinga-controls {
.uploaded-files {
- background-color: @default-input-bg;
+ background-color: var(--default-input-bg, @default-input-bg);
}
}
+// Icinga Web < 2.13
+.button-link[aria-disabled="true"]:hover {
+ background: none;
+}
+
form.icinga-form {
.uploaded-files {
flex: 1 1 auto;
@@ -20,6 +25,14 @@ form.icinga-form {
}
}
+.icinga-controls {
+ .required-hint {
+ font-weight: bold;
+ color: var(--default-text-color-light, @default-text-color-light);
+ }
+}
+
+
// Button styles
// The `form` selector is only required to overrule the hover effect applied by Icinga Web.
@@ -86,3 +99,51 @@ form.icinga-form .control-group {
}
}
}
+
+// suggestion-element style
+form.icinga-form .suggestion-element-group {
+ flex: 1 1 auto;
+
+ .suggestion-element {
+ border-radius: 0 0.25em 0.25em 0;
+ }
+}
+
+.module-icingadb {
+ // Icinga DB Web (legacy) table header layout (e.g. in group details)
+ > .controls {
+ > .table-row {
+ display: flex;
+ gap: .5em;
+
+ > .col.title {
+ margin-right: auto;
+ }
+ }
+ }
+
+ // Icinga DB Web (legacy) object grid layout
+ > .content > .item-table.group-grid:has(.col.title) {
+ grid-template-columns: repeat(auto-fit, 15em) !important;
+
+ > .group-grid-cell {
+ display: revert;
+
+ &::before, &::after {
+ display: none !important;
+ }
+
+ > .col.title {
+ border: none;
+
+ > .column-content {
+ overflow: hidden;
+
+ > * {
+ .text-ellipsis();
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/asset/css/controls.less b/asset/css/controls.less
index 1bccbd8..ed27794 100644
--- a/asset/css/controls.less
+++ b/asset/css/controls.less
@@ -16,7 +16,7 @@
display: block;
}
- i:before {
+ i::before {
margin: 0;
}
}
@@ -52,7 +52,7 @@
}
}
- i.icon:before {
+ i.icon::before {
color: inherit;
}
}
@@ -69,7 +69,7 @@
height: 100%;
}
- i.icon:before {
+ i.icon::before {
margin-right: 0;
}
}
@@ -154,11 +154,6 @@
}
> .search-controls > .search-bar .filter-input-area {
- label {
- &::after,
- input {
- padding: 0 .5em;
- }
- }
+ --term-padding-v: 0px;
}
}
diff --git a/asset/css/empty-state.less b/asset/css/empty-state.less
index 6291055..75879d8 100644
--- a/asset/css/empty-state.less
+++ b/asset/css/empty-state.less
@@ -1,5 +1,5 @@
.empty-state {
- color: @empty-state-color;
+ color: var(--empty-state-color, @empty-state-color);
}
.empty-state-bar {
@@ -7,5 +7,6 @@
text-align: center;
.rounded-corners();
- background-color: @empty-state-bar-bg;
+ background-color: var(--empty-state-bar-bg, @empty-state-bar-bg);
+ color: var(--default-text-color, @default-text-color);
}
diff --git a/asset/css/icinga-icons.less b/asset/css/icinga-icons.less
index 5b631f9..0ed3046 100644
--- a/asset/css/icinga-icons.less
+++ b/asset/css/icinga-icons.less
@@ -1,5 +1,5 @@
@font-face {
- font-family: 'Icinga-Icons';
+ font-family: Icinga-Icons;
src: url('@{iplWebAssets}/font/icinga-icons/fonts/Icinga-Icons.ttf') format('truetype'),
url('@{iplWebAssets}/font/icinga-icons/fonts/Icinga-Icons.woff') format('woff'),
url('@{iplWebAssets}/font/icinga-icons/fonts/Icinga-Icons.svg') format('svg');
@@ -8,9 +8,9 @@
font-display: block;
}
-[class^="iicon-"]:before, [class*=" iicon-"]:before {
+[class^="iicon-"]::before, [class*=" iicon-"]::before {
/* use !important to prevent issues with browser extensions that change fonts */
- font-family: 'Icinga-Icons';
+ font-family: Icinga-Icons;
speak: none;
font-style: normal;
font-weight: normal;
@@ -23,42 +23,51 @@
-moz-osx-font-smoothing: grayscale;
}
-.iicon-certificate:before {
+.iicon-add-inside::before {
+ content: "\e90c";
+}
+.iicon-insert-group::before {
+ content: "\e90d";
+}
+.iicon-wrap::before {
+ content: "\e90e";
+}
+.iicon-certificate::before {
content: "\e906";
}
-.iicon-filter-check-circle:before {
+.iicon-filter-check-circle::before {
content: "\e90b";
}
-.iicon-ca-check-circle:before {
+.iicon-ca-check-circle::before {
content: "\e908";
}
-.iicon-refresh-cert:before {
+.iicon-refresh-cert::before {
content: "\e909";
}
-.iicon-th-list:before {
+.iicon-th-list::before {
content: "\e90a";
}
-.iicon-icinga:before {
+.iicon-icinga::before {
content: "\e907";
}
-.iicon-minimal:before,
-.iicon-list-view-minimal:before {
+.iicon-minimal::before,
+.iicon-list-view-minimal::before {
content: "\e900";
}
-.iicon-detailed:before,
-.iicon-list-view-detailed:before {
+.iicon-detailed::before,
+.iicon-list-view-detailed::before {
content: "\e901";
}
-.iicon-default:before,
-.iicon-list-view-default:before {
+.iicon-default::before,
+.iicon-list-view-default::before {
content: "\e902";
}
-.iicon-grid:before {
+.iicon-grid::before {
content: "\e903";
}
-.iicon-bracket-open:before {
+.iicon-bracket-open::before {
content: "\e904";
}
-.iicon-bracket-close:before {
+.iicon-bracket-close::before {
content: "\e905";
}
diff --git a/asset/css/item-layout.less b/asset/css/item-layout.less
new file mode 100644
index 0000000..0d5ef68
--- /dev/null
+++ b/asset/css/item-layout.less
@@ -0,0 +1,177 @@
+// Layout
+
+.item-layout {
+ // Note that mode specific rules are as strict as possible to avoid conflicts with nested layouts.
+ // Consider an item which contains another item in a different layout mode. Coincidentally, this is
+ // already the case in Icinga DB Web with the last comment flyout.
+
+ .flowing-content(@layout) when (@layout = "default") {
+ display: inline-flex;
+ align-items: baseline;
+ white-space: nowrap;
+ min-width: 0;
+ column-gap: .28125em; // calculated width
+
+ > .ellipsize, > .subject { // .subject is compat only, Icinga DB Web used it thoroughly
+ .text-ellipsis();
+ }
+ }
+ .flowing-content(@layout) when (@layout = "detailed") {
+ display: inline-flex;
+ align-items: baseline;
+ flex-wrap: wrap;
+ column-gap: .28125em; // calculated width
+ }
+
+ display: flex;
+
+ .visual {
+ display: flex;
+ flex-direction: column;
+
+ width: auto;
+ padding: .25em 0;
+ margin-right: 1em;
+
+ > i.icon {
+ font-size: 1.5em;
+
+ &::before {
+ margin-right: 0;
+ }
+ }
+ }
+
+ .main {
+ flex: 1 1 auto;
+ padding: .25em 0;
+ width: 0;
+ }
+
+ header {
+ display: flex;
+ align-items: baseline;
+ justify-content: space-between;
+
+ > .extended-info {
+ flex-shrink: 0;
+ }
+ }
+
+ .caption {
+ p {
+ display: inline-block;
+ }
+
+ img {
+ max-height: 1em;
+ }
+ }
+
+ footer {
+ display: flex;
+ justify-content: space-between;
+
+ padding-top: .5em;
+ }
+
+ .title {
+ margin-right: 1em;
+ }
+
+ &.minimal-item-layout > .main > header {
+ max-width: 100%;
+ height: 1.5em;
+
+ > .caption {
+ flex: 1 1 auto;
+ height: 1.5em;
+ width: 0;
+
+ &:not(:empty) {
+ margin-right: 1em;
+ }
+
+ .text-ellipsis();
+ }
+ }
+
+ &.default-item-layout > .main {
+ > header {
+ height: 1.5em;
+
+ > .title {
+ .flowing-content("default");
+ }
+
+ > .extended-info {
+ .flowing-content("default");
+ }
+ }
+
+ > .caption {
+ height: 1.5em;
+
+ .text-ellipsis();
+ }
+ }
+
+ &.detailed-item-layout > .main {
+ > header {
+ > .title {
+ .flowing-content("detailed");
+
+ word-break: break-word;
+ hyphens: auto;
+ }
+
+ > .extended-info {
+ .flowing-content("detailed");
+ }
+ }
+
+ > .caption {
+ display: block;
+ overflow: hidden;
+ position: relative;
+
+ .line-clamp(5);
+ }
+ }
+}
+
+// Style
+
+.item-layout {
+ color: var(--default-text-color-light, @default-text-color-light);
+
+ .caption {
+ i {
+ opacity: 0.8;
+ }
+
+ a {
+ color: var(--default-text-color, @default-text-color);
+ }
+ }
+
+ .title {
+ .subject {
+ color: var(--default-text-color, @default-text-color);
+ }
+
+ a {
+ color: var(--default-text-color, @default-text-color);
+ font-weight: bold;
+
+ &:hover {
+ color: var(--link-hover-color, @link-hover-color);
+ text-decoration: none;
+
+ .subject {
+ color: var(--link-hover-color, @link-hover-color);
+ }
+ }
+ }
+ }
+}
diff --git a/asset/css/list/item-list.less b/asset/css/list/item-list.less
index c5c0bd2..56aba0d 100644
--- a/asset/css/list/item-list.less
+++ b/asset/css/list/item-list.less
@@ -4,82 +4,35 @@
list-style-type: none;
}
+.content:has(> .item-list) > .item-list > .empty-state {
+ .empty-state-bar();
+}
+
// Layout
.item-list {
margin: 0;
padding: 0;
- .list-item {
- display: flex;
-
- .main {
- flex: 1 1 auto;
- padding: .5em 0;
- width: 0;
- margin-left: .5em;
- }
-
- .visual {
- display: flex;
- align-items: center;
- flex-direction: column;
- }
-
- .caption {
- height: 3em;
- text-overflow: ellipsis;
- overflow: hidden;
-
- .line-clamp();
-
- img {
- max-height: 1em;
- }
- }
-
- header {
- display: flex;
- align-items: flex-start;
- justify-content: space-between;
- }
-
- footer {
- display: flex;
- justify-content: space-between;
- }
- }
-
> .empty-state-bar {
margin: 0 1em;
}
}
-.item-list.default-layout .list-item {
- .title {
- display: inline-flex;
- align-items: baseline;
- white-space: nowrap;
- min-width: 0;
-
- > * {
- margin: 0 .28125em; // 0 calculated width
-
- &:first-child {
- margin-left: 0;
- }
-
- &:last-child {
- margin-right: 0;
- }
- }
-
- .subject {
- .text-ellipsis();
- }
- }
-}
-
.controls .list-item:not(:last-child) {
margin-bottom: .5em;
}
+
+:not(.dashboard) > .container > .content:has(> .item-list), // compat only, for Icinga Web (See #286)
+.content:has(> .item-list) {
+ padding-left: 0;
+ padding-right: 0;
+
+ > .item-list > .list-item {
+ padding-left: 1em;
+ padding-right: 1em;
+ }
+ > .item-list > .empty-state {
+ margin: 0 1em;
+ }
+}
diff --git a/asset/css/list/item-table.less b/asset/css/list/item-table.less
index bd87503..d075702 100644
--- a/asset/css/list/item-table.less
+++ b/asset/css/list/item-table.less
@@ -4,79 +4,116 @@ ul.item-table {
list-style-type: none;
}
-.table-row {
- color: @default-text-color-light;
-
- .title {
- .subject {
- color: @default-text-color;
- }
-
- a {
- font-weight: bold;
-
- &:hover {
- color: @list-item-title-hover-color;
- text-decoration: none;
- }
- }
- }
-}
-
-@media print {
- .item-table li.page-break-follows:not(:last-of-type) {
- .col {
- border-bottom: none;
- }
-
- .visual {
- margin-bottom: 0;
- }
- }
+.content:has(> .item-table) > .item-table > .empty-state {
+ .empty-state-bar();
}
// Layout
-.table-row {
- .title {
- display: flex;
+ul.item-table {
+ // Grid specific rules
+ display: grid;
+ grid-template-columns: minmax(0, 1fr) repeat(var(--columns), auto);
+ &:has(> li > .visual) {
+ grid-template-columns: auto minmax(0, 1fr) repeat(var(--columns), auto);
+ }
- .visual {
- width: 2.5em;
- padding: .5em 0;
- margin-top: -.5em;
- margin-bottom: -.5em;
+ > li {
+ display: contents;
+
+ &.item-layout .main {
+ // Usually, the parent is flex, but here it's contents. .main is still stretched though,
+ // because it's a grid item with a width of 1fr. But the default-item-layout sets a width
+ // which needs to be overridden.
+ width: auto;
}
- .column-content {
- flex: 1 1 auto;
- width: 0;
+ .col, &::before, &::after {
+ // The li might get a background on hover. Though, this won't be visible
+ // as it has no box model since we apply display:contents to it.
+ background-color: inherit;
+ }
+ }
+}
- > * {
- .text-ellipsis();
+:not(.dashboard) > .container > .content:has(> .item-table), // compat only, for Icinga Web (See #286)
+.content:has(> .item-table) {
+ padding-left: 0;
+ padding-right: 0;
+
+ > .item-table > .empty-state {
+ margin: 0 1em;
+ }
+
+ > ul.item-table {
+ // Again, since the li has no box model, it cannot have padding. So the first
+ // and last child need to get the left and right padding respectively.
+ // But we don't want to have a border that spans to the very right or left,
+ // so pseudo elements are required. We could add empty cells instead, but
+ // that would require hard coding the width here, which I'd like to avoid.
+
+ grid-template-columns: ~"auto minmax(0, 1fr) repeat(var(--columns), auto) auto";
+ &:has(> li > .visual) {
+ grid-template-columns: ~"auto auto minmax(0, 1fr) repeat(var(--columns), auto) auto";
+ }
+
+ > li.table-row {
+ &::before, &::after {
+ display: inline-block;
+ content: '\00a0';
+ width: 0;
+ margin-bottom: 1px;
+ }
+
+ &::before {
+ padding-left: 1em;
+ }
+
+ &::after {
+ padding-right: 1em;
}
}
}
-
- .col {
- white-space: nowrap;
- }
-}
-
-ul.item-table {
- display: grid;
-
- > .table-row {
- .col:not(.title) {
- display: grid;
- align-items: center;
- }
- }
}
ul.item-table {
+ // General rules
padding: 0;
margin: 0;
+
+ .table-row {
+ .col {
+ margin-right: 0; // Otherwise background has gaps
+ padding: .5em 1em .5em 0;
+ &:last-child {
+ padding-right: 0;
+ }
+
+ .title {
+ margin-right: 0;
+ }
+ }
+
+ // This is for the legacy layout only
+ // TODO: Drop this together with BaseTableRowItem
+ .col.title:has(> .visual) {
+ display: flex;
+
+ > .visual {
+ padding-right: .5em;
+ }
+ }
+
+ &:not(:last-of-type) {
+ .col {
+ border-bottom: 1px solid @list-item-separation-bg;
+
+ &.visual {
+ border-color: @default-bg;
+ }
+ }
+ }
+ }
}
div.item-table {
@@ -85,11 +122,10 @@ div.item-table {
}
}
-div.table-row {
- display: flex;
- column-gap: 1em;
-
- .title {
- flex: 1 1 auto;
+@media print {
+ .item-table li.page-break-follows:not(:last-of-type) {
+ .col {
+ border-bottom: none;
+ }
}
}
diff --git a/asset/css/list/list-item.less b/asset/css/list/list-item.less
index 41b66ff..2b878f4 100644
--- a/asset/css/list/list-item.less
+++ b/asset/css/list/list-item.less
@@ -1,8 +1,6 @@
// Style
.list-item {
- color: @default-text-color-light;
-
&:not(:first-child) > .main {
border-top: 1px solid @list-item-separation-bg;
}
@@ -10,40 +8,6 @@
&:not(:first-child) .visual {
margin-top: 1px;
}
-
- .caption {
- i {
- opacity: 0.8;
- }
-
- a {
- color: @default-text-color;
- }
- }
-
- .title {
- .subject {
- color: @default-text-color;
- }
-
- a {
- color: @default-text-color;
- font-weight: bold;
-
- &:hover {
- color: @list-item-title-hover-color;
- text-decoration: none;
-
- .subject {
- color: @list-item-title-hover-color;
- }
- }
- }
- }
-
- footer {
- padding-top: .5em;
- }
}
@media print {
@@ -56,34 +20,10 @@
// Layout
-.list-item {
+.list-item.item-layout {
+ .main,
.visual {
- padding: .5em 0;
- width: 2.5em;
- }
-
- .caption {
- p {
- display: inline-block;
- }
- }
-
- .title {
- margin-right: 1em;
-
- p {
- margin: 0;
- }
- }
-
- time {
- white-space: nowrap;
- }
-
- footer {
- > * {
- font-size: .857em;
- line-height: 1.5*.857em;
- }
+ padding-top: .5em;
+ padding-bottom: .5em;
}
}
diff --git a/asset/css/mixin/mixins.less b/asset/css/mixin/mixins.less
index 58b9567..e82fb37 100644
--- a/asset/css/mixin/mixins.less
+++ b/asset/css/mixin/mixins.less
@@ -39,3 +39,8 @@
.monospace-font() {
font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace;
}
+
+.user-select(@user-select) {
+ -webkit-user-select: @user-select;
+ user-select: @user-select;
+}
diff --git a/asset/css/schedule-element.less b/asset/css/schedule-element.less
index 1905a05..807b87a 100644
--- a/asset/css/schedule-element.less
+++ b/asset/css/schedule-element.less
@@ -19,7 +19,7 @@
}
&:disabled {
- color: @schedule-element-fields-disabled-color;
+ color: var(--schedule-element-fields-disabled-color, @schedule-element-fields-disabled-color);
}
}
}
@@ -39,7 +39,7 @@
.monthly, .ordinal:not(.annually) {
padding: .5em;
margin-left: -.5em;
- border: 1px solid @schedule-element-fields-border-color;
+ border: 1px solid var(--schedule-element-fields-border-color, @schedule-element-fields-border-color);
.rounded-corners(.75em);
}
@@ -56,13 +56,13 @@
pointer-events: none;
label {
- color: @schedule-element-fields-disabled-color;
- background-color: @schedule-element-fields-disabled-bg;
+ color: var(--schedule-element-fields-disabled-color, @schedule-element-fields-disabled-color);
+ background-color: var(--schedule-element-fields-disabled-bg, @schedule-element-fields-disabled-bg);
}
input:checked + label {
- background: @schedule-element-fields-disabled-selected-bg;
- color: @schedule-element-fields-disabled-color;
+ background: var(--schedule-element-fields-disabled-selected-bg, @schedule-element-fields-disabled-selected-bg);
+ color: var(--schedule-element-fields-disabled-color, @schedule-element-fields-disabled-color);
}
}
@@ -75,11 +75,11 @@
cursor: pointer;
text-align: center;
padding: .75em 0;
- background: @schedule-element-fields-bg;
- color: @schedule-element-fields-color;
+ background: var(--schedule-element-fields-bg, @schedule-element-fields-bg);
+ color: var(--schedule-element-fields-color, @schedule-element-fields-color);
&:hover {
- background-color: @schedule-element-fields-hover-bg;
+ background-color: var(--schedule-element-fields-hover-bg, @schedule-element-fields-hover-bg);
}
&:focus {
@@ -88,27 +88,27 @@
}
input:checked + label {
- background-color: @schedule-element-fields-selected-bg;
- color: @schedule-element-fields-selected-color;
+ background-color: var(--schedule-element-fields-selected-bg, @schedule-element-fields-selected-bg);
+ color: var(--schedule-element-fields-selected-color, @schedule-element-fields-selected-color);
}
input:checked + label:hover {
- background-color: @schedule-element-fields-selected-hover-bg;
- border-color: @schedule-element-fields-selected-hover-bg;
+ background-color: var(--schedule-element-fields-selected-hover-bg, @schedule-element-fields-selected-hover-bg);
+ border-color: var(--schedule-element-fields-selected-hover-bg, @schedule-element-fields-selected-hover-bg);
}
}
&.multiple-fields {
li:not(:last-child) label {
- border-right: 1px solid @schedule-element-fields-border-color;
+ border-right: 1px solid var(--schedule-element-fields-border-color, @schedule-element-fields-border-color);
}
input:focus + label {
- box-shadow: inset 0 0 0 3px @schedule-element-fields-outline-color;
+ box-shadow: inset 0 0 0 3px var(--schedule-element-fields-outline-color, @schedule-element-fields-outline-color);
}
input:checked:focus + label {
- box-shadow: inset 0 0 0 3px @schedule-element-fields-selected-outline-color;
+ box-shadow: inset 0 0 0 3px var(--schedule-element-fields-selected-outline-color, @schedule-element-fields-selected-outline-color);
}
}
@@ -128,7 +128,7 @@
}
&:focus-within {
- outline: 3px solid @schedule-element-fields-outline-color;
+ outline: 3px solid var(--schedule-element-fields-outline-color, @schedule-element-fields-outline-color);
outline-offset: 2px;
}
@@ -137,7 +137,7 @@
}
input:checked + label:hover {
- background-color: @schedule-element-fields-selected-bg;
+ background-color: var(--schedule-element-fields-selected-bg, @schedule-element-fields-selected-bg);
}
}
}
@@ -145,20 +145,17 @@
.note {
display: none;
padding: .5em;
- background: @schedule-element-keyboard-note-bg;
+ background: var(--schedule-element-keyboard-note-bg, @schedule-element-keyboard-note-bg);
.rounded-corners(.25em);
text-align: center;
margin-top: 1em;
line-height: 1.25;
}
- /* .weekly */
- .weekly { }
-
/* .monthly styles */
.monthly {
li label {
- border-top: 1px solid @schedule-element-fields-border-color;
+ border-top: 1px solid var(--schedule-element-fields-border-color, @schedule-element-fields-border-color);
}
li:first-child,
@@ -189,14 +186,13 @@
li:nth-child(4n) label {
margin-right: 0;
}
+ }
- .toggle-slider-controls {
- display: flex;
- column-gap: 1em;
- align-items: center;
- margin-top: 1em;
- margin-bottom: -.6em;
- }
+ .toggle-slider-controls {
+ display: flex;
+ column-gap: 1em;
+ align-items: center;
+ margin-bottom: -.6em;
}
}
@@ -205,6 +201,6 @@
padding-top: 0.5625em;
p {
- color: @schedule-element-fields-disabled-color;
+ color: var(--schedule-element-fields-disabled-color, @schedule-element-fields-disabled-color);
}
}
diff --git a/asset/css/search-bar.less b/asset/css/search-bar.less
index 6ad1aec..deb5f9e 100644
--- a/asset/css/search-bar.less
+++ b/asset/css/search-bar.less
@@ -11,8 +11,8 @@
}
// Submit button styles
- input[type=submit],
- button[type=submit],
+ input[type="submit"],
+ button[type="submit"],
button:not([type]) {
background: var(--primary-button-bg, @primary-button-bg);
color: var(--primary-button-color, @primary-button-color);
@@ -26,20 +26,20 @@
}
// Hide the submit button, it must exist, but shouldn't be shown to the user
- input[type=submit][value="hidden"] {
+ input[type="submit"][value="hidden"] {
display: none;
}
// Left-most search dropdown style
button.search-options {
- i.icon:before {
+ i.icon::before {
font-size: 1.2em;
margin-right: 0;
color: var(--control-color, @control-color);
}
&:disabled {
- i.icon:before {
+ i.icon::before {
color: var(--control-disabled-color, @control-disabled-color);
}
}
@@ -52,7 +52,7 @@
background-color: var(--search-condition-remove-bg, @search-condition-remove-bg);
color: var(--search-condition-remove-color, @search-condition-remove-color);
- &:after {
+ &::after {
content: "";
position: absolute;
width: .4em;
@@ -77,7 +77,7 @@
.terms > .filter-condition:first-child button {
border-radius: 0 .4em .4em 0;
- &:before {
+ &::before {
content: "";
position: absolute;
width: .4em;
@@ -92,14 +92,14 @@
border-bottom-right-radius: .4em;
}
- &:after {
+ &::after {
content: none;
}
}
- .logical_operator,
- .grouping_operator_open,
- .grouping_operator_close {
+ .logical-operator,
+ .grouping-operator-open,
+ .grouping-operator-close {
input {
.rounded-corners();
background-color: var(--search-logical-operator-bg, @search-logical-operator-bg);
@@ -108,9 +108,9 @@
}
.operator,
- .logical_operator,
- .grouping_operator_open,
- .grouping_operator_close {
+ .logical-operator,
+ .grouping-operator-open,
+ .grouping-operator-close {
input {
text-align: center;
}
@@ -153,7 +153,7 @@
li {
display: inline;
- &:not(:first-of-type):before {
+ &:not(:first-of-type)::before {
display: inline;
content: ', ';
}
@@ -193,12 +193,12 @@
left: ~"calc(-2em - 2px)"; // That's min-width + margin-right of an operator
line-height: 16/12; // 16 (px) desired / default font size (px)
- i:before {
+ i::before {
margin-right: 0;
}
}
- &:not(._hover_delay):hover button {
+ &:not([data-hover-delay]):hover button {
display: inline;
}
}
@@ -210,9 +210,9 @@
}
label {
- &.logical_operator,
- &.grouping_operator_open,
- &.grouping_operator_close {
+ &.logical-operator,
+ &.grouping-operator-open,
+ &.grouping-operator-close {
margin-left: 1px; // adds up to 2px with the previous term
margin-right: 2px;
}
diff --git a/asset/css/search-base.less b/asset/css/search-base.less
index 416ee31..50e7fc7 100644
--- a/asset/css/search-base.less
+++ b/asset/css/search-base.less
@@ -58,20 +58,29 @@ fieldset:disabled .term-input-area [data-drag-initiator] {
cursor: not-allowed;
}
-.invalid-reason {
- padding: .25em;
- .rounded-corners(.25em);
- border: 1px solid black;
- font-weight: bold;
- background: var(--search-term-invalid-reason-bg, @search-term-invalid-reason-bg);
+.term-input-area {
+ .invalid-reason {
+ padding: .25em;
+ .rounded-corners(.25em);
+ border: 1px solid black;
+ font-weight: bold;
+ background: var(--search-term-invalid-reason-bg, @search-term-invalid-reason-bg);
- opacity: 0;
- visibility: hidden;
- transition: opacity 2s, visibility 2s;
- &.visible {
- opacity: 1;
- visibility: visible;
- transition: none;
+ opacity: 0;
+ visibility: hidden;
+ transition: opacity 2s, visibility 2s;
+
+ &.visible {
+ opacity: 1;
+ visibility: visible;
+ transition: none;
+ }
+ }
+
+ .remove-action {
+ background: var(--search-term-remove-action-bg, @search-term-remove-action-bg);
+ color: var(--search-term-remove-action-color, @search-term-remove-action-color);
+ .rounded-corners(0.25em);
}
}
@@ -153,12 +162,15 @@ fieldset:disabled .term-input-area [data-drag-initiator] {
// Layout
.search-bar .filter-input-area,
.term-input-area:not(.vertical) {
+ --term-padding-v: .25em;
+ --term-padding-h: .5em;
+
overflow: auto hidden;
- overflow-x: overlay; // Not invalid, but proprietary feature by chrome/webkit
display: flex;
flex-wrap: nowrap;
width: 100%;
- height: ~"calc(2em + 10px)"; // Search bar height + approximate scrollbar height
+ // input line-height + (input vertical padding * 2) + approximate scrollbar height
+ height: ~"calc(20px + calc(var(--term-padding-v) * 2) + 10px)";
// Lets inputs grow based on their contents, Inspired by https://css-tricks.com/auto-growing-inputs-textareas/
label {
@@ -170,7 +182,7 @@ fieldset:disabled .term-input-area [data-drag-initiator] {
&::after,
input {
width: auto;
- padding: .25em .5em;
+ padding: var(--term-padding-v) var(--term-padding-h);
resize: none;
}
@@ -208,6 +220,11 @@ fieldset:disabled .term-input-area [data-drag-initiator] {
margin-right: 1px;
}
}
+
+ &.read-only [data-index] .remove-action {
+ line-height: 20/12;
+ padding: var(--term-padding-v) var(--term-padding-h);
+ }
}
.term-input-area.vertical {
@@ -278,7 +295,6 @@ fieldset:disabled .term-input-area [data-drag-initiator] {
position: relative;
input {
- padding-left: 1.5em;
text-align: center;
cursor: pointer;
@@ -305,6 +321,36 @@ fieldset:disabled .term-input-area [data-drag-initiator] {
top: 85%;
left: .5em;
}
+
+ .remove-action {
+ display: flex;
+ align-items: center;
+ visibility: visible;
+ position: absolute;
+ width: 100%;
+ top: 0;
+ line-height: normal;
+ padding: 0.5em;
+ cursor: pointer;
+
+ i.icon {
+ margin-left: auto;
+ }
+
+ .remove-action-label {
+ margin-right: auto;
+ .text-ellipsis();
+ }
+ }
+
+ input:invalid ~ .remove-action,
+ input.invalid ~ .remove-action {
+ pointer-events: none;
+ }
+
+ &:not(:hover) .remove-action {
+ visibility: hidden;
+ }
}
}
}
@@ -324,7 +370,7 @@ fieldset:disabled .term-input-area [data-drag-initiator] {
padding: 0;
li.suggestion-title {
- padding: 1.25em .625em 0 .625em;
+ padding: 1.25em .625em 0;
}
li.failure-message {
diff --git a/asset/css/search-editor.less b/asset/css/search-editor.less
index d32d31c..d1959ae 100644
--- a/asset/css/search-editor.less
+++ b/asset/css/search-editor.less
@@ -28,7 +28,7 @@
.rounded-corners(0);
}
- i.icon:before {
+ i.drag-initiator.icon::before {
color: var(--search-editor-control-color, @search-editor-control-color);
}
@@ -36,6 +36,10 @@
cursor: grab;
}
+ .remove-button {
+ color: var(--search-editor-remove-control-color, @search-editor-remove-control-color);
+ }
+
input[type="text"], select {
border: none;
background: var(--search-term-bg, @search-term-bg);
@@ -81,50 +85,6 @@
}
}
- .buttons {
- ul {
- .rounded-corners();
- .box-shadow(0, 0, .5em);
- border: 1px solid var(--search-editor-context-menu-border-color, @search-editor-context-menu-border-color);
- background: var(--search-editor-context-menu-bg, @search-editor-context-menu-bg);
-
- li:not(:first-child) {
- border-top: 1px solid var(--search-editor-context-menu-border-color, @search-editor-context-menu-border-color);
- }
-
- button:hover {
- background: var(--primary-button-bg, @primary-button-bg);
- color: var(--primary-button-color, @primary-button-color);
- }
-
- // Add rounded corners to buttons as well, otherwise their
- // background is not rounded and overlaps the list's corners
- :first-child button {
- .rounded-corners();
- border-bottom-left-radius: 0;
- border-bottom-right-radius: 0;
- }
- :last-child button {
- .rounded-corners();
- border-top-left-radius: 0;
- border-top-right-radius: 0;
- }
-
- &:before {
- // The left pointing arrow
- border-bottom: 1px solid var(--search-editor-context-menu-border-color, @search-editor-context-menu-border-color);
- border-left: 1px solid var(--search-editor-context-menu-border-color, @search-editor-context-menu-border-color);
- background: var(--search-editor-context-menu-bg, @search-editor-context-menu-bg);
- }
- }
-
- &:hover i.icon:before {
- .rounded-corners();
- background: var(--primary-button-bg, @primary-button-bg);
- color: var(--primary-button-color, @primary-button-color);
- }
- }
-
input[type="submit"] {
.rounded-corners();
background: var(--primary-button-bg, @primary-button-bg);
@@ -156,17 +116,18 @@
li {
display: flex;
- > :not(:first-child) {
+ > .buttons {
margin-left: @item-spacing;
}
+
+ > select,
+ > fieldset {
+ margin-left: ~"calc(@{item-spacing} + var(--depth))";
+ }
}
ol {
- padding-left: 1em;
- padding-bottom: @item-spacing;
-
- > li:first-child,
- > :not(.filter-chain) + li {
+ > li {
margin-top: @item-spacing;
}
}
@@ -175,16 +136,13 @@
padding: 0 .5em;
}
- li > select {
- margin-right: auto;
- }
-
fieldset {
display: flex;
flex: 1 1 auto;
margin: 0;
padding: 0;
+ input[data-type="column"],
input[data-type="value"] {
flex: 1 1 auto;
}
@@ -202,55 +160,35 @@
margin-left: .5em;
}
- i.icon:before {
+ i.drag-initiator {
+ width: 1.5em; // Not a fan, but the only way to have a known width
+ }
+
+ li > ul:not(.buttons) > li:first-child:not(:has(.drag-initiator)),
+ ol > li:not(:has(.drag-initiator)) {
+ padding-left: 1.5em;
+ }
+
+ i.icon::before {
margin: 0;
font-size: 1.5em;
line-height: 1.5;
}
- .buttons {
- position: relative;
+ select + .buttons {
+ display: flex;
+ width: 100%;
- ul {
- position: absolute;
- right: 32/12em; // Target distance @ default font size / default font size
- z-index: 1;
- width: auto;
- padding: 0;
-
- display: none;
-
- button {
- z-index: 1;
- width: 100%;
- text-align: left;
- white-space: nowrap;
- }
-
- &:before {
- // The left pointing arrow
- content: "";
- display: block;
- height: 1em;
- transform: rotate(-135deg);
- width: 1em;
- z-index: 1;
-
- position: absolute;
- top: ((28/12)/2)-.5em; // ((First row pixels @ default font size / default font size) / 2) - own half width
- right: -.5em;
- }
- }
-
- &:hover ul {
- display: block;
- }
-
- i.icon:before {
- padding: ((28/18)-1)/2em; // (Container pixels / default font size) - line height / (padding-top,padding-bottom)
- line-height: 1;
+ > :last-child {
+ flex: 1 1 auto;
+ display: flex;
+ justify-content: flex-end;
}
}
+ fieldset + .buttons {
+ display: flex;
+ width: auto;
+ }
.cancel-button {
margin-top: 2em - @item-spacing;
diff --git a/asset/css/suggestion-element.less b/asset/css/suggestion-element.less
new file mode 100644
index 0000000..db6b89f
--- /dev/null
+++ b/asset/css/suggestion-element.less
@@ -0,0 +1,29 @@
+.suggestion-element-group {
+ display: inline-flex;
+
+ .suggestion-element,
+ .suggestion-element-icon {
+ line-height: normal;
+ height: 2.25em;
+ padding: 0.5em;
+ background-color: var(--default-input-bg, @default-input-bg);
+ color: var(--default-text-color, @default-text-color);
+ }
+
+ .suggestion-element {
+ border: none;
+ outline: none;
+ border-radius: 0 0.25em 0.25em 0;
+ }
+
+ .suggestion-element-icon {
+ padding-right: 0;
+ border-radius: 0.25em 0 0 0.25em;
+ }
+
+ &:focus-within {
+ border-radius: 0.25em;
+ outline: 3px solid var(--default-input-outline-color, @default-input-outline-color);
+ outline-offset: 1px;
+ }
+}
diff --git a/asset/css/variables.less b/asset/css/variables.less
index 322049c..1e0efbd 100644
--- a/asset/css/variables.less
+++ b/asset/css/variables.less
@@ -41,6 +41,12 @@
@default-text-color-light: fade(@default-text-color, 75%);
@default-text-color-inverted: @default-bg;
@default-input-bg: #404d72;
+@default-input-hover-bg: #434374;
+@default-input-outline-color: @base-primary-light;
+@default-remove-bg: @state-critical;
+@default-remove-color: @default-text-color-inverted;
+@default-delete-bg: @state-critical;
+@default-delete-color: @default-text-color-inverted;
@state-ok: #44bb77;
@state-up: @state-ok;
@@ -54,6 +60,7 @@
@primary-button-color: @default-text-color-inverted;
@primary-button-bg: @base-primary-bg;
@primary-button-hover-bg: @base-primary-dark;
+@link-hover-color: @base-primary-color;
@search-term-bg: @base-gray;
@search-term-color: @default-text-color-inverted;
@@ -66,6 +73,8 @@
@search-term-highlighted-bg: @base-primary-bg;
@search-term-highlighted-color: @default-text-color-inverted;
@search-term-drag-border-color: @base-gray;
+@search-term-remove-action-bg: @default-remove-bg;
+@search-term-remove-action-color: @default-remove-color;
@search-condition-remove-bg: @state-critical;
@search-condition-remove-color: @default-text-color-inverted;
@@ -78,9 +87,7 @@
@search-editor-error-color: @state-critical;
@search-editor-control-color: @base-gray-light;
-@search-editor-logical-op-bg: @base-gray-light;
-@search-editor-context-menu-border-color: @base-gray-light;
-@search-editor-context-menu-bg: @default-bg;
+@search-editor-remove-control-color: @state-critical;
@search-editor-drag-outline-color: @base-gray;
@control-color: @base-primary-color;
@@ -115,7 +122,7 @@
@schedule-element-fields-selected-bg: @primary-button-bg;
@schedule-element-fields-selected-color: @default-text-color-inverted;
@schedule-element-fields-hover-bg: @base-primary-light;
-@schedule-element-fields-outline-color: fade(@base-primary-bg, 50%);
+@schedule-element-fields-outline-color: @default-input-outline-color;
@schedule-element-fields-selected-outline-color: fade(#fff, 50%);
@schedule-element-fields-selected-hover-bg: @primary-button-hover-bg;
@schedule-element-fields-disabled-color: @base-gray;
@@ -126,7 +133,7 @@
@empty-state-color: @base-gray-semilight;
@empty-state-bar-bg: @base-gray-lighter;
-@list-item-title-hover-color: @base-primary-color;
+@list-item-title-hover-color: @link-hover-color;
@list-item-separation-bg: @base-gray-light;
@iplWebLightRules: {
@@ -143,10 +150,17 @@
--default-text-color-light: fade(#535353, 75%); // --default-text-color
--default-text-color-inverted: #F5F9FA;
--default-input-bg: #DEECF1;
+ --default-input-hover-bg: #C0CCCD;
+ --default-input-outline-color: @base-primary-light;
+ --default-remove-bg: var(--base-remove-bg);
+ --default-remove-color: var(--default-text-color-inverted);
+ --default-delete-bg: var(--base-remove-bg);
+ --default-delete-color: var(--default-text-color-inverted);
--primary-button-color: var(--default-text-color-inverted);
--primary-button-bg: @primary-button-bg;
--primary-button-hover-bg: @primary-button-hover-bg;
+ --link-hover-color: var(--base-primary-color);
--searchbar-bg: var(--default-input-bg);
--searchbar-scrollbar-bg: var(--base-gray-light);
@@ -162,6 +176,8 @@
--search-term-highlighted-bg: var(--primary-button-bg);
--search-term-highlighted-color: var(--default-text-color-inverted);
--search-term-drag-border-color: var(--base-gray);
+ --search-term-remove-action-bg: var(--default-remove-bg);
+ --search-term-remove-action-color: var(--default-remove-color);
--search-condition-remove-bg: var(--base-remove-bg);
--search-condition-remove-color: var(--default-text-color-inverted);
@@ -171,9 +187,6 @@
--search-editor-error-color: var(--base-remove-bg);
--search-editor-control-color: var(--base-gray-light);
- --search-editor-logical-op-bg: var(--base-gray-light);
- --search-editor-context-menu-border-color: var(--base-gray-light);
- --search-editor-context-menu-bg: var(--default-text-color-inverted);
--search-editor-drag-outline-color: var(--base-gray);
--control-color: var(--primary-button-bg);
@@ -203,7 +216,7 @@
--schedule-element-fields-selected-bg: var(--primary-button-bg);
--schedule-element-fields-selected-color: var(--default-text-color-inverted);
--schedule-element-fields-hover-bg: @base-primary-light;
- --schedule-element-fields-outline-color: fade(@base-primary-bg, 50%);
+ --schedule-element-fields-outline-color: @default-input-outline-color;
--schedule-element-fields-selected-outline-color: fade(#fff, 50%);
--schedule-element-fields-selected-hover-bg: var(--primary-button-hover-bg);
--schedule-element-fields-disabled-color: var(--base-gray);
@@ -214,7 +227,7 @@
--empty-state-color: var(--base-gray-semilight);
--empty-state-bar-bg: var(--base-gray-lighter);
- --list-item-title-hover-color: var(--base-primary-color);
+ --list-item-title-hover-color: var(--link-hover-color);
--list-item-separation-bg: var(--base-gray-light);
}
};
diff --git a/asset/js/iterator.js b/asset/js/iterator.js
new file mode 100644
index 0000000..2c78d9f
--- /dev/null
+++ b/asset/js/iterator.js
@@ -0,0 +1,96 @@
+(function (root, factory) {
+ "use strict";
+
+ if (typeof define === "function" && define.icinga) {
+ define(["exports"], factory);
+ } else {
+ factory(root.icingaIteratorPolyfill = root.icingaIteratorPolyfill || {});
+ }
+}(self, function (exports) {
+ /**
+ * Polyfill for `Iterator.filter`
+ *
+ * @param {Symbol.iterator} iterator
+ * @param {function} callback
+ * @returns {Generator<*, void, *>}
+ */
+ function* filter(iterator, callback) {
+ if (typeof iterator.filter === "function") {
+ yield* iterator.filter(callback);
+ }
+
+ for (const item of iterator) {
+ if (callback(item)) {
+ yield item;
+ }
+ }
+ }
+
+ /**
+ * Polyfill for `Iterator.find`
+ *
+ * @param {Symbol.iterator} iterator
+ * @param {function} callback
+ * @returns {*}
+ */
+ function find(iterator, callback) {
+ if (typeof iterator.find === "function") {
+ return iterator.find(callback);
+ }
+
+ for (const item of iterator) {
+ if (callback(item)) {
+ return item;
+ }
+ }
+ }
+
+ /**
+ * Polyfill for `Iterator.map`
+ *
+ * @param {Symbol.iterator} iterator
+ * @param {function} callback
+ * @returns {Generator<*, void, *>}
+ */
+ function* map(iterator, callback) {
+ if (typeof iterator.map === "function") {
+ yield* iterator.map(callback);
+ }
+
+ for (const item of iterator) {
+ yield callback(item);
+ }
+ }
+
+ /**
+ * Find the first key in the map whose value satisfies the provided testing function.
+ * @param {Map} map
+ * @param {function} callback Passed arguments are: value, key, map
+ * @returns {*} Returns undefined if no key satisfies the testing function.
+ */
+ function findKey(map, callback) {
+ for (const key of findKeys(map, callback)) {
+ return key;
+ }
+ }
+
+ /**
+ * Find all keys in the map whose value satisfies the provided testing function.
+ * @param {Map} map
+ * @param {function} callback Passed arguments are: value, key, map
+ * @returns {Generator<*, void, *>}
+ */
+ function* findKeys(map, callback) {
+ for (const [ key, value ] of map) {
+ if (callback(value, key, map)) {
+ yield key;
+ }
+ }
+ }
+
+ exports.findKeys = findKeys;
+ exports.findKey = findKey;
+ exports.filter = filter;
+ exports.find = find;
+ exports.map = map;
+}));
diff --git a/asset/js/widget/BaseInput.js b/asset/js/widget/BaseInput.js
index eca7371..360d502 100644
--- a/asset/js/widget/BaseInput.js
+++ b/asset/js/widget/BaseInput.js
@@ -632,7 +632,11 @@ define(["../notjQuery", "Completer"], function ($, Completer) {
let eventData = { submittedBy: input };
if (changeType === 'paste') {
// Ensure that what's pasted is also transmitted as value
- eventData['terms'] = this.termsToQueryString(data['terms']) + this.separator + data['input'];
+ if (data['terms'].length === 0) {
+ eventData['terms'] = data['input'];
+ } else {
+ eventData['terms'] = this.termsToQueryString(data['terms']) + this.separator + data['input'];
+ }
}
$(this.input.form).trigger('submit', eventData);
@@ -713,7 +717,14 @@ define(["../notjQuery", "Completer"], function ($, Completer) {
this.input.name = '';
// Set the hidden input's value, it's what's sent
- if (event.detail && 'terms' in event.detail) {
+ if (
+ event.detail
+ && 'terms' in event.detail
+ && (
+ ! ('submittedBy' in event.detail)
+ || event.detail.submittedBy === this.input
+ )
+ ) {
this.termInput.value = event.detail.terms;
} else {
let renderedTerms = this.termsToQueryString(this.usedTerms);
diff --git a/asset/js/widget/FilterInput.js b/asset/js/widget/FilterInput.js
index fad3da0..3f1d947 100644
--- a/asset/js/widget/FilterInput.js
+++ b/asset/js/widget/FilterInput.js
@@ -13,7 +13,7 @@ define(["../notjQuery", "BaseInput"], function ($, BaseInput) {
*
* @type {{}}
*/
- this.negationOperator = { label: '!', search: '!', class: 'logical_operator', type: 'negation_operator' };
+ this.negationOperator = { label: '!', search: '!', class: 'logical-operator', type: 'negation_operator' };
/**
* Supported grouping operators
@@ -21,8 +21,8 @@ define(["../notjQuery", "BaseInput"], function ($, BaseInput) {
* @type {{close: {}, open: {}}}
*/
this.grouping_operators = {
- open: { label: '(', search: '(', class: 'grouping_operator_open', type: 'grouping_operator' },
- close: { label: ')', search: ')', class: 'grouping_operator_close', type: 'grouping_operator' }
+ open: { label: '(', search: '(', class: 'grouping-operator-open', type: 'grouping_operator' },
+ close: { label: ')', search: ')', class: 'grouping-operator-close', type: 'grouping_operator' }
};
/**
@@ -33,8 +33,8 @@ define(["../notjQuery", "BaseInput"], function ($, BaseInput) {
* @type {{}[]}
*/
this.logical_operators = [
- { label: '&', search: '&', class: 'logical_operator', type: 'logical_operator', default: true },
- { label: '|', search: '|', class: 'logical_operator', type: 'logical_operator' },
+ { label: '&', search: '&', class: 'logical-operator', type: 'logical_operator', default: true },
+ { label: '|', search: '|', class: 'logical-operator', type: 'logical_operator' },
];
/**
@@ -958,7 +958,7 @@ define(["../notjQuery", "BaseInput"], function ($, BaseInput) {
label.dataset.type = termData.type;
if (! termData.class) {
- label.classList.add(termData.type);
+ label.classList.add(termData.type.replace('_', '-'));
}
if (termData.counterpart >= 0) {
@@ -1256,11 +1256,11 @@ define(["../notjQuery", "BaseInput"], function ($, BaseInput) {
let label = event.currentTarget;
if (['column', 'operator', 'value'].includes(label.dataset.type)) {
- // This adds a class to delay the remove button. If it's shown instantly upon hover
+ // This adds an attr to delay the remove button. If it's shown instantly upon hover
// it's too easy to accidentally click it instead of the desired grouping operator.
- label.parentNode.classList.add('_hover_delay');
+ label.parentNode.dataset.hoverDelay = "";
setTimeout(function () {
- label.parentNode.classList.remove('_hover_delay');
+ delete label.parentNode.dataset.hoverDelay;
}, 500);
}
diff --git a/asset/js/widget/SearchEditor.js b/asset/js/widget/SearchEditor.js
index b8235f0..81079a5 100644
--- a/asset/js/widget/SearchEditor.js
+++ b/asset/js/widget/SearchEditor.js
@@ -55,7 +55,7 @@ define(["../notjQuery", "../vendor/Sortable"], function ($, Sortable) {
if (! neighbour) {
// User dropped the rule into an empty group
placement = 'to';
- neighbour = event.to.closest('[id]');
+ neighbour = event.to.closest('li[id]');
}
}
diff --git a/asset/js/widget/TermInput.js b/asset/js/widget/TermInput.js
index 9e2d9de..c015469 100644
--- a/asset/js/widget/TermInput.js
+++ b/asset/js/widget/TermInput.js
@@ -187,8 +187,16 @@ define(["../notjQuery", "../vendor/Sortable", "BaseInput"], function ($, Sortabl
const label = super.renderTerm(termData, termIndex);
if (this.readOnly) {
+ const removeLabel = this.termContainer.dataset.removeActionLabel;
label.firstChild.readOnly = true;
- label.appendChild($.render(''));
+ label.appendChild(
+ $.render(
+ `
` +
+ '' +
+ `${ removeLabel }` +
+ '
'
+ )
+ );
label.appendChild($.render(''));
}
@@ -311,7 +319,12 @@ define(["../notjQuery", "../vendor/Sortable", "BaseInput"], function ($, Sortabl
}
onButtonClick(event) {
- if (! this.hasSyntaxError()) {
+ // Exchange terms only when an Enter key is pressed while not in the term input.
+ // If the pointerType is not empty, the click event is triggered by clicking the Submit button in the form,
+ // and the default submit event should not be prevented.
+ // The below solution does not work if the click event is triggered by pressing Space while on the Submit button.
+ // In which case the Submit button needs to be clicked again to trigger the form submission.
+ if (! this.hasSyntaxError() && event.pointerType === '') {
let addedTerms = this.exchangeTerm();
if (Object.keys(addedTerms).length) {
this.togglePlaceholder();
diff --git a/asset/static/font/icinga-icons/fonts/Icinga-Icons.svg b/asset/static/font/icinga-icons/fonts/Icinga-Icons.svg
index 6afa055..6d83116 100644
--- a/asset/static/font/icinga-icons/fonts/Icinga-Icons.svg
+++ b/asset/static/font/icinga-icons/fonts/Icinga-Icons.svg
@@ -19,4 +19,7 @@
+
+
+
\ No newline at end of file
diff --git a/asset/static/font/icinga-icons/fonts/Icinga-Icons.ttf b/asset/static/font/icinga-icons/fonts/Icinga-Icons.ttf
index c281593a40db08d087708ec4dd39920cf98f867f..1b1207d4c9b2010fa8150f756dd7a4e9f9e03380 100644
GIT binary patch
delta 1027
zcmbVLOH31C5T5Bmx3O64+Zd^Ke_MzNQ2N@c#0RN}&<90BVhn|*Rya^8X%EPypjSLd
z49P=;WvLk)zI~IserJ;K
z7=UhSD3!R;c&RN*E>&dr4-vtya_JHY
zmx$$JoNvbJaupR*oYp*3?M8NLU!e>Xi|(Kn^VCo!Gt@u>T%?kH%*@Olv&ZN0G0ttZ
zq19qG@jB$yOsH?ddZ*7To<-3w3JPg9DJ~wjLi)Ul3sbcu=jW3P3oYSbFlDQ&v!#N;
z@ZWl0tY@4tmS^KVvA%7f==g1MF*!S%#PrV1bj=3=^C_
zJ=2>kXOI_N{uZ>N-E2p_*Y6RWOi<^|Wb?RXgpcMl+H5p1=h+NPYaVG9%hGwy92bR%
zBizvuc0>d*j%zhM+NHHXbZO}{>fhjU*H#kWwMQ`?kX(TQ?B6be_7Y5B2R{`dsF~Zs
z>rJwtTt2C>9G<9Joo0
zid$1+6r%xEE)bP2udGB$rHE8g80ueQq7f+)iB}uiXhI|wycF%AG--#L6f=pw!HU6T
zk;mj;)4`4fF^~wWMIr|E-HL(5O-|1FedoLPo^#WB-?&UnL^|b2P+(-Vqtjbc;em33
zn2sf_lyCehPs9!2vAC5^Asb+swfOwfT-Wne4>(IywVjx?W?Jh8eMFvm^n(cqYEfK*
zqu`cAGLsFGxCUpy=KNwTWYyjoPY@0vG$pNUiW+DKd;|6`SjpL=wTl<Y$lcduNnyr0bfX_aIWiGs-4XZ)y|WTH0hJ!J*8
zAN91|F4j?(Jx)>NSYx=92wX$%sK#NygfN|5_c8OiGpTm4yW}Ee-^ptS3T`IwO1(3r
zpR%f!&=DJsr&{M`IVPh0wQg(5+xJGg3j)!@$7G5PR+Z{7?P#)_g+7g$Yh4|<46c4YQr=+3n!Hs$lOfU
z#)U0vND}-(Y7tV4m~ztugGehEAuU>kEkbBf5ClT_?A-VK3EV{Qz3<+0zH{z9_ndop
z&&6kM+wEvu8v%lkxsDjvT=R)QUJz^#PndIu6Y2OcA&^4;3WL3S?eRc7!?+^q6+5UN
z7`$^6xfMc8lMGzXz425seuI$ePV@;dG+t`Wq>w~z0`)ouewq82N@qurdx3h0p%sV0
zp#=Ixsy9(S&TwSSv7U~PVqoDI>KcxcgvjqG644PNomOjr!#{DA%#Xu2U#a`T@5(=Q<9qTL_h45pn9A+~
zR%*MX3*(BZ@=i^;%9RS=%ijW&3XA+HC@+=aVG5rsUg`E$P8r?-Q&h{fLk7rUDq3V>
z#KK&}l>O97tzN6w@AXs8V|RevX0`Ap;Pq6jKMD12zfU?3Qa}<_(rQs%ydIVG`&1XI
zYfj9~CFbXw!@*$EQCsUs27}?h<=$A=7^O5v$GT#@JBlj9kA;QA%uE8>4ldF*=%5D{
zX&VqNnQwRnHN-|5Fc~Vk{Q?y%wzI%XO@U^xgVX8+!58p~ZYt_?R|ZRN9)9q7apJSvjg)URsJ2ixH)$%c|toq>MHRyOwn&qGxfo
zvA^ovFJd;Zt|sKGS^2#?=O;{3SnYPzgabA-VSfLMM^&Oxzog&fwO@m|&`_noAA$t&
AvH$=8
delta 574
zcmZ3Ywn9m)+~3WOfsp|S1T`4ALA1af2FA&P!om|Z#p?Nza}x^~7#K5v;vpa`9(HL`
zdSWq1Y!8sn0mTC8IhAQZu_Fu&JPSbBbQvm@j7JmQ(=64gmQMAZ*6Kd^smS8K};WAIN7=0%74>0#9-iD}WaBgET6Du?)k)
zyu{p8pqLBL@XXKvj!{`kpXD}K#0fj+;
ziGjh~k`crL6CefwF)juNpos^V8zyrxJ!E%aZ~(F$CVygT1hN%??1afx%)LN1Sj}cW
zmIg)+MxZJtU!baKtN|R1K0r<+v%}_hth*T*_itXsuFuH&pM`;G&E|U?8<~JQGk~T@
zY@Wuwmywb1H*$~O};RCa*2SsqX0x4
xED7=q1CZ~4iWz}?MjwzmGz?P5KKX}$k`Pc1WT61Vd`Q}0U;?F#&CY@k837J2W`Y0!
diff --git a/asset/static/font/icinga-icons/selection.json b/asset/static/font/icinga-icons/selection.json
index 015faf0..b97abba 100644
--- a/asset/static/font/icinga-icons/selection.json
+++ b/asset/static/font/icinga-icons/selection.json
@@ -1 +1 @@
-{"IcoMoonType":"selection","icons":[{"icon":{"paths":["M64 0h896c35.328 0 64 28.672 64 64v640c0 35.328-28.672 64-64 64h-350.72v-64h350.72v-640h-896v640h33.28v64h-33.28c-35.328 0-64-28.672-64-64v-640c0-35.328 28.672-64 64-64z","M576.048 481.122c0 123.698-100.277 223.976-223.976 223.976s-223.976-100.277-223.976-223.976c0-123.698 100.277-223.976 223.976-223.976s223.976 100.277 223.976 223.976z","M511.488 720.896l64 303.104-224.32-128-223.168 128 64-303.488c45.76 30.656 100.8 48.576 160 48.576 58.944 0 113.792-17.728 159.488-48.192z","M896 192c0-16.96-6.784-33.28-18.752-45.248-12.032-12.032-28.288-18.752-45.248-18.752-71.040 0-185.024 0-256 0-17.024 0-33.28 6.72-45.248 18.752-12.032 11.968-18.752 28.288-18.752 45.248s6.72 33.28 18.752 45.248c11.968 12.032 28.224 18.752 45.248 18.752 70.976 0 184.96 0 256 0 16.96 0 33.216-6.72 45.248-18.752 11.968-11.968 18.752-28.288 18.752-45.248z","M896 384c0-16.96-6.784-33.28-18.752-45.248-12.032-12.032-28.288-18.752-45.248-18.752-71.040 0-57.024 0-128 0-17.024 0-33.28 6.72-45.248 18.752-12.032 11.968-18.752 28.288-18.752 45.248s6.72 33.28 18.752 45.248c11.968 12.032 28.224 18.752 45.248 18.752 70.976 0 56.96 0 128 0 16.96 0 33.216-6.72 45.248-18.752 11.968-11.968 18.752-28.288 18.752-45.248z"],"attrs":[],"grid":0,"tags":["certificate"]},"attrs":[],"properties":{"order":18,"id":11,"name":"certificate","prevSize":32,"code":59654},"setIdx":0,"setId":1,"iconIdx":0},{"icon":{"paths":["M7.232 90.496c11.776-24.896 36.672-40.704 64.192-40.704h768c27.584 0 52.48 15.808 64.192 40.704s8.192 54.208-9.216 75.52l-189.376 231.488c-142.592 29.312-249.6 155.392-249.6 306.496 0 48.704 11.2 94.912 31.104 136-2.816-1.408-5.696-3.2-8.32-5.184l-113.792-85.312c-14.4-10.688-22.784-27.52-22.784-45.504v-140.608l-325.312-397.504c-17.216-21.184-20.992-50.688-9.088-75.392z","M1024 705.024c-2.176 72.512-27.456 132.992-75.84 181.504-48.384 48.576-108.672 73.344-180.992 74.496-72.256-1.152-132.288-25.92-180.096-74.496-47.808-48.512-72.832-108.992-75.072-181.504 2.24-72.512 27.264-133.056 75.072-181.568s107.84-73.344 180.096-74.432c72.32 1.088 132.608 25.92 180.992 74.432s73.664 109.056 75.84 181.568zM966.144 581.248c-0.512-0.704-1.088-1.344-1.728-1.92-22.656-22.72-59.52-22.72-82.176 0l-80.448 80.32-33.024 76.608c0 0-25.6-65.728-25.6-65.728l-29.312-29.312c-22.656-22.656-59.52-22.656-82.176 0-22.72 22.72-22.72 59.52 0 82.24l94.272 94.272c11.2 11.2 25.856 16.832 40.512 16.96 0.448 0 0.896 0 1.28 0 14.656-0.192 29.248-5.824 40.384-16.96l156.224-156.224c22.016-22.016 22.656-57.472 1.792-80.256z"],"attrs":[],"grid":0,"tags":["filter-check-circle"]},"attrs":[],"properties":{"order":15,"id":10,"name":"filter-check-circle","prevSize":32,"code":59659},"setIdx":0,"setId":1,"iconIdx":1},{"icon":{"paths":["M177.038 607.479c-5.88 0.539-12.299 0.833-19.306 0.833-22.54 0-43.317-4.018-62.378-12.103-19.061-8.036-35.672-19.453-49.883-34.202-14.259-14.749-25.382-32.34-33.418-52.725s-12.103-43.072-12.103-68.013c0-24.941 4.165-47.727 12.495-68.405s19.6-38.22 33.81-52.725c14.21-14.504 30.968-25.48 50.324-33.026 19.306-7.497 40.23-11.27 62.77-11.27 20.384 0 40.671 3.92 60.761 11.711 20.139 7.742 36.358 19.159 48.707 34.202l-48.266 52.333c-6.468-10.241-15.043-17.591-25.774-22.148s-22.001-6.86-33.81-6.86c-11.809 0-22.932 2.401-33.418 7.252-10.437 4.851-19.453 11.515-26.95 20.139-7.497 8.575-13.279 18.767-17.297 30.576s-6.076 24.696-6.076 38.613c0 13.965 2.058 26.999 6.076 39.054 4.018 12.103 9.8 22.295 17.297 30.576 7.497 8.33 16.219 14.896 26.166 19.747 9.898 4.802 21.070 7.252 33.369 7.252 13.965 0 26.313-2.989 37.044-8.869 8.575-4.851 15.827-11.025 21.756-18.522l-41.896 96.58z","M484.864 594.112l-18.752-49.408h-123.2l-23.296 63.616h-82.944l132.8-321.984h74.88l90.688 222.4c-21.632 25.92-38.336 54.336-50.176 85.376zM405.696 372.48l-40.192 110.272h79.68l-39.488-110.272z","M1024 705.024c-2.176 72.512-27.456 132.992-75.84 181.504-48.384 48.576-108.672 73.344-180.992 74.496-72.256-1.152-132.288-25.92-180.096-74.496-47.808-48.512-72.832-108.992-75.072-181.504 2.24-72.512 27.264-133.056 75.072-181.568s107.84-73.344 180.096-74.432c72.32 1.088 132.608 25.92 180.992 74.432s73.664 109.056 75.84 181.568zM966.144 581.248c-0.512-0.704-1.088-1.344-1.728-1.92-22.656-22.72-59.52-22.72-82.176 0l-80.448 80.32-33.024 76.608c0 0-25.6-65.728-25.6-65.728l-29.312-29.312c-22.656-22.656-59.52-22.656-82.176 0-22.72 22.72-22.72 59.52 0 82.24l94.272 94.272c11.2 11.2 25.856 16.832 40.512 16.96 0.448 0 0.896 0 1.28 0 14.656-0.192 29.248-5.824 40.384-16.96l156.224-156.224c22.016-22.016 22.656-57.472 1.792-80.256z"],"attrs":[],"grid":0,"tags":["filter-circle-check"]},"attrs":[],"properties":{"order":16,"id":9,"name":"ca-circle-check","prevSize":32,"code":59656},"setIdx":0,"setId":1,"iconIdx":2},{"icon":{"paths":["M319.936 448h384v257.088h-384v-257.088z","M383.936 416v-96c0-35.328 28.672-64 64-64h128c35.328 0 64 28.672 64 64v96h-256zM575.936 320h-128v96h128v-96z","M192.448 724.864c68.864 103.168 186.368 171.136 319.552 171.136 141.568 0 265.344-76.8 331.904-190.912h142.4c-76.288 187.008-260.032 318.912-474.304 318.912-180.544 0-339.392-93.632-430.592-235.008l-81.536 47.104 2.112-324.096 281.472 160.384-91.008 52.48zM833.472 302.080c-68.544-104.832-187.008-174.080-321.472-174.080-167.040 0-309.376 106.944-362.112 256h-133.76c56.896-220.736 257.472-384 495.872-384 181.824 0 341.632 94.976 432.448 237.952l79.68-45.952-2.112 324.096-281.472-160.384 92.928-53.632z"],"attrs":[],"grid":0,"tags":["refresh-cert"]},"attrs":[],"properties":{"order":17,"id":8,"name":"refresh-cert","prevSize":32,"code":59657},"setIdx":0,"setId":1,"iconIdx":3},{"icon":{"paths":["M64.491 787.398c0 19.125 6.694 35.381 20.081 48.768s29.644 20.081 48.768 20.081h30.6c19.125 0 35.381-6.694 48.768-20.081s20.081-29.644 20.081-48.768c0-19.125-6.694-35.381-20.081-48.768s-29.644-20.081-48.768-20.081h-30.6c-19.125 0-35.381 6.694-48.768 20.081s-20.081 29.644-20.081 48.768zM64.491 512c0 19.125 6.694 35.381 20.081 48.768s29.644 20.081 48.768 20.081h30.6c19.125 0 35.381-6.694 48.768-20.081s20.081-29.644 20.081-48.768c0-19.125-6.694-35.381-20.081-48.768s-29.644-20.081-48.768-20.081h-30.6c-19.125 0-35.381 6.694-48.768 20.081s-20.081 29.644-20.081 48.768zM64.491 236.602c0 19.125 6.694 35.381 20.081 48.768s29.644 20.081 48.768 20.081h30.6c19.125 0 35.381-6.694 48.768-20.081s20.081-29.644 20.081-48.768c0-19.125-6.694-35.381-20.081-48.768s-29.644-20.081-48.768-20.081h-30.6c-19.125 0-35.381 6.694-48.768 20.081s-20.081 29.644-20.081 48.768zM288.252 787.398c0 19.125 6.694 35.381 20.081 48.768s29.644 20.081 48.768 20.081h534.54c19.125 0 35.381-6.694 48.768-20.081s20.081-29.644 20.081-48.768c0-19.125-6.694-35.381-20.081-48.768s-29.644-20.081-48.768-20.081h-534.54c-19.125 0-35.381 6.694-48.768 20.081s-20.081 29.644-20.081 48.768zM288.252 512c0 19.125 6.694 35.381 20.081 48.768s29.644 20.081 48.768 20.081h534.54c19.125 0 35.381-6.694 48.768-20.081s20.081-29.644 20.081-48.768c0-19.125-6.694-35.381-20.081-48.768s-29.644-20.081-48.768-20.081h-534.54c-19.125 0-35.381 6.694-48.768 20.081s-20.081 29.644-20.081 48.768zM288.252 236.602c0 19.125 6.694 35.381 20.081 48.768s29.644 20.081 48.768 20.081h534.54c19.125 0 35.381-6.694 48.768-20.081s20.081-29.644 20.081-48.768c0-19.125-6.694-35.381-20.081-48.768s-29.644-20.081-48.768-20.081h-534.54c-19.125 0-35.381 6.694-48.768 20.081s-20.081 29.644-20.081 48.768z"],"attrs":[],"grid":0,"tags":["th-list"]},"attrs":[],"properties":{"order":11,"id":7,"name":"th-list","prevSize":32,"code":59658},"setIdx":0,"setId":1,"iconIdx":4},{"icon":{"paths":["M574.496 81.411l45.262 8.286-149.128 422.304-45.261-8.286 149.126-422.304z","M896.001 369.329v29.341l-379.111 128.001-9.78-29.341 388.891-128.001z","M656 768v43.787l-164.906-224.295 41.812-23.571 123.093 204.079z","M205.566 845.588l-27.131-27.175 205.565-242.414 63.999 13.589-242.434 255.999z","M192.001 320.001l-38.798-52.36 308.952 225.624-28.309 38.763-241.845-212.028z","M576.418 0.897c75.061 0 136.002 60.94 136.002 136s-60.941 136-136.002 136c-75.058 0-135.999-60.94-135.999-136s60.941-136 135.999-136z","M911.998 272.897c61.815 0 111.999 50.187 111.999 112 0 61.816-50.185 112-111.999 112s-111.999-50.184-111.999-112c0-61.813 50.185-112 111.999-112z","M656 719.998c44.154 0 80.002 35.85 80.002 80.001 0 44.155-35.848 80.001-80.002 80.001-44.15 0-79.998-35.846-79.998-80.001 0-44.151 35.848-80.001 79.998-80.001z","M143.999 735.999c79.478 0 144.002 64.526 144.002 144.002s-64.524 143.999-144.002 143.999c-79.475 0-143.999-64.524-143.999-143.999s64.524-144.002 143.999-144.002z","M139.048 191.022c52.984 0 96.001 43.016 96.001 96.001 0 52.982-43.018 95.998-96.001 95.998s-95.998-43.016-95.998-95.998c0-52.985 43.014-96.001 95.998-96.001z","M448 319.706c105.968 0 192 86.034 192 192.001s-86.032 191.999-192 191.999c-105.968 0-192-86.032-192-191.999s86.032-192.001 192-192.001z"],"attrs":[],"grid":0,"tags":["icinga"]},"attrs":[],"properties":{"order":10,"id":6,"name":"icinga","prevSize":32,"code":59655},"setIdx":0,"setId":1,"iconIdx":5},{"icon":{"paths":["M192.009 128.005c0 35.361-28.665 64.026-64.026 64.026s-64.026-28.665-64.026-64.026c0-35.361 28.665-64.026 64.026-64.026s64.026 28.665 64.026 64.026z","M192.009 320.329c0 35.361-28.665 64.026-64.026 64.026s-64.026-28.665-64.026-64.026c0-35.361 28.665-64.026 64.026-64.026s64.026 28.665 64.026 64.026z","M192.009 512.329c0 35.361-28.665 64.026-64.026 64.026s-64.026-28.665-64.026-64.026c0-35.361 28.665-64.026 64.026-64.026s64.026 28.665 64.026 64.026z","M320.006 96.003h640.004v64.005h-640.004v-64.005z","M320.006 480.326h640.004v64.005h-640.004v-64.005z","M320.006 288.326h640.004v64.005h-640.004v-64.005z","M320.006 672.326h640.004v64.005h-640.004v-64.005z","M320.006 864.326h640.004v64.005h-640.004v-64.005z","M192.009 704.652c0 35.361-28.665 64.026-64.026 64.026s-64.026-28.665-64.026-64.026c0-35.361 28.665-64.026 64.026-64.026s64.026 28.665 64.026 64.026z","M192.009 896.329c0 35.361-28.665 64.026-64.026 64.026s-64.026-28.665-64.026-64.026c0-35.361 28.665-64.026 64.026-64.026s64.026 28.665 64.026 64.026z"],"attrs":[],"grid":0,"tags":["list-view-minimal"]},"attrs":[],"properties":{"order":4,"id":5,"name":"list-view-minimal","prevSize":32,"code":59648},"setIdx":0,"setId":1,"iconIdx":6},{"icon":{"paths":["M320.007 128.321h639.993v191.358h-639.993v-191.358z","M320.007 384.003h639.993v63.992h-639.993v-63.992z","M256.014 223.683c0 53.041-42.998 96.039-96.039 96.039s-96.039-42.998-96.039-96.039c0-53.041 42.998-96.039 96.039-96.039s96.039 42.998 96.039 96.039z","M256.014 672.008c0 53.041-42.998 96.039-96.039 96.039s-96.039-42.998-96.039-96.039c0-53.041 42.998-96.039 96.039-96.039s96.039 42.998 96.039 96.039z","M320.007 575.996h639.993v192.005h-639.993v-192.005z","M320.007 831.995h639.993v63.992h-639.993v-63.992z"],"attrs":[],"grid":0,"tags":["list-view-detailed"]},"attrs":[],"properties":{"order":5,"id":4,"name":"list-view-detailed","prevSize":32,"code":59649},"setIdx":0,"setId":1,"iconIdx":7},{"icon":{"paths":["M256.015 192.008c0 53.041-42.998 96.039-96.039 96.039s-96.039-42.998-96.039-96.039c0-53.041 42.998-96.039 96.039-96.039s96.039 42.998 96.039 96.039z","M384.001 96h576.002v192.008h-576.002v-192.008z","M384.001 416.002h576.002v192.008h-576.002v-192.008z","M384.001 736.002h576.002v192.008h-576.002v-192.008z","M256.015 512.010c0 53.041-42.998 96.039-96.039 96.039s-96.039-42.998-96.039-96.039c0-53.041 42.998-96.039 96.039-96.039s96.039 42.998 96.039 96.039z","M256.015 832.010c0 53.041-42.998 96.039-96.039 96.039s-96.039-42.998-96.039-96.039c0-53.041 42.998-96.039 96.039-96.039s96.039 42.998 96.039 96.039z"],"attrs":[],"grid":0,"tags":["listr-view-default"]},"attrs":[],"properties":{"order":6,"id":3,"name":"list-view-default","prevSize":32,"code":59650},"setIdx":0,"setId":1,"iconIdx":8},{"icon":{"paths":["M64.059 911.075v-274.364c0-14.39 4.781-25.902 14.342-35.495s21.035-14.39 35.377-15.349h273.451c13.386 0 24.859 4.797 35.377 15.349s15.298 22.064 14.342 35.495v274.364c0 13.43-4.781 24.942-14.342 34.535s-21.035 14.39-35.377 14.39h-273.451c-14.342 0-25.815-4.797-35.377-14.39s-14.342-21.105-14.342-34.535zM64.059 387.289v-274.364c0-13.43 4.781-24.942 14.342-34.535s21.035-14.39 35.377-14.39h273.451c13.386 0 24.859 4.797 35.377 14.39s15.298 21.105 14.342 34.535v274.364c0 14.39-4.781 25.902-14.342 35.495s-21.035 14.39-35.377 15.349h-273.451c-13.386 0-24.859-4.797-35.377-15.349s-15.298-22.064-14.342-35.495zM148.197 876.539h204.61v-205.293h-204.61v205.293zM148.197 352.753h204.61v-204.334h-204.61v204.334zM587.058 911.075v-274.364c0-14.39 4.781-25.902 14.342-35.495s21.035-14.39 35.377-15.349h273.451c13.386 0 24.859 4.797 35.377 15.349s15.298 22.064 14.342 35.495v274.364c0 13.43-4.781 24.942-14.342 34.535s-21.035 14.39-35.377 14.39h-273.451c-13.386 0-24.859-4.797-35.377-14.39s-15.298-21.105-14.342-34.535zM587.058 387.289v-274.364c0-13.43 4.781-24.942 14.342-34.535s21.035-14.39 35.377-14.39h273.451c14.342 0 25.815 4.797 35.377 14.39s14.342 21.105 14.342 34.535v274.364c0 14.39-4.781 25.902-14.342 35.495s-21.035 14.39-35.377 15.349h-273.451c-13.386 0-24.859-4.797-35.377-15.349s-15.298-22.064-14.342-35.495zM671.197 876.539h205.566v-205.293h-205.566v205.293zM671.197 352.753h205.566v-204.334h-205.566v204.334z"],"attrs":[],"grid":0,"tags":["th-thumb-empty"]},"attrs":[],"properties":{"order":7,"id":2,"name":"grid","prevSize":32,"code":59651},"setIdx":0,"setId":1,"iconIdx":9},{"icon":{"paths":["M473.568 780.8c0 59.098 44.467 107.789 101.76 114.432l6.682 0.576 6.758 0.192h-153.6l-6.758-0.192c-58.253-3.379-104.87-49.997-108.25-108.25l-0.192-6.758v-537.6l0.192-6.758c3.226-55.91 46.349-101.107 101.299-107.635l6.95-0.614 6.758-0.192h153.6l-6.758 0.192c-55.91 3.226-101.107 46.349-107.635 101.299l-0.614 6.95-0.192 6.758v537.6z"],"attrs":[],"grid":0,"tags":["bracket-open"]},"attrs":[],"properties":{"order":8,"id":1,"name":"bracket-open","prevSize":32,"code":59652},"setIdx":0,"setId":1,"iconIdx":10},{"icon":{"paths":["M447.136 780.8c0 59.098-44.467 107.789-101.76 114.432l-6.682 0.576-6.758 0.192h153.6l6.758-0.192c58.253-3.379 104.87-49.997 108.25-108.25l0.192-6.758v-537.6l-0.192-6.758c-3.226-55.91-46.349-101.107-101.299-107.635l-6.95-0.614-6.758-0.192h-153.6l6.758 0.192c55.91 3.226 101.107 46.349 107.635 101.299l0.614 6.95 0.192 6.758v537.6z"],"attrs":[],"grid":0,"tags":["bracket-close"]},"attrs":[],"properties":{"order":13,"id":0,"name":"bracket-close","prevSize":32,"code":59653},"setIdx":0,"setId":1,"iconIdx":11}],"height":1024,"metadata":{"name":"Icinga-Icons","url":"https://icinga.com","designer":"Florian Strohmaier (Icinga)","designerURL":"https://icinga.com","license":"Proprietary"},"preferences":{"showGlyphs":true,"showQuickUse":true,"showQuickUse2":true,"showSVGs":true,"fontPref":{"prefix":"iicon-","metadata":{"fontFamily":"Icinga-Icons","majorVersion":1,"minorVersion":0,"fontURL":"https://icinga.com","copyright":"Icinga GmbH","designer":"Florian Strohmaier (Icinga)","designerURL":"https://icinga.com","license":"Proprietary"},"metrics":{"emSize":1024,"baseline":6.25,"whitespace":50},"embed":false,"noie8":true,"ie7":false,"showSelector":true,"showMetrics":false,"showMetadata":false,"showVersion":false},"imagePref":{"prefix":"icon-","png":true,"useClassSelector":true,"color":0,"bgColor":16777215,"classSelector":".icon"},"historySize":50,"showCodes":true,"gridSize":16,"showGrid":false}}
\ No newline at end of file
+{"IcoMoonType":"selection","icons":[{"icon":{"paths":["M561.28 464.64v-160.64h-99.2v160.64h-158.080v99.2h158.080v156.16h99.2v-156.16h158.72v-99.2h-158.72z","M512 138.88c206.080 0 373.12 167.68 373.12 373.12s-167.68 373.12-373.12 373.12-373.12-167.68-373.12-373.12 167.68-373.12 373.12-373.12zM512 64c-247.68 0-448 200.32-448 448s200.32 448 448 448 448-200.32 448-448-200.32-448-448-448v0z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["add-inside"]},"attrs":[{},{}],"properties":{"order":21,"id":14,"name":"add-inside","prevSize":32,"code":59660},"setIdx":0,"setId":1,"iconIdx":0},{"icon":{"paths":["M419.2 499.84h-156.8c-10.88 0-19.2-8.96-19.2-19.2v-288.64h-115.2v307.84c0 74.24 60.16 135.040 135.040 135.040h156.8l-50.56 173.44 231.040-173.44s76.8-57.6 76.8-57.6l-308.48-273.28 51.2 195.84z","M64 64h448v74.88h-448v-74.88z","M853.12 808.32v-464c0-93.44 75.52-149.12 149.12-149.12-45.44 0-99.84-1.28-149.12-1.28-103.040 0-149.12 75.52-149.12 150.4v464c0 74.88 46.080 151.68 149.12 151.68 49.28 0 103.68-0.64 149.12-1.28-73.6 0-149.76-76.16-149.12-150.4z"],"attrs":[{},{},{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["inser-group"]},"attrs":[{},{},{}],"properties":{"order":29,"id":13,"name":"insert-group","prevSize":32,"code":59661},"setIdx":0,"setId":1,"iconIdx":1},{"icon":{"paths":["M802.56 62.72c-49.28 0-110.72 0.64-156.16 1.28 73.6 0 168.32 60.16 167.68 134.4v627.2c0 74.24-94.72 134.4-167.68 134.4 45.44 0 106.88 1.28 156.16 1.28 103.040 0 157.44-60.8 157.44-135.68v-627.2c0-74.88-55.040-135.68-157.44-135.68z","M704 502.4h-152.96v-182.4h-78.080v182.4h-152.96v77.44h152.96v188.16h78.080v-188.16h152.96v-77.44z","M209.92 825.6v-627.2c0-74.24 94.72-134.4 167.68-134.4-45.44 0-106.88-1.28-156.16-1.28-102.4 0-157.44 60.8-157.44 135.68v627.2c0 74.88 55.040 135.68 157.44 135.68 49.28 0 110.72-0.64 156.16-1.28-73.6 0-168.32-60.16-167.68-134.4z"],"attrs":[{},{},{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["wrap"]},"attrs":[{},{},{}],"properties":{"order":27,"id":12,"name":"wrap","prevSize":32,"code":59662},"setIdx":0,"setId":1,"iconIdx":2},{"icon":{"paths":["M64 0h896c35.328 0 64 28.672 64 64v640c0 35.328-28.672 64-64 64h-350.72v-64h350.72v-640h-896v640h33.28v64h-33.28c-35.328 0-64-28.672-64-64v-640c0-35.328 28.672-64 64-64z","M576.048 481.122c0 123.698-100.277 223.976-223.976 223.976s-223.976-100.277-223.976-223.976c0-123.698 100.277-223.976 223.976-223.976s223.976 100.277 223.976 223.976z","M511.488 720.896l64 303.104-224.32-128-223.168 128 64-303.488c45.76 30.656 100.8 48.576 160 48.576 58.944 0 113.792-17.728 159.488-48.192z","M896 192c0-16.96-6.784-33.28-18.752-45.248-12.032-12.032-28.288-18.752-45.248-18.752-71.040 0-185.024 0-256 0-17.024 0-33.28 6.72-45.248 18.752-12.032 11.968-18.752 28.288-18.752 45.248s6.72 33.28 18.752 45.248c11.968 12.032 28.224 18.752 45.248 18.752 70.976 0 184.96 0 256 0 16.96 0 33.216-6.72 45.248-18.752 11.968-11.968 18.752-28.288 18.752-45.248z","M896 384c0-16.96-6.784-33.28-18.752-45.248-12.032-12.032-28.288-18.752-45.248-18.752-71.040 0-57.024 0-128 0-17.024 0-33.28 6.72-45.248 18.752-12.032 11.968-18.752 28.288-18.752 45.248s6.72 33.28 18.752 45.248c11.968 12.032 28.224 18.752 45.248 18.752 70.976 0 56.96 0 128 0 16.96 0 33.216-6.72 45.248-18.752 11.968-11.968 18.752-28.288 18.752-45.248z"],"attrs":[],"grid":0,"tags":["certificate"]},"attrs":[],"properties":{"order":22,"id":11,"name":"certificate","prevSize":32,"code":59654},"setIdx":0,"setId":1,"iconIdx":3},{"icon":{"paths":["M7.232 90.496c11.776-24.896 36.672-40.704 64.192-40.704h768c27.584 0 52.48 15.808 64.192 40.704s8.192 54.208-9.216 75.52l-189.376 231.488c-142.592 29.312-249.6 155.392-249.6 306.496 0 48.704 11.2 94.912 31.104 136-2.816-1.408-5.696-3.2-8.32-5.184l-113.792-85.312c-14.4-10.688-22.784-27.52-22.784-45.504v-140.608l-325.312-397.504c-17.216-21.184-20.992-50.688-9.088-75.392z","M1024 705.024c-2.176 72.512-27.456 132.992-75.84 181.504-48.384 48.576-108.672 73.344-180.992 74.496-72.256-1.152-132.288-25.92-180.096-74.496-47.808-48.512-72.832-108.992-75.072-181.504 2.24-72.512 27.264-133.056 75.072-181.568s107.84-73.344 180.096-74.432c72.32 1.088 132.608 25.92 180.992 74.432s73.664 109.056 75.84 181.568zM966.144 581.248c-0.512-0.704-1.088-1.344-1.728-1.92-22.656-22.72-59.52-22.72-82.176 0l-80.448 80.32-33.024 76.608c0 0-25.6-65.728-25.6-65.728l-29.312-29.312c-22.656-22.656-59.52-22.656-82.176 0-22.72 22.72-22.72 59.52 0 82.24l94.272 94.272c11.2 11.2 25.856 16.832 40.512 16.96 0.448 0 0.896 0 1.28 0 14.656-0.192 29.248-5.824 40.384-16.96l156.224-156.224c22.016-22.016 22.656-57.472 1.792-80.256z"],"attrs":[],"grid":0,"tags":["filter-check-circle"]},"attrs":[],"properties":{"order":23,"id":10,"name":"filter-check-circle","prevSize":32,"code":59659},"setIdx":0,"setId":1,"iconIdx":4},{"icon":{"paths":["M177.038 607.479c-5.88 0.539-12.299 0.833-19.306 0.833-22.54 0-43.317-4.018-62.378-12.103-19.061-8.036-35.672-19.453-49.883-34.202-14.259-14.749-25.382-32.34-33.418-52.725s-12.103-43.072-12.103-68.013c0-24.941 4.165-47.727 12.495-68.405s19.6-38.22 33.81-52.725c14.21-14.504 30.968-25.48 50.324-33.026 19.306-7.497 40.23-11.27 62.77-11.27 20.384 0 40.671 3.92 60.761 11.711 20.139 7.742 36.358 19.159 48.707 34.202l-48.266 52.333c-6.468-10.241-15.043-17.591-25.774-22.148s-22.001-6.86-33.81-6.86c-11.809 0-22.932 2.401-33.418 7.252-10.437 4.851-19.453 11.515-26.95 20.139-7.497 8.575-13.279 18.767-17.297 30.576s-6.076 24.696-6.076 38.613c0 13.965 2.058 26.999 6.076 39.054 4.018 12.103 9.8 22.295 17.297 30.576 7.497 8.33 16.219 14.896 26.166 19.747 9.898 4.802 21.070 7.252 33.369 7.252 13.965 0 26.313-2.989 37.044-8.869 8.575-4.851 15.827-11.025 21.756-18.522l-41.896 96.58z","M484.864 594.112l-18.752-49.408h-123.2l-23.296 63.616h-82.944l132.8-321.984h74.88l90.688 222.4c-21.632 25.92-38.336 54.336-50.176 85.376zM405.696 372.48l-40.192 110.272h79.68l-39.488-110.272z","M1024 705.024c-2.176 72.512-27.456 132.992-75.84 181.504-48.384 48.576-108.672 73.344-180.992 74.496-72.256-1.152-132.288-25.92-180.096-74.496-47.808-48.512-72.832-108.992-75.072-181.504 2.24-72.512 27.264-133.056 75.072-181.568s107.84-73.344 180.096-74.432c72.32 1.088 132.608 25.92 180.992 74.432s73.664 109.056 75.84 181.568zM966.144 581.248c-0.512-0.704-1.088-1.344-1.728-1.92-22.656-22.72-59.52-22.72-82.176 0l-80.448 80.32-33.024 76.608c0 0-25.6-65.728-25.6-65.728l-29.312-29.312c-22.656-22.656-59.52-22.656-82.176 0-22.72 22.72-22.72 59.52 0 82.24l94.272 94.272c11.2 11.2 25.856 16.832 40.512 16.96 0.448 0 0.896 0 1.28 0 14.656-0.192 29.248-5.824 40.384-16.96l156.224-156.224c22.016-22.016 22.656-57.472 1.792-80.256z"],"attrs":[],"grid":0,"tags":["filter-circle-check"]},"attrs":[],"properties":{"order":24,"id":9,"name":"ca-circle-check","prevSize":32,"code":59656},"setIdx":0,"setId":1,"iconIdx":5},{"icon":{"paths":["M319.936 448h384v257.088h-384v-257.088z","M383.936 416v-96c0-35.328 28.672-64 64-64h128c35.328 0 64 28.672 64 64v96h-256zM575.936 320h-128v96h128v-96z","M192.448 724.864c68.864 103.168 186.368 171.136 319.552 171.136 141.568 0 265.344-76.8 331.904-190.912h142.4c-76.288 187.008-260.032 318.912-474.304 318.912-180.544 0-339.392-93.632-430.592-235.008l-81.536 47.104 2.112-324.096 281.472 160.384-91.008 52.48zM833.472 302.080c-68.544-104.832-187.008-174.080-321.472-174.080-167.040 0-309.376 106.944-362.112 256h-133.76c56.896-220.736 257.472-384 495.872-384 181.824 0 341.632 94.976 432.448 237.952l79.68-45.952-2.112 324.096-281.472-160.384 92.928-53.632z"],"attrs":[],"grid":0,"tags":["refresh-cert"]},"attrs":[],"properties":{"order":25,"id":8,"name":"refresh-cert","prevSize":32,"code":59657},"setIdx":0,"setId":1,"iconIdx":6},{"icon":{"paths":["M64.491 787.398c0 19.125 6.694 35.381 20.081 48.768s29.644 20.081 48.768 20.081h30.6c19.125 0 35.381-6.694 48.768-20.081s20.081-29.644 20.081-48.768c0-19.125-6.694-35.381-20.081-48.768s-29.644-20.081-48.768-20.081h-30.6c-19.125 0-35.381 6.694-48.768 20.081s-20.081 29.644-20.081 48.768zM64.491 512c0 19.125 6.694 35.381 20.081 48.768s29.644 20.081 48.768 20.081h30.6c19.125 0 35.381-6.694 48.768-20.081s20.081-29.644 20.081-48.768c0-19.125-6.694-35.381-20.081-48.768s-29.644-20.081-48.768-20.081h-30.6c-19.125 0-35.381 6.694-48.768 20.081s-20.081 29.644-20.081 48.768zM64.491 236.602c0 19.125 6.694 35.381 20.081 48.768s29.644 20.081 48.768 20.081h30.6c19.125 0 35.381-6.694 48.768-20.081s20.081-29.644 20.081-48.768c0-19.125-6.694-35.381-20.081-48.768s-29.644-20.081-48.768-20.081h-30.6c-19.125 0-35.381 6.694-48.768 20.081s-20.081 29.644-20.081 48.768zM288.252 787.398c0 19.125 6.694 35.381 20.081 48.768s29.644 20.081 48.768 20.081h534.54c19.125 0 35.381-6.694 48.768-20.081s20.081-29.644 20.081-48.768c0-19.125-6.694-35.381-20.081-48.768s-29.644-20.081-48.768-20.081h-534.54c-19.125 0-35.381 6.694-48.768 20.081s-20.081 29.644-20.081 48.768zM288.252 512c0 19.125 6.694 35.381 20.081 48.768s29.644 20.081 48.768 20.081h534.54c19.125 0 35.381-6.694 48.768-20.081s20.081-29.644 20.081-48.768c0-19.125-6.694-35.381-20.081-48.768s-29.644-20.081-48.768-20.081h-534.54c-19.125 0-35.381 6.694-48.768 20.081s-20.081 29.644-20.081 48.768zM288.252 236.602c0 19.125 6.694 35.381 20.081 48.768s29.644 20.081 48.768 20.081h534.54c19.125 0 35.381-6.694 48.768-20.081s20.081-29.644 20.081-48.768c0-19.125-6.694-35.381-20.081-48.768s-29.644-20.081-48.768-20.081h-534.54c-19.125 0-35.381 6.694-48.768 20.081s-20.081 29.644-20.081 48.768z"],"attrs":[],"grid":0,"tags":["th-list"]},"attrs":[],"properties":{"order":26,"id":7,"name":"th-list","prevSize":32,"code":59658},"setIdx":0,"setId":1,"iconIdx":7},{"icon":{"paths":["M574.496 81.411l45.262 8.286-149.128 422.304-45.261-8.286 149.126-422.304z","M896.001 369.329v29.341l-379.111 128.001-9.78-29.341 388.891-128.001z","M656 768v43.787l-164.906-224.295 41.812-23.571 123.093 204.079z","M205.566 845.588l-27.131-27.175 205.565-242.414 63.999 13.589-242.434 255.999z","M192.001 320.001l-38.798-52.36 308.952 225.624-28.309 38.763-241.845-212.028z","M576.418 0.897c75.061 0 136.002 60.94 136.002 136s-60.941 136-136.002 136c-75.058 0-135.999-60.94-135.999-136s60.941-136 135.999-136z","M911.998 272.897c61.815 0 111.999 50.187 111.999 112 0 61.816-50.185 112-111.999 112s-111.999-50.184-111.999-112c0-61.813 50.185-112 111.999-112z","M656 719.998c44.154 0 80.002 35.85 80.002 80.001 0 44.155-35.848 80.001-80.002 80.001-44.15 0-79.998-35.846-79.998-80.001 0-44.151 35.848-80.001 79.998-80.001z","M143.999 735.999c79.478 0 144.002 64.526 144.002 144.002s-64.524 143.999-144.002 143.999c-79.475 0-143.999-64.524-143.999-143.999s64.524-144.002 143.999-144.002z","M139.048 191.022c52.984 0 96.001 43.016 96.001 96.001 0 52.982-43.018 95.998-96.001 95.998s-95.998-43.016-95.998-95.998c0-52.985 43.014-96.001 95.998-96.001z","M448 319.706c105.968 0 192 86.034 192 192.001s-86.032 191.999-192 191.999c-105.968 0-192-86.032-192-191.999s86.032-192.001 192-192.001z"],"attrs":[],"grid":0,"tags":["icinga"]},"attrs":[],"properties":{"order":10,"id":6,"name":"icinga","prevSize":32,"code":59655},"setIdx":0,"setId":1,"iconIdx":8},{"icon":{"paths":["M192.009 128.005c0 35.361-28.665 64.026-64.026 64.026s-64.026-28.665-64.026-64.026c0-35.361 28.665-64.026 64.026-64.026s64.026 28.665 64.026 64.026z","M192.009 320.329c0 35.361-28.665 64.026-64.026 64.026s-64.026-28.665-64.026-64.026c0-35.361 28.665-64.026 64.026-64.026s64.026 28.665 64.026 64.026z","M192.009 512.329c0 35.361-28.665 64.026-64.026 64.026s-64.026-28.665-64.026-64.026c0-35.361 28.665-64.026 64.026-64.026s64.026 28.665 64.026 64.026z","M320.006 96.003h640.004v64.005h-640.004v-64.005z","M320.006 480.326h640.004v64.005h-640.004v-64.005z","M320.006 288.326h640.004v64.005h-640.004v-64.005z","M320.006 672.326h640.004v64.005h-640.004v-64.005z","M320.006 864.326h640.004v64.005h-640.004v-64.005z","M192.009 704.652c0 35.361-28.665 64.026-64.026 64.026s-64.026-28.665-64.026-64.026c0-35.361 28.665-64.026 64.026-64.026s64.026 28.665 64.026 64.026z","M192.009 896.329c0 35.361-28.665 64.026-64.026 64.026s-64.026-28.665-64.026-64.026c0-35.361 28.665-64.026 64.026-64.026s64.026 28.665 64.026 64.026z"],"attrs":[],"grid":0,"tags":["list-view-minimal"]},"attrs":[],"properties":{"order":4,"id":5,"name":"list-view-minimal","prevSize":32,"code":59648},"setIdx":0,"setId":1,"iconIdx":9},{"icon":{"paths":["M320.007 128.321h639.993v191.358h-639.993v-191.358z","M320.007 384.003h639.993v63.992h-639.993v-63.992z","M256.014 223.683c0 53.041-42.998 96.039-96.039 96.039s-96.039-42.998-96.039-96.039c0-53.041 42.998-96.039 96.039-96.039s96.039 42.998 96.039 96.039z","M256.014 672.008c0 53.041-42.998 96.039-96.039 96.039s-96.039-42.998-96.039-96.039c0-53.041 42.998-96.039 96.039-96.039s96.039 42.998 96.039 96.039z","M320.007 575.996h639.993v192.005h-639.993v-192.005z","M320.007 831.995h639.993v63.992h-639.993v-63.992z"],"attrs":[],"grid":0,"tags":["list-view-detailed"]},"attrs":[],"properties":{"order":5,"id":4,"name":"list-view-detailed","prevSize":32,"code":59649},"setIdx":0,"setId":1,"iconIdx":10},{"icon":{"paths":["M256.015 192.008c0 53.041-42.998 96.039-96.039 96.039s-96.039-42.998-96.039-96.039c0-53.041 42.998-96.039 96.039-96.039s96.039 42.998 96.039 96.039z","M384.001 96h576.002v192.008h-576.002v-192.008z","M384.001 416.002h576.002v192.008h-576.002v-192.008z","M384.001 736.002h576.002v192.008h-576.002v-192.008z","M256.015 512.010c0 53.041-42.998 96.039-96.039 96.039s-96.039-42.998-96.039-96.039c0-53.041 42.998-96.039 96.039-96.039s96.039 42.998 96.039 96.039z","M256.015 832.010c0 53.041-42.998 96.039-96.039 96.039s-96.039-42.998-96.039-96.039c0-53.041 42.998-96.039 96.039-96.039s96.039 42.998 96.039 96.039z"],"attrs":[],"grid":0,"tags":["listr-view-default"]},"attrs":[],"properties":{"order":6,"id":3,"name":"list-view-default","prevSize":32,"code":59650},"setIdx":0,"setId":1,"iconIdx":11},{"icon":{"paths":["M64.059 911.075v-274.364c0-14.39 4.781-25.902 14.342-35.495s21.035-14.39 35.377-15.349h273.451c13.386 0 24.859 4.797 35.377 15.349s15.298 22.064 14.342 35.495v274.364c0 13.43-4.781 24.942-14.342 34.535s-21.035 14.39-35.377 14.39h-273.451c-14.342 0-25.815-4.797-35.377-14.39s-14.342-21.105-14.342-34.535zM64.059 387.289v-274.364c0-13.43 4.781-24.942 14.342-34.535s21.035-14.39 35.377-14.39h273.451c13.386 0 24.859 4.797 35.377 14.39s15.298 21.105 14.342 34.535v274.364c0 14.39-4.781 25.902-14.342 35.495s-21.035 14.39-35.377 15.349h-273.451c-13.386 0-24.859-4.797-35.377-15.349s-15.298-22.064-14.342-35.495zM148.197 876.539h204.61v-205.293h-204.61v205.293zM148.197 352.753h204.61v-204.334h-204.61v204.334zM587.058 911.075v-274.364c0-14.39 4.781-25.902 14.342-35.495s21.035-14.39 35.377-15.349h273.451c13.386 0 24.859 4.797 35.377 15.349s15.298 22.064 14.342 35.495v274.364c0 13.43-4.781 24.942-14.342 34.535s-21.035 14.39-35.377 14.39h-273.451c-13.386 0-24.859-4.797-35.377-14.39s-15.298-21.105-14.342-34.535zM587.058 387.289v-274.364c0-13.43 4.781-24.942 14.342-34.535s21.035-14.39 35.377-14.39h273.451c14.342 0 25.815 4.797 35.377 14.39s14.342 21.105 14.342 34.535v274.364c0 14.39-4.781 25.902-14.342 35.495s-21.035 14.39-35.377 15.349h-273.451c-13.386 0-24.859-4.797-35.377-15.349s-15.298-22.064-14.342-35.495zM671.197 876.539h205.566v-205.293h-205.566v205.293zM671.197 352.753h205.566v-204.334h-205.566v204.334z"],"attrs":[],"grid":0,"tags":["th-thumb-empty"]},"attrs":[],"properties":{"order":7,"id":2,"name":"grid","prevSize":32,"code":59651},"setIdx":0,"setId":1,"iconIdx":12},{"icon":{"paths":["M473.568 780.8c0 59.098 44.467 107.789 101.76 114.432l6.682 0.576 6.758 0.192h-153.6l-6.758-0.192c-58.253-3.379-104.87-49.997-108.25-108.25l-0.192-6.758v-537.6l0.192-6.758c3.226-55.91 46.349-101.107 101.299-107.635l6.95-0.614 6.758-0.192h153.6l-6.758 0.192c-55.91 3.226-101.107 46.349-107.635 101.299l-0.614 6.95-0.192 6.758v537.6z"],"attrs":[],"grid":0,"tags":["bracket-open"]},"attrs":[],"properties":{"order":8,"id":1,"name":"bracket-open","prevSize":32,"code":59652},"setIdx":0,"setId":1,"iconIdx":13},{"icon":{"paths":["M447.136 780.8c0 59.098-44.467 107.789-101.76 114.432l-6.682 0.576-6.758 0.192h153.6l6.758-0.192c58.253-3.379 104.87-49.997 108.25-108.25l0.192-6.758v-537.6l-0.192-6.758c-3.226-55.91-46.349-101.107-101.299-107.635l-6.95-0.614-6.758-0.192h-153.6l6.758 0.192c55.91 3.226 101.107 46.349 107.635 101.299l0.614 6.95 0.192 6.758v537.6z"],"attrs":[],"grid":0,"tags":["bracket-close"]},"attrs":[],"properties":{"order":13,"id":0,"name":"bracket-close","prevSize":32,"code":59653},"setIdx":0,"setId":1,"iconIdx":14}],"height":1024,"metadata":{"name":"Icinga-Icons","url":"https://icinga.com","designer":"Florian Strohmaier (Icinga)","designerURL":"https://icinga.com","license":"Proprietary"},"preferences":{"showGlyphs":true,"showQuickUse":true,"showQuickUse2":true,"showSVGs":true,"fontPref":{"prefix":"iicon-","metadata":{"fontFamily":"Icinga-Icons","majorVersion":1,"minorVersion":0,"fontURL":"https://icinga.com","copyright":"Icinga GmbH","designer":"Florian Strohmaier (Icinga)","designerURL":"https://icinga.com","license":"Proprietary"},"metrics":{"emSize":1024,"baseline":6.25,"whitespace":50},"embed":false,"noie8":true,"ie7":false,"showSelector":true,"showMetrics":true,"showMetadata":true,"showVersion":true},"imagePref":{"prefix":"icon-","png":true,"useClassSelector":true,"color":0,"bgColor":16777215,"classSelector":".icon"},"historySize":50,"showCodes":true,"gridSize":16,"showGrid":false}}
\ No newline at end of file
diff --git a/asset/static/font/icinga-icons/src/add-inside.svg b/asset/static/font/icinga-icons/src/add-inside.svg
new file mode 100644
index 0000000..07377af
--- /dev/null
+++ b/asset/static/font/icinga-icons/src/add-inside.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/asset/static/font/icinga-icons/src/insert-group.svg b/asset/static/font/icinga-icons/src/insert-group.svg
new file mode 100644
index 0000000..0d89c3f
--- /dev/null
+++ b/asset/static/font/icinga-icons/src/insert-group.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/asset/static/font/icinga-icons/src/wrap.svg b/asset/static/font/icinga-icons/src/wrap.svg
new file mode 100644
index 0000000..5c78ca9
--- /dev/null
+++ b/asset/static/font/icinga-icons/src/wrap.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/asset/static/font/icinga-icons/style.css b/asset/static/font/icinga-icons/style.css
index dde73b4..566e7f5 100644
--- a/asset/static/font/icinga-icons/style.css
+++ b/asset/static/font/icinga-icons/style.css
@@ -24,6 +24,15 @@
-moz-osx-font-smoothing: grayscale;
}
+.iicon-add-inside:before {
+ content: "\e90c";
+}
+.iicon-insert-group:before {
+ content: "\e90d";
+}
+.iicon-wrap:before {
+ content: "\e90e";
+}
.iicon-certificate:before {
content: "\e906";
}
diff --git a/composer.lock b/composer.lock
index 2d119b7..e9327d6 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,30 +4,29 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "20d4022bc196691807f55d4a47c06474",
+ "content-hash": "7a1692c86b6fc70eaaf43c4bee3673aa",
"packages": [
{
"name": "brick/math",
- "version": "0.9.3",
+ "version": "0.14.0",
"source": {
"type": "git",
"url": "https://github.com/brick/math.git",
- "reference": "ca57d18f028f84f777b2168cd1911b0dee2343ae"
+ "reference": "113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/brick/math/zipball/ca57d18f028f84f777b2168cd1911b0dee2343ae",
- "reference": "ca57d18f028f84f777b2168cd1911b0dee2343ae",
+ "url": "https://api.github.com/repos/brick/math/zipball/113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2",
+ "reference": "113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2",
"shasum": ""
},
"require": {
- "ext-json": "*",
- "php": "^7.1 || ^8.0"
+ "php": "^8.2"
},
"require-dev": {
"php-coveralls/php-coveralls": "^2.2",
- "phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.0",
- "vimeo/psalm": "4.9.2"
+ "phpstan/phpstan": "2.1.22",
+ "phpunit/phpunit": "^11.5"
},
"type": "library",
"autoload": {
@@ -47,101 +46,56 @@
"arithmetic",
"bigdecimal",
"bignum",
+ "bignumber",
"brick",
- "math"
+ "decimal",
+ "integer",
+ "math",
+ "mathematics",
+ "rational"
],
"support": {
"issues": "https://github.com/brick/math/issues",
- "source": "https://github.com/brick/math/tree/0.9.3"
+ "source": "https://github.com/brick/math/tree/0.14.0"
},
"funding": [
{
"url": "https://github.com/BenMorel",
"type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/brick/math",
- "type": "tidelift"
}
],
- "time": "2021-08-15T20:50:18+00:00"
- },
- {
- "name": "cweagans/composer-patches",
- "version": "1.7.3",
- "source": {
- "type": "git",
- "url": "https://github.com/cweagans/composer-patches.git",
- "reference": "e190d4466fe2b103a55467dfa83fc2fecfcaf2db"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/cweagans/composer-patches/zipball/e190d4466fe2b103a55467dfa83fc2fecfcaf2db",
- "reference": "e190d4466fe2b103a55467dfa83fc2fecfcaf2db",
- "shasum": ""
- },
- "require": {
- "composer-plugin-api": "^1.0 || ^2.0",
- "php": ">=5.3.0"
- },
- "require-dev": {
- "composer/composer": "~1.0 || ~2.0",
- "phpunit/phpunit": "~4.6"
- },
- "type": "composer-plugin",
- "extra": {
- "class": "cweagans\\Composer\\Patches"
- },
- "autoload": {
- "psr-4": {
- "cweagans\\Composer\\": "src"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Cameron Eagans",
- "email": "me@cweagans.net"
- }
- ],
- "description": "Provides a way to patch Composer packages.",
- "support": {
- "issues": "https://github.com/cweagans/composer-patches/issues",
- "source": "https://github.com/cweagans/composer-patches/tree/1.7.3"
- },
- "time": "2022-12-20T22:53:13+00:00"
+ "time": "2025-08-29T12:40:03+00:00"
},
{
"name": "doctrine/collections",
- "version": "1.8.0",
+ "version": "2.4.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/collections.git",
- "reference": "2b44dd4cbca8b5744327de78bafef5945c7e7b5e"
+ "reference": "9acfeea2e8666536edff3d77c531261c63680160"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/collections/zipball/2b44dd4cbca8b5744327de78bafef5945c7e7b5e",
- "reference": "2b44dd4cbca8b5744327de78bafef5945c7e7b5e",
+ "url": "https://api.github.com/repos/doctrine/collections/zipball/9acfeea2e8666536edff3d77c531261c63680160",
+ "reference": "9acfeea2e8666536edff3d77c531261c63680160",
"shasum": ""
},
"require": {
- "doctrine/deprecations": "^0.5.3 || ^1",
- "php": "^7.1.3 || ^8.0"
+ "doctrine/deprecations": "^1",
+ "php": "^8.1",
+ "symfony/polyfill-php84": "^1.30"
},
"require-dev": {
- "doctrine/coding-standard": "^9.0 || ^10.0",
- "phpstan/phpstan": "^1.4.8",
- "phpunit/phpunit": "^7.5 || ^8.5 || ^9.1.5",
- "vimeo/psalm": "^4.22"
+ "doctrine/coding-standard": "^14",
+ "ext-json": "*",
+ "phpstan/phpstan": "^2.1.30",
+ "phpstan/phpstan-phpunit": "^2.0.7",
+ "phpunit/phpunit": "^10.5.58 || ^11.5.42 || ^12.4"
},
"type": "library",
"autoload": {
"psr-4": {
- "Doctrine\\Common\\Collections\\": "lib/Doctrine/Common/Collections"
+ "Doctrine\\Common\\Collections\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -180,9 +134,23 @@
],
"support": {
"issues": "https://github.com/doctrine/collections/issues",
- "source": "https://github.com/doctrine/collections/tree/1.8.0"
+ "source": "https://github.com/doctrine/collections/tree/2.4.0"
},
- "time": "2022-09-01T20:12:10+00:00"
+ "funding": [
+ {
+ "url": "https://www.doctrine-project.org/sponsorship.html",
+ "type": "custom"
+ },
+ {
+ "url": "https://www.patreon.com/phpdoctrine",
+ "type": "patreon"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcollections",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-10-25T09:18:13+00:00"
},
{
"name": "doctrine/deprecations",
@@ -234,29 +202,28 @@
},
{
"name": "dragonmantank/cron-expression",
- "version": "v3.4.0",
+ "version": "v3.6.0",
"source": {
"type": "git",
"url": "https://github.com/dragonmantank/cron-expression.git",
- "reference": "8c784d071debd117328803d86b2097615b457500"
+ "reference": "d61a8a9604ec1f8c3d150d09db6ce98b32675013"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/8c784d071debd117328803d86b2097615b457500",
- "reference": "8c784d071debd117328803d86b2097615b457500",
+ "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/d61a8a9604ec1f8c3d150d09db6ce98b32675013",
+ "reference": "d61a8a9604ec1f8c3d150d09db6ce98b32675013",
"shasum": ""
},
"require": {
- "php": "^7.2|^8.0",
- "webmozart/assert": "^1.0"
+ "php": "^8.2|^8.3|^8.4|^8.5"
},
"replace": {
"mtdowling/cron-expression": "^1.0"
},
"require-dev": {
- "phpstan/extension-installer": "^1.0",
- "phpstan/phpstan": "^1.0",
- "phpunit/phpunit": "^7.0|^8.0|^9.0"
+ "phpstan/extension-installer": "^1.4.3",
+ "phpstan/phpstan": "^1.12.32|^2.1.31",
+ "phpunit/phpunit": "^8.5.48|^9.0"
},
"type": "library",
"extra": {
@@ -287,7 +254,7 @@
],
"support": {
"issues": "https://github.com/dragonmantank/cron-expression/issues",
- "source": "https://github.com/dragonmantank/cron-expression/tree/v3.4.0"
+ "source": "https://github.com/dragonmantank/cron-expression/tree/v3.6.0"
},
"funding": [
{
@@ -295,7 +262,7 @@
"type": "github"
}
],
- "time": "2024-10-09T13:47:03+00:00"
+ "time": "2025-10-31T18:51:33+00:00"
},
{
"name": "evenement/evenement",
@@ -507,16 +474,16 @@
},
{
"name": "ipl/html",
- "version": "v0.8.2",
+ "version": "dev-main",
"source": {
"type": "git",
"url": "https://github.com/Icinga/ipl-html.git",
- "reference": "e18bdf11abca5e477100e2c7d190ef5f424d0d98"
+ "reference": "9354c29faf807e67c4a0a365b450b7f0b64598ad"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Icinga/ipl-html/zipball/e18bdf11abca5e477100e2c7d190ef5f424d0d98",
- "reference": "e18bdf11abca5e477100e2c7d190ef5f424d0d98",
+ "url": "https://api.github.com/repos/Icinga/ipl-html/zipball/9354c29faf807e67c4a0a365b450b7f0b64598ad",
+ "reference": "9354c29faf807e67c4a0a365b450b7f0b64598ad",
"shasum": ""
},
"require": {
@@ -524,13 +491,15 @@
"guzzlehttp/psr7": "^2.5",
"ipl/stdlib": ">=0.12.0",
"ipl/validator": ">=0.5.0",
- "php": ">=7.2",
+ "php": ">=8.2",
"psr/http-message": "^1.1"
},
"require-dev": {
+ "ext-dom": "*",
"ipl/stdlib": "dev-main",
"ipl/validator": "dev-main"
},
+ "default-branch": true,
"type": "library",
"autoload": {
"psr-4": {
@@ -548,22 +517,22 @@
],
"support": {
"issues": "https://github.com/Icinga/ipl-html/issues",
- "source": "https://github.com/Icinga/ipl-html/tree/v0.8.2"
+ "source": "https://github.com/Icinga/ipl-html/tree/main"
},
- "time": "2025-05-21T09:00:03+00:00"
+ "time": "2025-10-29T14:21:51+00:00"
},
{
"name": "ipl/i18n",
- "version": "v0.2.2",
+ "version": "dev-main",
"source": {
"type": "git",
"url": "https://github.com/Icinga/ipl-i18n.git",
- "reference": "a2b6109c5a93f86ce46d5dc351dbe75e8502cf8c"
+ "reference": "692c33cf46fb8a4511da613dbf97c6216c345cc5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Icinga/ipl-i18n/zipball/a2b6109c5a93f86ce46d5dc351dbe75e8502cf8c",
- "reference": "a2b6109c5a93f86ce46d5dc351dbe75e8502cf8c",
+ "url": "https://api.github.com/repos/Icinga/ipl-i18n/zipball/692c33cf46fb8a4511da613dbf97c6216c345cc5",
+ "reference": "692c33cf46fb8a4511da613dbf97c6216c345cc5",
"shasum": ""
},
"require": {
@@ -575,6 +544,7 @@
"require-dev": {
"ipl/stdlib": "dev-main"
},
+ "default-branch": true,
"type": "library",
"autoload": {
"files": [
@@ -599,35 +569,36 @@
],
"support": {
"issues": "https://github.com/Icinga/ipl-i18n/issues",
- "source": "https://github.com/Icinga/ipl-i18n/tree/v0.2.2"
+ "source": "https://github.com/Icinga/ipl-i18n/tree/main"
},
- "time": "2024-04-08T12:28:47+00:00"
+ "time": "2025-06-12T11:57:41+00:00"
},
{
"name": "ipl/orm",
- "version": "v0.6.3",
+ "version": "dev-main",
"source": {
"type": "git",
"url": "https://github.com/Icinga/ipl-orm.git",
- "reference": "a775a2745764a8dc7f28618cce69dcd7bbfd7915"
+ "reference": "dbcb2da01c168a02fe264e075e1c02c7233851df"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Icinga/ipl-orm/zipball/a775a2745764a8dc7f28618cce69dcd7bbfd7915",
- "reference": "a775a2745764a8dc7f28618cce69dcd7bbfd7915",
+ "url": "https://api.github.com/repos/Icinga/ipl-orm/zipball/dbcb2da01c168a02fe264e075e1c02c7233851df",
+ "reference": "dbcb2da01c168a02fe264e075e1c02c7233851df",
"shasum": ""
},
"require": {
"ext-pdo": "*",
"ipl/sql": ">=0.7.0",
"ipl/stdlib": ">=0.12.0",
- "php": ">=7.2"
+ "php": ">=8.2"
},
"require-dev": {
"ext-pdo_sqlite": "*",
"ipl/sql": "dev-main",
"ipl/stdlib": "dev-main"
},
+ "default-branch": true,
"type": "library",
"autoload": {
"psr-4": {
@@ -647,22 +618,22 @@
],
"support": {
"issues": "https://github.com/Icinga/ipl-orm/issues",
- "source": "https://github.com/Icinga/ipl-orm/tree/v0.6.3"
+ "source": "https://github.com/Icinga/ipl-orm/tree/main"
},
- "time": "2025-06-12T11:57:55+00:00"
+ "time": "2025-11-06T09:05:06+00:00"
},
{
"name": "ipl/scheduler",
- "version": "v0.1.2",
+ "version": "dev-main",
"source": {
"type": "git",
"url": "https://github.com/Icinga/ipl-scheduler.git",
- "reference": "6119afdea07b1390bd728e350e0d80b26ec8d6ba"
+ "reference": "d15143b2db2623b42bd25a013a73800dae2c6459"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Icinga/ipl-scheduler/zipball/6119afdea07b1390bd728e350e0d80b26ec8d6ba",
- "reference": "6119afdea07b1390bd728e350e0d80b26ec8d6ba",
+ "url": "https://api.github.com/repos/Icinga/ipl-scheduler/zipball/d15143b2db2623b42bd25a013a73800dae2c6459",
+ "reference": "d15143b2db2623b42bd25a013a73800dae2c6459",
"shasum": ""
},
"require": {
@@ -682,6 +653,7 @@
"suggest": {
"ext-ev": "Improves performance, efficiency and avoids system limitations. Highly recommended! (See https://www.php.net/manual/en/intro.ev.php for details)"
},
+ "default-branch": true,
"type": "library",
"autoload": {
"files": [
@@ -705,22 +677,22 @@
],
"support": {
"issues": "https://github.com/Icinga/ipl-scheduler/issues",
- "source": "https://github.com/Icinga/ipl-scheduler/tree/v0.1.2"
+ "source": "https://github.com/Icinga/ipl-scheduler/tree/main"
},
- "time": "2023-08-30T14:14:23+00:00"
+ "time": "2025-11-03T08:42:06+00:00"
},
{
"name": "ipl/sql",
- "version": "v0.7.1",
+ "version": "dev-main",
"source": {
"type": "git",
"url": "https://github.com/Icinga/ipl-sql.git",
- "reference": "e80f1b712c4b96099b0bf9096e6efe317a165e3b"
+ "reference": "6f4258c4e3b20655db57d248e26edf7b54c04729"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Icinga/ipl-sql/zipball/e80f1b712c4b96099b0bf9096e6efe317a165e3b",
- "reference": "e80f1b712c4b96099b0bf9096e6efe317a165e3b",
+ "url": "https://api.github.com/repos/Icinga/ipl-sql/zipball/6f4258c4e3b20655db57d248e26edf7b54c04729",
+ "reference": "6f4258c4e3b20655db57d248e26edf7b54c04729",
"shasum": ""
},
"require": {
@@ -731,6 +703,7 @@
"require-dev": {
"ipl/stdlib": "dev-main"
},
+ "default-branch": true,
"type": "library",
"autoload": {
"psr-4": {
@@ -749,22 +722,22 @@
],
"support": {
"issues": "https://github.com/Icinga/ipl-sql/issues",
- "source": "https://github.com/Icinga/ipl-sql/tree/v0.7.1"
+ "source": "https://github.com/Icinga/ipl-sql/tree/main"
},
- "time": "2024-06-25T09:55:43+00:00"
+ "time": "2025-10-08T07:03:38+00:00"
},
{
"name": "ipl/stdlib",
- "version": "v0.14.0",
+ "version": "dev-main",
"source": {
"type": "git",
"url": "https://github.com/Icinga/ipl-stdlib.git",
- "reference": "bf5fc8f40b86bd90337db6f3be389be2a93fa64a"
+ "reference": "9b7a903fbfc341da59f242149ac333594e4a6fa3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Icinga/ipl-stdlib/zipball/bf5fc8f40b86bd90337db6f3be389be2a93fa64a",
- "reference": "bf5fc8f40b86bd90337db6f3be389be2a93fa64a",
+ "url": "https://api.github.com/repos/Icinga/ipl-stdlib/zipball/9b7a903fbfc341da59f242149ac333594e4a6fa3",
+ "reference": "9b7a903fbfc341da59f242149ac333594e4a6fa3",
"shasum": ""
},
"require": {
@@ -772,6 +745,7 @@
"ext-openssl": "*",
"php": ">=7.2"
},
+ "default-branch": true,
"type": "library",
"autoload": {
"files": [
@@ -788,22 +762,22 @@
"description": "ipl Standard Library",
"support": {
"issues": "https://github.com/Icinga/ipl-stdlib/issues",
- "source": "https://github.com/Icinga/ipl-stdlib/tree/v0.14.0"
+ "source": "https://github.com/Icinga/ipl-stdlib/tree/main"
},
- "time": "2024-04-22T08:47:08+00:00"
+ "time": "2025-09-05T12:07:21+00:00"
},
{
"name": "ipl/validator",
- "version": "v0.5.0",
+ "version": "dev-main",
"source": {
"type": "git",
"url": "https://github.com/Icinga/ipl-validator.git",
- "reference": "a601fae0ed330e63cea50e4a2a6659ca1ad97bde"
+ "reference": "eac5c6c114d8007db5c24ae159fe6f55e89a946b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Icinga/ipl-validator/zipball/a601fae0ed330e63cea50e4a2a6659ca1ad97bde",
- "reference": "a601fae0ed330e63cea50e4a2a6659ca1ad97bde",
+ "url": "https://api.github.com/repos/Icinga/ipl-validator/zipball/eac5c6c114d8007db5c24ae159fe6f55e89a946b",
+ "reference": "eac5c6c114d8007db5c24ae159fe6f55e89a946b",
"shasum": ""
},
"require": {
@@ -812,11 +786,14 @@
"ipl/i18n": ">=0.2.0",
"ipl/stdlib": ">=0.12.0",
"php": ">=7.2",
- "psr/http-message": "~1.0"
+ "psr/http-message": "^1.1"
},
"require-dev": {
- "guzzlehttp/psr7": "^1"
+ "guzzlehttp/psr7": "^1",
+ "ipl/i18n": "dev-main",
+ "ipl/stdlib": "dev-main"
},
+ "default-branch": true,
"type": "library",
"autoload": {
"psr-4": {
@@ -831,33 +808,33 @@
"homepage": "https://github.com/Icinga/ipl-validator",
"support": {
"issues": "https://github.com/Icinga/ipl-validator/issues",
- "source": "https://github.com/Icinga/ipl-validator/tree/v0.5.0"
+ "source": "https://github.com/Icinga/ipl-validator/tree/main"
},
- "time": "2023-03-21T15:59:00+00:00"
+ "time": "2025-06-12T11:59:27+00:00"
},
{
"name": "ipl/web",
- "version": "v0.10.2",
+ "version": "dev-main",
"source": {
"type": "git",
"url": "https://github.com/Icinga/ipl-web.git",
- "reference": "a3d134c0d67aa51a9b186519c76e718603fda835"
+ "reference": "3e8867cbdde8af9724f64b84830503f8fcbd90e8"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Icinga/ipl-web/zipball/a3d134c0d67aa51a9b186519c76e718603fda835",
- "reference": "a3d134c0d67aa51a9b186519c76e718603fda835",
+ "url": "https://api.github.com/repos/Icinga/ipl-web/zipball/3e8867cbdde8af9724f64b84830503f8fcbd90e8",
+ "reference": "3e8867cbdde8af9724f64b84830503f8fcbd90e8",
"shasum": ""
},
"require": {
"ext-json": "*",
"fortawesome/font-awesome": "^6",
- "ipl/html": ">=0.8.0",
+ "ipl/html": ">=0.9.0",
"ipl/i18n": ">=0.2.0",
"ipl/orm": ">=0.5.2",
"ipl/scheduler": ">=0.1.0",
"ipl/stdlib": ">=0.13.0",
- "php": ">=7.2",
+ "php": ">=8.2",
"psr/http-message": "^1.1",
"wikimedia/less.php": "^3.2.1"
},
@@ -869,6 +846,7 @@
"ipl/stdlib": "dev-main",
"shardj/zf1-future": "^1.22"
},
+ "default-branch": true,
"type": "library",
"autoload": {
"psr-4": {
@@ -886,9 +864,9 @@
],
"support": {
"issues": "https://github.com/Icinga/ipl-web/issues",
- "source": "https://github.com/Icinga/ipl-web/tree/v0.10.2"
+ "source": "https://github.com/Icinga/ipl-web/tree/main"
},
- "time": "2025-03-26T07:49:58+00:00"
+ "time": "2025-10-31T09:12:36+00:00"
},
{
"name": "psr/http-factory",
@@ -1094,40 +1072,49 @@
},
{
"name": "ramsey/collection",
- "version": "1.1.4",
+ "version": "2.1.1",
"source": {
"type": "git",
"url": "https://github.com/ramsey/collection.git",
- "reference": "ab2237657ad99667a5143e32ba2683c8029563d4"
+ "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/ramsey/collection/zipball/ab2237657ad99667a5143e32ba2683c8029563d4",
- "reference": "ab2237657ad99667a5143e32ba2683c8029563d4",
+ "url": "https://api.github.com/repos/ramsey/collection/zipball/344572933ad0181accbf4ba763e85a0306a8c5e2",
+ "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2",
"shasum": ""
},
"require": {
- "php": "^7.2 || ^8"
+ "php": "^8.1"
},
"require-dev": {
- "captainhook/captainhook": "^5.3",
- "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
- "ergebnis/composer-normalize": "^2.6",
- "fakerphp/faker": "^1.5",
- "hamcrest/hamcrest-php": "^2",
- "jangregor/phpstan-prophecy": "^0.8",
- "mockery/mockery": "^1.3",
- "phpstan/extension-installer": "^1",
- "phpstan/phpstan": "^0.12.32",
- "phpstan/phpstan-mockery": "^0.12.5",
- "phpstan/phpstan-phpunit": "^0.12.11",
- "phpunit/phpunit": "^8.5 || ^9",
- "psy/psysh": "^0.10.4",
- "slevomat/coding-standard": "^6.3",
- "squizlabs/php_codesniffer": "^3.5",
- "vimeo/psalm": "^4.4"
+ "captainhook/plugin-composer": "^5.3",
+ "ergebnis/composer-normalize": "^2.45",
+ "fakerphp/faker": "^1.24",
+ "hamcrest/hamcrest-php": "^2.0",
+ "jangregor/phpstan-prophecy": "^2.1",
+ "mockery/mockery": "^1.6",
+ "php-parallel-lint/php-console-highlighter": "^1.0",
+ "php-parallel-lint/php-parallel-lint": "^1.4",
+ "phpspec/prophecy-phpunit": "^2.3",
+ "phpstan/extension-installer": "^1.4",
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-mockery": "^2.0",
+ "phpstan/phpstan-phpunit": "^2.0",
+ "phpunit/phpunit": "^10.5",
+ "ramsey/coding-standard": "^2.3",
+ "ramsey/conventional-commits": "^1.6",
+ "roave/security-advisories": "dev-latest"
},
"type": "library",
+ "extra": {
+ "captainhook": {
+ "force-install": true
+ },
+ "ramsey/conventional-commits": {
+ "configFile": "conventional-commits.json"
+ }
+ },
"autoload": {
"psr-4": {
"Ramsey\\Collection\\": "src/"
@@ -1144,7 +1131,7 @@
"homepage": "https://benramsey.com"
}
],
- "description": "A PHP 7.2+ library for representing and manipulating collections.",
+ "description": "A PHP library for representing and manipulating collections.",
"keywords": [
"array",
"collection",
@@ -1155,70 +1142,53 @@
],
"support": {
"issues": "https://github.com/ramsey/collection/issues",
- "source": "https://github.com/ramsey/collection/tree/1.1.4"
+ "source": "https://github.com/ramsey/collection/tree/2.1.1"
},
- "funding": [
- {
- "url": "https://github.com/ramsey",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/ramsey/collection",
- "type": "tidelift"
- }
- ],
- "time": "2021-07-30T00:58:27+00:00"
+ "time": "2025-03-22T05:38:12+00:00"
},
{
"name": "ramsey/uuid",
- "version": "4.2.3",
+ "version": "4.9.1",
"source": {
"type": "git",
"url": "https://github.com/ramsey/uuid.git",
- "reference": "fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df"
+ "reference": "81f941f6f729b1e3ceea61d9d014f8b6c6800440"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/ramsey/uuid/zipball/fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df",
- "reference": "fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df",
+ "url": "https://api.github.com/repos/ramsey/uuid/zipball/81f941f6f729b1e3ceea61d9d014f8b6c6800440",
+ "reference": "81f941f6f729b1e3ceea61d9d014f8b6c6800440",
"shasum": ""
},
"require": {
- "brick/math": "^0.8 || ^0.9",
- "ext-json": "*",
- "php": "^7.2 || ^8.0",
- "ramsey/collection": "^1.0",
- "symfony/polyfill-ctype": "^1.8",
- "symfony/polyfill-php80": "^1.14"
+ "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13 || ^0.14",
+ "php": "^8.0",
+ "ramsey/collection": "^1.2 || ^2.0"
},
"replace": {
"rhumsaa/uuid": "self.version"
},
"require-dev": {
- "captainhook/captainhook": "^5.10",
+ "captainhook/captainhook": "^5.25",
"captainhook/plugin-composer": "^5.3",
- "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
- "doctrine/annotations": "^1.8",
- "ergebnis/composer-normalize": "^2.15",
- "mockery/mockery": "^1.3",
- "moontoast/math": "^1.1",
+ "dealerdirect/phpcodesniffer-composer-installer": "^1.0",
+ "ergebnis/composer-normalize": "^2.47",
+ "mockery/mockery": "^1.6",
"paragonie/random-lib": "^2",
- "php-mock/php-mock": "^2.2",
- "php-mock/php-mock-mockery": "^1.3",
- "php-parallel-lint/php-parallel-lint": "^1.1",
- "phpbench/phpbench": "^1.0",
- "phpstan/extension-installer": "^1.0",
- "phpstan/phpstan": "^0.12",
- "phpstan/phpstan-mockery": "^0.12",
- "phpstan/phpstan-phpunit": "^0.12",
- "phpunit/phpunit": "^8.5 || ^9",
- "slevomat/coding-standard": "^7.0",
- "squizlabs/php_codesniffer": "^3.5",
- "vimeo/psalm": "^4.9"
+ "php-mock/php-mock": "^2.6",
+ "php-mock/php-mock-mockery": "^1.5",
+ "php-parallel-lint/php-parallel-lint": "^1.4.0",
+ "phpbench/phpbench": "^1.2.14",
+ "phpstan/extension-installer": "^1.4",
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-mockery": "^2.0",
+ "phpstan/phpstan-phpunit": "^2.0",
+ "phpunit/phpunit": "^9.6",
+ "slevomat/coding-standard": "^8.18",
+ "squizlabs/php_codesniffer": "^3.13"
},
"suggest": {
"ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.",
- "ext-ctype": "Enables faster processing of character classification using ctype functions.",
"ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.",
"ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.",
"paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter",
@@ -1228,9 +1198,6 @@
"extra": {
"captainhook": {
"force-install": true
- },
- "branch-alias": {
- "dev-main": "4.x-dev"
}
},
"autoload": {
@@ -1253,19 +1220,9 @@
],
"support": {
"issues": "https://github.com/ramsey/uuid/issues",
- "source": "https://github.com/ramsey/uuid/tree/4.2.3"
+ "source": "https://github.com/ramsey/uuid/tree/4.9.1"
},
- "funding": [
- {
- "url": "https://github.com/ramsey",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/ramsey/uuid",
- "type": "tidelift"
- }
- ],
- "time": "2021-09-25T23:10:38+00:00"
+ "time": "2025-09-04T20:59:21+00:00"
},
{
"name": "react/event-loop",
@@ -1471,100 +1428,17 @@
"time": "2024-12-12T15:39:24+00:00"
},
{
- "name": "symfony/polyfill-ctype",
+ "name": "symfony/polyfill-php84",
"version": "v1.33.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/polyfill-ctype.git",
- "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638"
+ "url": "https://github.com/symfony/polyfill-php84.git",
+ "reference": "d8ced4d875142b6a7426000426b8abc631d6b191"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638",
- "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638",
- "shasum": ""
- },
- "require": {
- "php": ">=7.2"
- },
- "provide": {
- "ext-ctype": "*"
- },
- "suggest": {
- "ext-ctype": "For best performance"
- },
- "type": "library",
- "extra": {
- "thanks": {
- "url": "https://github.com/symfony/polyfill",
- "name": "symfony/polyfill"
- }
- },
- "autoload": {
- "files": [
- "bootstrap.php"
- ],
- "psr-4": {
- "Symfony\\Polyfill\\Ctype\\": ""
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Gert de Pagter",
- "email": "BackEndTea@gmail.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Symfony polyfill for ctype functions",
- "homepage": "https://symfony.com",
- "keywords": [
- "compatibility",
- "ctype",
- "polyfill",
- "portable"
- ],
- "support": {
- "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0"
- },
- "funding": [
- {
- "url": "https://symfony.com/sponsor",
- "type": "custom"
- },
- {
- "url": "https://github.com/fabpot",
- "type": "github"
- },
- {
- "url": "https://github.com/nicolas-grekas",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
- "type": "tidelift"
- }
- ],
- "time": "2024-09-09T11:45:10+00:00"
- },
- {
- "name": "symfony/polyfill-php80",
- "version": "v1.33.0",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/polyfill-php80.git",
- "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608",
- "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608",
+ "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191",
+ "reference": "d8ced4d875142b6a7426000426b8abc631d6b191",
"shasum": ""
},
"require": {
@@ -1582,7 +1456,7 @@
"bootstrap.php"
],
"psr-4": {
- "Symfony\\Polyfill\\Php80\\": ""
+ "Symfony\\Polyfill\\Php84\\": ""
},
"classmap": [
"Resources/stubs"
@@ -1593,10 +1467,6 @@
"MIT"
],
"authors": [
- {
- "name": "Ion Bazan",
- "email": "ion.bazan@gmail.com"
- },
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
@@ -1606,7 +1476,7 @@
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
+ "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
@@ -1615,7 +1485,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0"
+ "source": "https://github.com/symfony/polyfill-php84/tree/v1.33.0"
},
"funding": [
{
@@ -1635,65 +1505,7 @@
"type": "tidelift"
}
],
- "time": "2025-01-02T08:10:11+00:00"
- },
- {
- "name": "webmozart/assert",
- "version": "1.11.0",
- "source": {
- "type": "git",
- "url": "https://github.com/webmozarts/assert.git",
- "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991",
- "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991",
- "shasum": ""
- },
- "require": {
- "ext-ctype": "*",
- "php": "^7.2 || ^8.0"
- },
- "conflict": {
- "phpstan/phpstan": "<0.12.20",
- "vimeo/psalm": "<4.6.1 || 4.6.2"
- },
- "require-dev": {
- "phpunit/phpunit": "^8.5.13"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.10-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Webmozart\\Assert\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Bernhard Schussek",
- "email": "bschussek@gmail.com"
- }
- ],
- "description": "Assertions to validate method input/output with nice error messages.",
- "keywords": [
- "assert",
- "check",
- "validate"
- ],
- "support": {
- "issues": "https://github.com/webmozarts/assert/issues",
- "source": "https://github.com/webmozarts/assert/tree/1.11.0"
- },
- "time": "2022-06-03T18:03:27+00:00"
+ "time": "2025-06-24T13:30:11+00:00"
},
{
"name": "wikimedia/less.php",
@@ -1772,17 +1584,75 @@
}
],
"packages-dev": [],
- "aliases": [],
- "minimum-stability": "stable",
- "stability-flags": [],
- "prefer-stable": false,
+ "aliases": [
+ {
+ "package": "ipl/html",
+ "version": "dev-main",
+ "alias": "99.x-dev",
+ "alias_normalized": "99.9999999.9999999.9999999-dev"
+ },
+ {
+ "package": "ipl/i18n",
+ "version": "dev-main",
+ "alias": "99.x-dev",
+ "alias_normalized": "99.9999999.9999999.9999999-dev"
+ },
+ {
+ "package": "ipl/orm",
+ "version": "dev-main",
+ "alias": "99.x-dev",
+ "alias_normalized": "99.9999999.9999999.9999999-dev"
+ },
+ {
+ "package": "ipl/scheduler",
+ "version": "dev-main",
+ "alias": "99.x-dev",
+ "alias_normalized": "99.9999999.9999999.9999999-dev"
+ },
+ {
+ "package": "ipl/sql",
+ "version": "dev-main",
+ "alias": "99.x-dev",
+ "alias_normalized": "99.9999999.9999999.9999999-dev"
+ },
+ {
+ "package": "ipl/stdlib",
+ "version": "dev-main",
+ "alias": "99.x-dev",
+ "alias_normalized": "99.9999999.9999999.9999999-dev"
+ },
+ {
+ "package": "ipl/validator",
+ "version": "dev-main",
+ "alias": "99.x-dev",
+ "alias_normalized": "99.9999999.9999999.9999999-dev"
+ },
+ {
+ "package": "ipl/web",
+ "version": "dev-main",
+ "alias": "99.x-dev",
+ "alias_normalized": "99.9999999.9999999.9999999-dev"
+ }
+ ],
+ "minimum-stability": "dev",
+ "stability-flags": {
+ "ipl/html": 20,
+ "ipl/i18n": 20,
+ "ipl/orm": 20,
+ "ipl/scheduler": 20,
+ "ipl/sql": 20,
+ "ipl/stdlib": 20,
+ "ipl/validator": 20,
+ "ipl/web": 20
+ },
+ "prefer-stable": true,
"prefer-lowest": false,
"platform": {
"php": ">=7.2"
},
- "platform-dev": [],
+ "platform-dev": {},
"platform-overrides": {
- "php": "7.2.9"
+ "php": "8.2"
},
"plugin-api-version": "2.6.0"
}
diff --git a/vendor/autoload.php b/vendor/autoload.php
index 076e293..5c3658e 100644
--- a/vendor/autoload.php
+++ b/vendor/autoload.php
@@ -14,12 +14,9 @@ if (PHP_VERSION_ID < 50600) {
echo $err;
}
}
- trigger_error(
- $err,
- E_USER_ERROR
- );
+ throw new RuntimeException($err);
}
require_once __DIR__ . '/composer/autoload_real.php';
-return ComposerAutoloaderInit20d4022bc196691807f55d4a47c06474::getLoader();
+return ComposerAutoloaderInit7a1692c86b6fc70eaaf43c4bee3673aa::getLoader();
diff --git a/vendor/brick/math/composer.json b/vendor/brick/math/composer.json
index ec19663..ad1dfe0 100644
--- a/vendor/brick/math/composer.json
+++ b/vendor/brick/math/composer.json
@@ -5,22 +5,26 @@
"keywords": [
"Brick",
"Math",
+ "Mathematics",
"Arbitrary-precision",
"Arithmetic",
"BigInteger",
"BigDecimal",
"BigRational",
- "Bignum"
+ "BigNumber",
+ "Bignum",
+ "Decimal",
+ "Rational",
+ "Integer"
],
"license": "MIT",
"require": {
- "php": "^7.1 || ^8.0",
- "ext-json": "*"
+ "php": "^8.2"
},
"require-dev": {
- "phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.0",
+ "phpunit/phpunit": "^11.5",
"php-coveralls/php-coveralls": "^2.2",
- "vimeo/psalm": "4.9.2"
+ "phpstan/phpstan": "2.1.22"
},
"autoload": {
"psr-4": {
diff --git a/vendor/brick/math/src/BigDecimal.php b/vendor/brick/math/src/BigDecimal.php
index 7824650..1a540c7 100644
--- a/vendor/brick/math/src/BigDecimal.php
+++ b/vendor/brick/math/src/BigDecimal.php
@@ -8,13 +8,13 @@ use Brick\Math\Exception\DivisionByZeroException;
use Brick\Math\Exception\MathException;
use Brick\Math\Exception\NegativeNumberException;
use Brick\Math\Internal\Calculator;
+use Brick\Math\Internal\CalculatorRegistry;
+use Override;
/**
* Immutable, arbitrary-precision signed decimal numbers.
- *
- * @psalm-immutable
*/
-final class BigDecimal extends BigNumber
+final readonly class BigDecimal extends BigNumber
{
/**
* The unscaled value of this decimal number.
@@ -22,25 +22,23 @@ final class BigDecimal extends BigNumber
* This is a string of digits with an optional leading minus sign.
* No leading zero must be present.
* No leading minus sign must be present if the value is 0.
- *
- * @var string
*/
- private $value;
+ private string $value;
/**
* The scale (number of digits after the decimal point) of this decimal number.
*
* This must be zero or more.
- *
- * @var int
*/
- private $scale;
+ private int $scale;
/**
* Protected constructor. Use a factory method to obtain an instance.
*
* @param string $value The unscaled value, validated.
* @param int $scale The scale, validated.
+ *
+ * @pure
*/
protected function __construct(string $value, int $scale = 0)
{
@@ -48,20 +46,10 @@ final class BigDecimal extends BigNumber
$this->scale = $scale;
}
- /**
- * Creates a BigDecimal of the given value.
- *
- * @param BigNumber|int|float|string $value
- *
- * @return BigDecimal
- *
- * @throws MathException If the value cannot be converted to a BigDecimal.
- *
- * @psalm-pure
- */
- public static function of($value) : BigNumber
+ #[Override]
+ protected static function from(BigNumber $number): static
{
- return parent::of($value)->toBigDecimal();
+ return $number->toBigDecimal();
}
/**
@@ -70,36 +58,33 @@ final class BigDecimal extends BigNumber
* Example: `(12345, 3)` will result in the BigDecimal `12.345`.
*
* @param BigNumber|int|float|string $value The unscaled value. Must be convertible to a BigInteger.
- * @param int $scale The scale of the number, positive or zero.
+ * @param int $scale The scale of the number. If negative, the scale will be set to zero
+ * and the unscaled value will be adjusted accordingly.
*
- * @return BigDecimal
- *
- * @throws \InvalidArgumentException If the scale is negative.
- *
- * @psalm-pure
+ * @pure
*/
- public static function ofUnscaledValue($value, int $scale = 0) : BigDecimal
+ public static function ofUnscaledValue(BigNumber|int|float|string $value, int $scale = 0) : BigDecimal
{
+ $value = (string) BigInteger::of($value);
+
if ($scale < 0) {
- throw new \InvalidArgumentException('The scale cannot be negative.');
+ if ($value !== '0') {
+ $value .= \str_repeat('0', -$scale);
+ }
+ $scale = 0;
}
- return new BigDecimal((string) BigInteger::of($value), $scale);
+ return new BigDecimal($value, $scale);
}
/**
* Returns a BigDecimal representing zero, with a scale of zero.
*
- * @return BigDecimal
- *
- * @psalm-pure
+ * @pure
*/
public static function zero() : BigDecimal
{
- /**
- * @psalm-suppress ImpureStaticVariable
- * @var BigDecimal|null $zero
- */
+ /** @var BigDecimal|null $zero */
static $zero;
if ($zero === null) {
@@ -112,16 +97,11 @@ final class BigDecimal extends BigNumber
/**
* Returns a BigDecimal representing one, with a scale of zero.
*
- * @return BigDecimal
- *
- * @psalm-pure
+ * @pure
*/
public static function one() : BigDecimal
{
- /**
- * @psalm-suppress ImpureStaticVariable
- * @var BigDecimal|null $one
- */
+ /** @var BigDecimal|null $one */
static $one;
if ($one === null) {
@@ -134,16 +114,11 @@ final class BigDecimal extends BigNumber
/**
* Returns a BigDecimal representing ten, with a scale of zero.
*
- * @return BigDecimal
- *
- * @psalm-pure
+ * @pure
*/
public static function ten() : BigDecimal
{
- /**
- * @psalm-suppress ImpureStaticVariable
- * @var BigDecimal|null $ten
- */
+ /** @var BigDecimal|null $ten */
static $ten;
if ($ten === null) {
@@ -160,11 +135,11 @@ final class BigDecimal extends BigNumber
*
* @param BigNumber|int|float|string $that The number to add. Must be convertible to a BigDecimal.
*
- * @return BigDecimal The result.
- *
* @throws MathException If the number is not valid, or is not convertible to a BigDecimal.
+ *
+ * @pure
*/
- public function plus($that) : BigDecimal
+ public function plus(BigNumber|int|float|string $that) : BigDecimal
{
$that = BigDecimal::of($that);
@@ -178,7 +153,7 @@ final class BigDecimal extends BigNumber
[$a, $b] = $this->scaleValues($this, $that);
- $value = Calculator::get()->add($a, $b);
+ $value = CalculatorRegistry::get()->add($a, $b);
$scale = $this->scale > $that->scale ? $this->scale : $that->scale;
return new BigDecimal($value, $scale);
@@ -191,11 +166,11 @@ final class BigDecimal extends BigNumber
*
* @param BigNumber|int|float|string $that The number to subtract. Must be convertible to a BigDecimal.
*
- * @return BigDecimal The result.
- *
* @throws MathException If the number is not valid, or is not convertible to a BigDecimal.
+ *
+ * @pure
*/
- public function minus($that) : BigDecimal
+ public function minus(BigNumber|int|float|string $that) : BigDecimal
{
$that = BigDecimal::of($that);
@@ -205,7 +180,7 @@ final class BigDecimal extends BigNumber
[$a, $b] = $this->scaleValues($this, $that);
- $value = Calculator::get()->sub($a, $b);
+ $value = CalculatorRegistry::get()->sub($a, $b);
$scale = $this->scale > $that->scale ? $this->scale : $that->scale;
return new BigDecimal($value, $scale);
@@ -218,11 +193,11 @@ final class BigDecimal extends BigNumber
*
* @param BigNumber|int|float|string $that The multiplier. Must be convertible to a BigDecimal.
*
- * @return BigDecimal The result.
- *
* @throws MathException If the multiplier is not a valid number, or is not convertible to a BigDecimal.
+ *
+ * @pure
*/
- public function multipliedBy($that) : BigDecimal
+ public function multipliedBy(BigNumber|int|float|string $that) : BigDecimal
{
$that = BigDecimal::of($that);
@@ -234,7 +209,7 @@ final class BigDecimal extends BigNumber
return $that;
}
- $value = Calculator::get()->mul($this->value, $that->value);
+ $value = CalculatorRegistry::get()->mul($this->value, $that->value);
$scale = $this->scale + $that->scale;
return new BigDecimal($value, $scale);
@@ -245,14 +220,14 @@ final class BigDecimal extends BigNumber
*
* @param BigNumber|int|float|string $that The divisor.
* @param int|null $scale The desired scale, or null to use the scale of this number.
- * @param int $roundingMode An optional rounding mode.
- *
- * @return BigDecimal
+ * @param RoundingMode $roundingMode An optional rounding mode, defaults to UNNECESSARY.
*
* @throws \InvalidArgumentException If the scale or rounding mode is invalid.
* @throws MathException If the number is invalid, is zero, or rounding was necessary.
+ *
+ * @pure
*/
- public function dividedBy($that, ?int $scale = null, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
+ public function dividedBy(BigNumber|int|float|string $that, ?int $scale = null, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
{
$that = BigDecimal::of($that);
@@ -273,7 +248,7 @@ final class BigDecimal extends BigNumber
$p = $this->valueWithMinScale($that->scale + $scale);
$q = $that->valueWithMinScale($this->scale - $scale);
- $result = Calculator::get()->divRound($p, $q, $roundingMode);
+ $result = CalculatorRegistry::get()->divRound($p, $q, $roundingMode);
return new BigDecimal($result, $scale);
}
@@ -285,12 +260,12 @@ final class BigDecimal extends BigNumber
*
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
*
- * @return BigDecimal The result.
- *
* @throws MathException If the divisor is not a valid number, is not convertible to a BigDecimal, is zero,
* or the result yields an infinite number of digits.
+ *
+ * @pure
*/
- public function exactlyDividedBy($that) : BigDecimal
+ public function exactlyDividedBy(BigNumber|int|float|string $that) : BigDecimal
{
$that = BigDecimal::of($that);
@@ -303,7 +278,7 @@ final class BigDecimal extends BigNumber
$d = \rtrim($b, '0');
$scale = \strlen($b) - \strlen($d);
- $calculator = Calculator::get();
+ $calculator = CalculatorRegistry::get();
foreach ([5, 2] as $prime) {
for (;;) {
@@ -321,16 +296,36 @@ final class BigDecimal extends BigNumber
return $this->dividedBy($that, $scale)->stripTrailingZeros();
}
+ /**
+ * Limits (clamps) this number between the given minimum and maximum values.
+ *
+ * If the number is lower than $min, returns a copy of $min.
+ * If the number is greater than $max, returns a copy of $max.
+ * Otherwise, returns this number unchanged.
+ *
+ * @param BigNumber|int|float|string $min The minimum. Must be convertible to a BigDecimal.
+ * @param BigNumber|int|float|string $max The maximum. Must be convertible to a BigDecimal.
+ *
+ * @throws MathException If min/max are not convertible to a BigDecimal.
+ */
+ public function clamp(BigNumber|int|float|string $min, BigNumber|int|float|string $max) : BigDecimal
+ {
+ if ($this->isLessThan($min)) {
+ return BigDecimal::of($min);
+ } elseif ($this->isGreaterThan($max)) {
+ return BigDecimal::of($max);
+ }
+ return $this;
+ }
+
/**
* Returns this number exponentiated to the given value.
*
* The result has a scale of `$this->scale * $exponent`.
*
- * @param int $exponent The exponent.
- *
- * @return BigDecimal The result.
- *
* @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000.
+ *
+ * @pure
*/
public function power(int $exponent) : BigDecimal
{
@@ -350,21 +345,21 @@ final class BigDecimal extends BigNumber
));
}
- return new BigDecimal(Calculator::get()->pow($this->value, $exponent), $this->scale * $exponent);
+ return new BigDecimal(CalculatorRegistry::get()->pow($this->value, $exponent), $this->scale * $exponent);
}
/**
- * Returns the quotient of the division of this number by this given one.
+ * Returns the quotient of the division of this number by the given one.
*
* The quotient has a scale of `0`.
*
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
*
- * @return BigDecimal The quotient.
- *
* @throws MathException If the divisor is not a valid decimal number, or is zero.
+ *
+ * @pure
*/
- public function quotient($that) : BigDecimal
+ public function quotient(BigNumber|int|float|string $that) : BigDecimal
{
$that = BigDecimal::of($that);
@@ -375,23 +370,23 @@ final class BigDecimal extends BigNumber
$p = $this->valueWithMinScale($that->scale);
$q = $that->valueWithMinScale($this->scale);
- $quotient = Calculator::get()->divQ($p, $q);
+ $quotient = CalculatorRegistry::get()->divQ($p, $q);
return new BigDecimal($quotient, 0);
}
/**
- * Returns the remainder of the division of this number by this given one.
+ * Returns the remainder of the division of this number by the given one.
*
* The remainder has a scale of `max($this->scale, $that->scale)`.
*
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
*
- * @return BigDecimal The remainder.
- *
* @throws MathException If the divisor is not a valid decimal number, or is zero.
+ *
+ * @pure
*/
- public function remainder($that) : BigDecimal
+ public function remainder(BigNumber|int|float|string $that) : BigDecimal
{
$that = BigDecimal::of($that);
@@ -402,7 +397,7 @@ final class BigDecimal extends BigNumber
$p = $this->valueWithMinScale($that->scale);
$q = $that->valueWithMinScale($this->scale);
- $remainder = Calculator::get()->divR($p, $q);
+ $remainder = CalculatorRegistry::get()->divR($p, $q);
$scale = $this->scale > $that->scale ? $this->scale : $that->scale;
@@ -416,11 +411,13 @@ final class BigDecimal extends BigNumber
*
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
*
- * @return BigDecimal[] An array containing the quotient and the remainder.
+ * @return array{BigDecimal, BigDecimal} An array containing the quotient and the remainder.
*
* @throws MathException If the divisor is not a valid decimal number, or is zero.
+ *
+ * @pure
*/
- public function quotientAndRemainder($that) : array
+ public function quotientAndRemainder(BigNumber|int|float|string $that) : array
{
$that = BigDecimal::of($that);
@@ -431,7 +428,7 @@ final class BigDecimal extends BigNumber
$p = $this->valueWithMinScale($that->scale);
$q = $that->valueWithMinScale($this->scale);
- [$quotient, $remainder] = Calculator::get()->divQR($p, $q);
+ [$quotient, $remainder] = CalculatorRegistry::get()->divQR($p, $q);
$scale = $this->scale > $that->scale ? $this->scale : $that->scale;
@@ -444,12 +441,10 @@ final class BigDecimal extends BigNumber
/**
* Returns the square root of this number, rounded down to the given number of decimals.
*
- * @param int $scale
- *
- * @return BigDecimal
- *
* @throws \InvalidArgumentException If the scale is negative.
* @throws NegativeNumberException If this number is negative.
+ *
+ * @pure
*/
public function sqrt(int $scale) : BigDecimal
{
@@ -481,7 +476,7 @@ final class BigDecimal extends BigNumber
$value = \substr($value, 0, $addDigits);
}
- $value = Calculator::get()->sqrt($value);
+ $value = CalculatorRegistry::get()->sqrt($value);
return new BigDecimal($value, $scale);
}
@@ -489,9 +484,7 @@ final class BigDecimal extends BigNumber
/**
* Returns a copy of this BigDecimal with the decimal point moved $n places to the left.
*
- * @param int $n
- *
- * @return BigDecimal
+ * @pure
*/
public function withPointMovedLeft(int $n) : BigDecimal
{
@@ -509,9 +502,7 @@ final class BigDecimal extends BigNumber
/**
* Returns a copy of this BigDecimal with the decimal point moved $n places to the right.
*
- * @param int $n
- *
- * @return BigDecimal
+ * @pure
*/
public function withPointMovedRight(int $n) : BigDecimal
{
@@ -539,7 +530,7 @@ final class BigDecimal extends BigNumber
/**
* Returns a copy of this BigDecimal with any trailing zeros removed from the fractional part.
*
- * @return BigDecimal
+ * @pure
*/
public function stripTrailingZeros() : BigDecimal
{
@@ -572,7 +563,7 @@ final class BigDecimal extends BigNumber
/**
* Returns the absolute value of this number.
*
- * @return BigDecimal
+ * @pure
*/
public function abs() : BigDecimal
{
@@ -582,17 +573,15 @@ final class BigDecimal extends BigNumber
/**
* Returns the negated value of this number.
*
- * @return BigDecimal
+ * @pure
*/
public function negated() : BigDecimal
{
- return new BigDecimal(Calculator::get()->neg($this->value), $this->scale);
+ return new BigDecimal(CalculatorRegistry::get()->neg($this->value), $this->scale);
}
- /**
- * {@inheritdoc}
- */
- public function compareTo($that) : int
+ #[Override]
+ public function compareTo(BigNumber|int|float|string $that) : int
{
$that = BigNumber::of($that);
@@ -603,42 +592,69 @@ final class BigDecimal extends BigNumber
if ($that instanceof BigDecimal) {
[$a, $b] = $this->scaleValues($this, $that);
- return Calculator::get()->cmp($a, $b);
+ return CalculatorRegistry::get()->cmp($a, $b);
}
return - $that->compareTo($this);
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function getSign() : int
{
return ($this->value === '0') ? 0 : (($this->value[0] === '-') ? -1 : 1);
}
/**
- * @return BigInteger
+ * @pure
*/
public function getUnscaledValue() : BigInteger
{
- return BigInteger::create($this->value);
+ return self::newBigInteger($this->value);
}
/**
- * @return int
+ * @pure
*/
public function getScale() : int
{
return $this->scale;
}
+ /**
+ * Returns the number of significant digits in the number.
+ *
+ * This is the number of digits to both sides of the decimal point, stripped of leading zeros.
+ * The sign has no impact on the result.
+ *
+ * Examples:
+ * 0 => 0
+ * 0.0 => 0
+ * 123 => 3
+ * 123.456 => 6
+ * 0.00123 => 3
+ * 0.0012300 => 5
+ *
+ * @pure
+ */
+ public function getPrecision(): int
+ {
+ $value = $this->value;
+
+ if ($value === '0') {
+ return 0;
+ }
+
+ $length = \strlen($value);
+
+ return ($value[0] === '-') ? $length - 1 : $length;
+ }
+
/**
* Returns a string representing the integral part of this decimal number.
*
* Example: `-123.456` => `-123`.
*
- * @return string
+ * @pure
*/
public function getIntegralPart() : string
{
@@ -658,7 +674,7 @@ final class BigDecimal extends BigNumber
*
* Examples: `-123.456` => '456', `123` => ''.
*
- * @return string
+ * @pure
*/
public function getFractionalPart() : string
{
@@ -674,46 +690,38 @@ final class BigDecimal extends BigNumber
/**
* Returns whether this decimal number has a non-zero fractional part.
*
- * @return bool
+ * @pure
*/
public function hasNonZeroFractionalPart() : bool
{
return $this->getFractionalPart() !== \str_repeat('0', $this->scale);
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function toBigInteger() : BigInteger
{
$zeroScaleDecimal = $this->scale === 0 ? $this : $this->dividedBy(1, 0);
- return BigInteger::create($zeroScaleDecimal->value);
+ return self::newBigInteger($zeroScaleDecimal->value);
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function toBigDecimal() : BigDecimal
{
return $this;
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function toBigRational() : BigRational
{
- $numerator = BigInteger::create($this->value);
- $denominator = BigInteger::create('1' . \str_repeat('0', $this->scale));
+ $numerator = self::newBigInteger($this->value);
+ $denominator = self::newBigInteger('1' . \str_repeat('0', $this->scale));
- return BigRational::create($numerator, $denominator, false);
+ return self::newBigRational($numerator, $denominator, false);
}
- /**
- * {@inheritdoc}
- */
- public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
+ #[Override]
+ public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
{
if ($scale === $this->scale) {
return $this;
@@ -722,33 +730,32 @@ final class BigDecimal extends BigNumber
return $this->dividedBy(BigDecimal::one(), $scale, $roundingMode);
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function toInt() : int
{
return $this->toBigInteger()->toInt();
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function toFloat() : float
{
return (float) (string) $this;
}
/**
- * {@inheritdoc}
+ * @return numeric-string
*/
+ #[Override]
public function __toString() : string
{
if ($this->scale === 0) {
+ /** @var numeric-string */
return $this->value;
}
$value = $this->getUnscaledValueWithLeadingZeros();
+ /** @phpstan-ignore return.type */
return \substr($value, 0, -$this->scale) . '.' . \substr($value, -$this->scale);
}
@@ -768,67 +775,29 @@ final class BigDecimal extends BigNumber
* This method is only here to allow unserializing the object and cannot be accessed directly.
*
* @internal
- * @psalm-suppress RedundantPropertyInitializationCheck
*
* @param array{value: string, scale: int} $data
*
- * @return void
- *
* @throws \LogicException
*/
public function __unserialize(array $data): void
{
+ /** @phpstan-ignore isset.initializedProperty */
if (isset($this->value)) {
throw new \LogicException('__unserialize() is an internal function, it must not be called directly.');
}
+ /** @phpstan-ignore deadCode.unreachable */
$this->value = $data['value'];
$this->scale = $data['scale'];
}
- /**
- * This method is required by interface Serializable and SHOULD NOT be accessed directly.
- *
- * @internal
- *
- * @return string
- */
- public function serialize() : string
- {
- return $this->value . ':' . $this->scale;
- }
-
- /**
- * This method is only here to implement interface Serializable and cannot be accessed directly.
- *
- * @internal
- * @psalm-suppress RedundantPropertyInitializationCheck
- *
- * @param string $value
- *
- * @return void
- *
- * @throws \LogicException
- */
- public function unserialize($value) : void
- {
- if (isset($this->value)) {
- throw new \LogicException('unserialize() is an internal function, it must not be called directly.');
- }
-
- [$value, $scale] = \explode(':', $value);
-
- $this->value = $value;
- $this->scale = (int) $scale;
- }
-
/**
* Puts the internal values of the given decimal numbers on the same scale.
*
- * @param BigDecimal $x The first decimal number.
- * @param BigDecimal $y The second decimal number.
- *
* @return array{string, string} The scaled integer values of $x and $y.
+ *
+ * @pure
*/
private function scaleValues(BigDecimal $x, BigDecimal $y) : array
{
@@ -845,9 +814,7 @@ final class BigDecimal extends BigNumber
}
/**
- * @param int $scale
- *
- * @return string
+ * @pure
*/
private function valueWithMinScale(int $scale) : string
{
@@ -863,7 +830,7 @@ final class BigDecimal extends BigNumber
/**
* Adds leading zeros if necessary to the unscaled value to represent the full decimal number.
*
- * @return string
+ * @pure
*/
private function getUnscaledValueWithLeadingZeros() : string
{
diff --git a/vendor/brick/math/src/BigInteger.php b/vendor/brick/math/src/BigInteger.php
index f213fbe..48a7bb3 100644
--- a/vendor/brick/math/src/BigInteger.php
+++ b/vendor/brick/math/src/BigInteger.php
@@ -10,51 +10,41 @@ use Brick\Math\Exception\MathException;
use Brick\Math\Exception\NegativeNumberException;
use Brick\Math\Exception\NumberFormatException;
use Brick\Math\Internal\Calculator;
+use Brick\Math\Internal\CalculatorRegistry;
+use Override;
/**
* An arbitrary-size integer.
*
* All methods accepting a number as a parameter accept either a BigInteger instance,
* an integer, or a string representing an arbitrary size integer.
- *
- * @psalm-immutable
*/
-final class BigInteger extends BigNumber
+final readonly class BigInteger extends BigNumber
{
/**
* The value, as a string of digits with optional leading minus sign.
*
* No leading zeros must be present.
* No leading minus sign must be present if the number is zero.
- *
- * @var string
*/
- private $value;
+ private string $value;
/**
* Protected constructor. Use a factory method to obtain an instance.
*
* @param string $value A string of digits, with optional leading minus sign.
+ *
+ * @pure
*/
protected function __construct(string $value)
{
$this->value = $value;
}
- /**
- * Creates a BigInteger of the given value.
- *
- * @param BigNumber|int|float|string $value
- *
- * @return BigInteger
- *
- * @throws MathException If the value cannot be converted to a BigInteger.
- *
- * @psalm-pure
- */
- public static function of($value) : BigNumber
+ #[Override]
+ protected static function from(BigNumber $number): static
{
- return parent::of($value)->toBigInteger();
+ return $number->toBigInteger();
}
/**
@@ -71,12 +61,10 @@ final class BigInteger extends BigNumber
* @param string $number The number to convert, in the given base.
* @param int $base The base of the number, between 2 and 36.
*
- * @return BigInteger
- *
* @throws NumberFormatException If the number is empty, or contains invalid chars for the given base.
* @throws \InvalidArgumentException If the base is out of range.
*
- * @psalm-pure
+ * @pure
*/
public static function fromBase(string $number, int $base) : BigInteger
{
@@ -125,7 +113,7 @@ final class BigInteger extends BigNumber
return new BigInteger($sign . $number);
}
- $result = Calculator::get()->fromBase($number, $base);
+ $result = CalculatorRegistry::get()->fromBase($number, $base);
return new BigInteger($sign . $result);
}
@@ -138,12 +126,10 @@ final class BigInteger extends BigNumber
* @param string $number The number to parse.
* @param string $alphabet The alphabet, for example '01' for base 2, or '01234567' for base 8.
*
- * @return BigInteger
- *
* @throws NumberFormatException If the given number is empty or contains invalid chars for the given alphabet.
* @throws \InvalidArgumentException If the alphabet does not contain at least 2 chars.
*
- * @psalm-pure
+ * @pure
*/
public static function fromArbitraryBase(string $number, string $alphabet) : BigInteger
{
@@ -163,7 +149,7 @@ final class BigInteger extends BigNumber
throw NumberFormatException::charNotInAlphabet($matches[0]);
}
- $number = Calculator::get()->fromArbitraryBase($number, $alphabet, $base);
+ $number = CalculatorRegistry::get()->fromArbitraryBase($number, $alphabet, $base);
return new BigInteger($number);
}
@@ -183,9 +169,9 @@ final class BigInteger extends BigNumber
* @param bool $signed Whether to interpret as a signed number in two's-complement representation with a leading
* sign bit.
*
- * @return BigInteger
- *
* @throws NumberFormatException If the string is empty.
+ *
+ * @pure
*/
public static function fromBytes(string $value, bool $signed = true) : BigInteger
{
@@ -217,14 +203,10 @@ final class BigInteger extends BigNumber
*
* Using the default random bytes generator, this method is suitable for cryptographic use.
*
- * @psalm-param callable(int): string $randomBytesGenerator
- *
- * @param int $numBits The number of bits.
- * @param callable|null $randomBytesGenerator A function that accepts a number of bytes as an integer, and returns a
- * string of random bytes of the given length. Defaults to the
- * `random_bytes()` function.
- *
- * @return BigInteger
+ * @param int $numBits The number of bits.
+ * @param (callable(int): string)|null $randomBytesGenerator A function that accepts a number of bytes, and returns
+ * a string of random bytes of the given length. Defaults
+ * to the `random_bytes()` function.
*
* @throws \InvalidArgumentException If $numBits is negative.
*/
@@ -239,9 +221,10 @@ final class BigInteger extends BigNumber
}
if ($randomBytesGenerator === null) {
- $randomBytesGenerator = 'random_bytes';
+ $randomBytesGenerator = random_bytes(...);
}
+ /** @var int<1, max> $byteLength */
$byteLength = \intdiv($numBits - 1, 8) + 1;
$extraBits = ($byteLength * 8 - $numBits);
@@ -258,21 +241,20 @@ final class BigInteger extends BigNumber
*
* Using the default random bytes generator, this method is suitable for cryptographic use.
*
- * @psalm-param (callable(int): string)|null $randomBytesGenerator
- *
- * @param BigNumber|int|float|string $min The lower bound. Must be convertible to a BigInteger.
- * @param BigNumber|int|float|string $max The upper bound. Must be convertible to a BigInteger.
- * @param callable|null $randomBytesGenerator A function that accepts a number of bytes as an integer,
- * and returns a string of random bytes of the given length.
- * Defaults to the `random_bytes()` function.
- *
- * @return BigInteger
+ * @param BigNumber|int|float|string $min The lower bound. Must be convertible to a BigInteger.
+ * @param BigNumber|int|float|string $max The upper bound. Must be convertible to a BigInteger.
+ * @param (callable(int): string)|null $randomBytesGenerator A function that accepts a number of bytes, and returns
+ * a string of random bytes of the given length. Defaults
+ * to the `random_bytes()` function.
*
* @throws MathException If one of the parameters cannot be converted to a BigInteger,
* or `$min` is greater than `$max`.
*/
- public static function randomRange($min, $max, ?callable $randomBytesGenerator = null) : BigInteger
- {
+ public static function randomRange(
+ BigNumber|int|float|string $min,
+ BigNumber|int|float|string $max,
+ ?callable $randomBytesGenerator = null
+ ) : BigInteger {
$min = BigInteger::of($min);
$max = BigInteger::of($max);
@@ -298,16 +280,11 @@ final class BigInteger extends BigNumber
/**
* Returns a BigInteger representing zero.
*
- * @return BigInteger
- *
- * @psalm-pure
+ * @pure
*/
public static function zero() : BigInteger
{
- /**
- * @psalm-suppress ImpureStaticVariable
- * @var BigInteger|null $zero
- */
+ /** @var BigInteger|null $zero */
static $zero;
if ($zero === null) {
@@ -320,16 +297,11 @@ final class BigInteger extends BigNumber
/**
* Returns a BigInteger representing one.
*
- * @return BigInteger
- *
- * @psalm-pure
+ * @pure
*/
public static function one() : BigInteger
{
- /**
- * @psalm-suppress ImpureStaticVariable
- * @var BigInteger|null $one
- */
+ /** @var BigInteger|null $one */
static $one;
if ($one === null) {
@@ -342,16 +314,11 @@ final class BigInteger extends BigNumber
/**
* Returns a BigInteger representing ten.
*
- * @return BigInteger
- *
- * @psalm-pure
+ * @pure
*/
public static function ten() : BigInteger
{
- /**
- * @psalm-suppress ImpureStaticVariable
- * @var BigInteger|null $ten
- */
+ /** @var BigInteger|null $ten */
static $ten;
if ($ten === null) {
@@ -361,16 +328,34 @@ final class BigInteger extends BigNumber
return $ten;
}
+ /**
+ * @pure
+ */
+ public static function gcdMultiple(BigInteger $a, BigInteger ...$n): BigInteger
+ {
+ $result = $a;
+
+ foreach ($n as $next) {
+ $result = $result->gcd($next);
+
+ if ($result->isEqualTo(1)) {
+ return $result;
+ }
+ }
+
+ return $result;
+ }
+
/**
* Returns the sum of this number and the given one.
*
* @param BigNumber|int|float|string $that The number to add. Must be convertible to a BigInteger.
*
- * @return BigInteger The result.
- *
* @throws MathException If the number is not valid, or is not convertible to a BigInteger.
+ *
+ * @pure
*/
- public function plus($that) : BigInteger
+ public function plus(BigNumber|int|float|string $that) : BigInteger
{
$that = BigInteger::of($that);
@@ -382,7 +367,7 @@ final class BigInteger extends BigNumber
return $that;
}
- $value = Calculator::get()->add($this->value, $that->value);
+ $value = CalculatorRegistry::get()->add($this->value, $that->value);
return new BigInteger($value);
}
@@ -392,11 +377,11 @@ final class BigInteger extends BigNumber
*
* @param BigNumber|int|float|string $that The number to subtract. Must be convertible to a BigInteger.
*
- * @return BigInteger The result.
- *
* @throws MathException If the number is not valid, or is not convertible to a BigInteger.
+ *
+ * @pure
*/
- public function minus($that) : BigInteger
+ public function minus(BigNumber|int|float|string $that) : BigInteger
{
$that = BigInteger::of($that);
@@ -404,7 +389,7 @@ final class BigInteger extends BigNumber
return $this;
}
- $value = Calculator::get()->sub($this->value, $that->value);
+ $value = CalculatorRegistry::get()->sub($this->value, $that->value);
return new BigInteger($value);
}
@@ -414,11 +399,11 @@ final class BigInteger extends BigNumber
*
* @param BigNumber|int|float|string $that The multiplier. Must be convertible to a BigInteger.
*
- * @return BigInteger The result.
- *
* @throws MathException If the multiplier is not a valid number, or is not convertible to a BigInteger.
+ *
+ * @pure
*/
- public function multipliedBy($that) : BigInteger
+ public function multipliedBy(BigNumber|int|float|string $that) : BigInteger
{
$that = BigInteger::of($that);
@@ -430,7 +415,7 @@ final class BigInteger extends BigNumber
return $that;
}
- $value = Calculator::get()->mul($this->value, $that->value);
+ $value = CalculatorRegistry::get()->mul($this->value, $that->value);
return new BigInteger($value);
}
@@ -439,14 +424,14 @@ final class BigInteger extends BigNumber
* Returns the result of the division of this number by the given one.
*
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
- * @param int $roundingMode An optional rounding mode.
- *
- * @return BigInteger The result.
+ * @param RoundingMode $roundingMode An optional rounding mode, defaults to UNNECESSARY.
*
* @throws MathException If the divisor is not a valid number, is not convertible to a BigInteger, is zero,
* or RoundingMode::UNNECESSARY is used and the remainder is not zero.
+ *
+ * @pure
*/
- public function dividedBy($that, int $roundingMode = RoundingMode::UNNECESSARY) : BigInteger
+ public function dividedBy(BigNumber|int|float|string $that, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigInteger
{
$that = BigInteger::of($that);
@@ -458,19 +443,40 @@ final class BigInteger extends BigNumber
throw DivisionByZeroException::divisionByZero();
}
- $result = Calculator::get()->divRound($this->value, $that->value, $roundingMode);
+ $result = CalculatorRegistry::get()->divRound($this->value, $that->value, $roundingMode);
return new BigInteger($result);
}
+ /**
+ * Limits (clamps) this number between the given minimum and maximum values.
+ *
+ * If the number is lower than $min, returns a copy of $min.
+ * If the number is greater than $max, returns a copy of $max.
+ * Otherwise, returns this number unchanged.
+ *
+ * @param BigNumber|int|float|string $min The minimum. Must be convertible to a BigInteger.
+ * @param BigNumber|int|float|string $max The maximum. Must be convertible to a BigInteger.
+ *
+ * @throws MathException If min/max are not convertible to a BigInteger.
+ */
+ public function clamp(BigNumber|int|float|string $min, BigNumber|int|float|string $max) : BigInteger
+ {
+ if ($this->isLessThan($min)) {
+ return BigInteger::of($min);
+ } elseif ($this->isGreaterThan($max)) {
+ return BigInteger::of($max);
+ }
+ return $this;
+ }
+
+
/**
* Returns this number exponentiated to the given value.
*
- * @param int $exponent The exponent.
- *
- * @return BigInteger The result.
- *
* @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000.
+ *
+ * @pure
*/
public function power(int $exponent) : BigInteger
{
@@ -490,7 +496,7 @@ final class BigInteger extends BigNumber
));
}
- return new BigInteger(Calculator::get()->pow($this->value, $exponent));
+ return new BigInteger(CalculatorRegistry::get()->pow($this->value, $exponent));
}
/**
@@ -498,11 +504,11 @@ final class BigInteger extends BigNumber
*
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
*
- * @return BigInteger
- *
* @throws DivisionByZeroException If the divisor is zero.
+ *
+ * @pure
*/
- public function quotient($that) : BigInteger
+ public function quotient(BigNumber|int|float|string $that) : BigInteger
{
$that = BigInteger::of($that);
@@ -514,7 +520,7 @@ final class BigInteger extends BigNumber
throw DivisionByZeroException::divisionByZero();
}
- $quotient = Calculator::get()->divQ($this->value, $that->value);
+ $quotient = CalculatorRegistry::get()->divQ($this->value, $that->value);
return new BigInteger($quotient);
}
@@ -526,11 +532,11 @@ final class BigInteger extends BigNumber
*
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
*
- * @return BigInteger
- *
* @throws DivisionByZeroException If the divisor is zero.
+ *
+ * @pure
*/
- public function remainder($that) : BigInteger
+ public function remainder(BigNumber|int|float|string $that) : BigInteger
{
$that = BigInteger::of($that);
@@ -542,7 +548,7 @@ final class BigInteger extends BigNumber
throw DivisionByZeroException::divisionByZero();
}
- $remainder = Calculator::get()->divR($this->value, $that->value);
+ $remainder = CalculatorRegistry::get()->divR($this->value, $that->value);
return new BigInteger($remainder);
}
@@ -552,11 +558,13 @@ final class BigInteger extends BigNumber
*
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
*
- * @return BigInteger[] An array containing the quotient and the remainder.
+ * @return array{BigInteger, BigInteger} An array containing the quotient and the remainder.
*
* @throws DivisionByZeroException If the divisor is zero.
+ *
+ * @pure
*/
- public function quotientAndRemainder($that) : array
+ public function quotientAndRemainder(BigNumber|int|float|string $that) : array
{
$that = BigInteger::of($that);
@@ -564,7 +572,7 @@ final class BigInteger extends BigNumber
throw DivisionByZeroException::divisionByZero();
}
- [$quotient, $remainder] = Calculator::get()->divQR($this->value, $that->value);
+ [$quotient, $remainder] = CalculatorRegistry::get()->divQR($this->value, $that->value);
return [
new BigInteger($quotient),
@@ -582,11 +590,11 @@ final class BigInteger extends BigNumber
*
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
*
- * @return BigInteger
- *
* @throws DivisionByZeroException If the divisor is zero.
+ *
+ * @pure
*/
- public function mod($that) : BigInteger
+ public function mod(BigNumber|int|float|string $that) : BigInteger
{
$that = BigInteger::of($that);
@@ -594,7 +602,7 @@ final class BigInteger extends BigNumber
throw DivisionByZeroException::modulusMustNotBeZero();
}
- $value = Calculator::get()->mod($this->value, $that->value);
+ $value = CalculatorRegistry::get()->mod($this->value, $that->value);
return new BigInteger($value);
}
@@ -602,14 +610,12 @@ final class BigInteger extends BigNumber
/**
* Returns the modular multiplicative inverse of this BigInteger modulo $m.
*
- * @param BigInteger $m
- *
- * @return BigInteger
- *
* @throws DivisionByZeroException If $m is zero.
* @throws NegativeNumberException If $m is negative.
* @throws MathException If this BigInteger has no multiplicative inverse mod m (that is, this BigInteger
* is not relatively prime to m).
+ *
+ * @pure
*/
public function modInverse(BigInteger $m) : BigInteger
{
@@ -625,7 +631,7 @@ final class BigInteger extends BigNumber
return BigInteger::zero();
}
- $value = Calculator::get()->modInverse($this->value, $m->value);
+ $value = CalculatorRegistry::get()->modInverse($this->value, $m->value);
if ($value === null) {
throw new MathException('Unable to compute the modInverse for the given modulus.');
@@ -642,12 +648,12 @@ final class BigInteger extends BigNumber
* @param BigNumber|int|float|string $exp The exponent. Must be positive or zero.
* @param BigNumber|int|float|string $mod The modulus. Must be strictly positive.
*
- * @return BigInteger
- *
* @throws NegativeNumberException If any of the operands is negative.
* @throws DivisionByZeroException If the modulus is zero.
+ *
+ * @pure
*/
- public function modPow($exp, $mod) : BigInteger
+ public function modPow(BigNumber|int|float|string $exp, BigNumber|int|float|string $mod) : BigInteger
{
$exp = BigInteger::of($exp);
$mod = BigInteger::of($mod);
@@ -660,7 +666,7 @@ final class BigInteger extends BigNumber
throw DivisionByZeroException::modulusMustNotBeZero();
}
- $result = Calculator::get()->modPow($this->value, $exp->value, $mod->value);
+ $result = CalculatorRegistry::get()->modPow($this->value, $exp->value, $mod->value);
return new BigInteger($result);
}
@@ -672,9 +678,9 @@ final class BigInteger extends BigNumber
*
* @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number.
*
- * @return BigInteger
+ * @pure
*/
- public function gcd($that) : BigInteger
+ public function gcd(BigNumber|int|float|string $that) : BigInteger
{
$that = BigInteger::of($that);
@@ -686,7 +692,7 @@ final class BigInteger extends BigNumber
return $that;
}
- $value = Calculator::get()->gcd($this->value, $that->value);
+ $value = CalculatorRegistry::get()->gcd($this->value, $that->value);
return new BigInteger($value);
}
@@ -696,9 +702,9 @@ final class BigInteger extends BigNumber
*
* The result is the largest x such that x² ≤ n.
*
- * @return BigInteger
- *
* @throws NegativeNumberException If this number is negative.
+ *
+ * @pure
*/
public function sqrt() : BigInteger
{
@@ -706,7 +712,7 @@ final class BigInteger extends BigNumber
throw new NegativeNumberException('Cannot calculate the square root of a negative number.');
}
- $value = Calculator::get()->sqrt($this->value);
+ $value = CalculatorRegistry::get()->sqrt($this->value);
return new BigInteger($value);
}
@@ -714,7 +720,7 @@ final class BigInteger extends BigNumber
/**
* Returns the absolute value of this number.
*
- * @return BigInteger
+ * @pure
*/
public function abs() : BigInteger
{
@@ -724,11 +730,11 @@ final class BigInteger extends BigNumber
/**
* Returns the inverse of this number.
*
- * @return BigInteger
+ * @pure
*/
public function negated() : BigInteger
{
- return new BigInteger(Calculator::get()->neg($this->value));
+ return new BigInteger(CalculatorRegistry::get()->neg($this->value));
}
/**
@@ -738,13 +744,13 @@ final class BigInteger extends BigNumber
*
* @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number.
*
- * @return BigInteger
+ * @pure
*/
- public function and($that) : BigInteger
+ public function and(BigNumber|int|float|string $that) : BigInteger
{
$that = BigInteger::of($that);
- return new BigInteger(Calculator::get()->and($this->value, $that->value));
+ return new BigInteger(CalculatorRegistry::get()->and($this->value, $that->value));
}
/**
@@ -754,13 +760,13 @@ final class BigInteger extends BigNumber
*
* @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number.
*
- * @return BigInteger
+ * @pure
*/
- public function or($that) : BigInteger
+ public function or(BigNumber|int|float|string $that) : BigInteger
{
$that = BigInteger::of($that);
- return new BigInteger(Calculator::get()->or($this->value, $that->value));
+ return new BigInteger(CalculatorRegistry::get()->or($this->value, $that->value));
}
/**
@@ -770,19 +776,19 @@ final class BigInteger extends BigNumber
*
* @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number.
*
- * @return BigInteger
+ * @pure
*/
- public function xor($that) : BigInteger
+ public function xor(BigNumber|int|float|string $that) : BigInteger
{
$that = BigInteger::of($that);
- return new BigInteger(Calculator::get()->xor($this->value, $that->value));
+ return new BigInteger(CalculatorRegistry::get()->xor($this->value, $that->value));
}
/**
* Returns the bitwise-not of this BigInteger.
*
- * @return BigInteger
+ * @pure
*/
public function not() : BigInteger
{
@@ -792,9 +798,7 @@ final class BigInteger extends BigNumber
/**
* Returns the integer left shifted by a given number of bits.
*
- * @param int $distance The distance to shift.
- *
- * @return BigInteger
+ * @pure
*/
public function shiftedLeft(int $distance) : BigInteger
{
@@ -812,9 +816,7 @@ final class BigInteger extends BigNumber
/**
* Returns the integer right shifted by a given number of bits.
*
- * @param int $distance The distance to shift.
- *
- * @return BigInteger
+ * @pure
*/
public function shiftedRight(int $distance) : BigInteger
{
@@ -841,7 +843,7 @@ final class BigInteger extends BigNumber
* For positive BigIntegers, this is equivalent to the number of bits in the ordinary binary representation.
* Computes (ceil(log2(this < 0 ? -this : this+1))).
*
- * @return int
+ * @pure
*/
public function getBitLength() : int
{
@@ -861,7 +863,7 @@ final class BigInteger extends BigNumber
*
* Returns -1 if this BigInteger contains no one bits.
*
- * @return int
+ * @pure
*/
public function getLowestSetBit() : int
{
@@ -882,7 +884,7 @@ final class BigInteger extends BigNumber
/**
* Returns whether this number is even.
*
- * @return bool
+ * @pure
*/
public function isEven() : bool
{
@@ -892,7 +894,7 @@ final class BigInteger extends BigNumber
/**
* Returns whether this number is odd.
*
- * @return bool
+ * @pure
*/
public function isOdd() : bool
{
@@ -906,9 +908,9 @@ final class BigInteger extends BigNumber
*
* @param int $n The bit to test, 0-based.
*
- * @return bool
- *
* @throws \InvalidArgumentException If the bit to test is negative.
+ *
+ * @pure
*/
public function testBit(int $n) : bool
{
@@ -919,63 +921,49 @@ final class BigInteger extends BigNumber
return $this->shiftedRight($n)->isOdd();
}
- /**
- * {@inheritdoc}
- */
- public function compareTo($that) : int
+ #[Override]
+ public function compareTo(BigNumber|int|float|string $that) : int
{
$that = BigNumber::of($that);
if ($that instanceof BigInteger) {
- return Calculator::get()->cmp($this->value, $that->value);
+ return CalculatorRegistry::get()->cmp($this->value, $that->value);
}
return - $that->compareTo($this);
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function getSign() : int
{
return ($this->value === '0') ? 0 : (($this->value[0] === '-') ? -1 : 1);
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function toBigInteger() : BigInteger
{
return $this;
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function toBigDecimal() : BigDecimal
{
- return BigDecimal::create($this->value);
+ return self::newBigDecimal($this->value);
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function toBigRational() : BigRational
{
- return BigRational::create($this, BigInteger::one(), false);
+ return self::newBigRational($this, BigInteger::one(), false);
}
- /**
- * {@inheritdoc}
- */
- public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
+ #[Override]
+ public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
{
return $this->toBigDecimal()->toScale($scale, $roundingMode);
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function toInt() : int
{
$intValue = (int) $this->value;
@@ -987,9 +975,7 @@ final class BigInteger extends BigNumber
return $intValue;
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function toFloat() : float
{
return (float) $this->value;
@@ -1000,11 +986,9 @@ final class BigInteger extends BigNumber
*
* The output will always be lowercase for bases greater than 10.
*
- * @param int $base
- *
- * @return string
- *
* @throws \InvalidArgumentException If the base is out of range.
+ *
+ * @pure
*/
public function toBase(int $base) : string
{
@@ -1016,7 +1000,7 @@ final class BigInteger extends BigNumber
throw new \InvalidArgumentException(\sprintf('Base %d is out of range [2, 36]', $base));
}
- return Calculator::get()->toBase($this->value, $base);
+ return CalculatorRegistry::get()->toBase($this->value, $base);
}
/**
@@ -1027,10 +1011,10 @@ final class BigInteger extends BigNumber
*
* @param string $alphabet The alphabet, for example '01' for base 2, or '01234567' for base 8.
*
- * @return string
- *
* @throws NegativeNumberException If this number is negative.
* @throws \InvalidArgumentException If the given alphabet does not contain at least 2 chars.
+ *
+ * @pure
*/
public function toArbitraryBase(string $alphabet) : string
{
@@ -1044,7 +1028,7 @@ final class BigInteger extends BigNumber
throw new NegativeNumberException(__FUNCTION__ . '() does not support negative numbers.');
}
- return Calculator::get()->toArbitraryBase($this->value, $alphabet, $base);
+ return CalculatorRegistry::get()->toArbitraryBase($this->value, $alphabet, $base);
}
/**
@@ -1063,9 +1047,9 @@ final class BigInteger extends BigNumber
*
* @param bool $signed Whether to output a signed number in two's-complement representation with a leading sign bit.
*
- * @return string
- *
* @throws NegativeNumberException If $signed is false, and the number is negative.
+ *
+ * @pure
*/
public function toBytes(bool $signed = true) : string
{
@@ -1105,14 +1089,19 @@ final class BigInteger extends BigNumber
}
}
- return \hex2bin($hex);
+ $result = \hex2bin($hex);
+ assert($result !== false);
+
+ return $result;
}
/**
- * {@inheritdoc}
+ * @return numeric-string
*/
+ #[Override]
public function __toString() : string
{
+ /** @var numeric-string */
return $this->value;
}
@@ -1132,53 +1121,19 @@ final class BigInteger extends BigNumber
* This method is only here to allow unserializing the object and cannot be accessed directly.
*
* @internal
- * @psalm-suppress RedundantPropertyInitializationCheck
*
* @param array{value: string} $data
*
- * @return void
- *
* @throws \LogicException
*/
public function __unserialize(array $data): void
{
+ /** @phpstan-ignore isset.initializedProperty */
if (isset($this->value)) {
throw new \LogicException('__unserialize() is an internal function, it must not be called directly.');
}
+ /** @phpstan-ignore deadCode.unreachable */
$this->value = $data['value'];
}
-
- /**
- * This method is required by interface Serializable and SHOULD NOT be accessed directly.
- *
- * @internal
- *
- * @return string
- */
- public function serialize() : string
- {
- return $this->value;
- }
-
- /**
- * This method is only here to implement interface Serializable and cannot be accessed directly.
- *
- * @internal
- * @psalm-suppress RedundantPropertyInitializationCheck
- *
- * @param string $value
- *
- * @return void
- *
- * @throws \LogicException
- */
- public function unserialize($value) : void
- {
- if (isset($this->value)) {
- throw new \LogicException('unserialize() is an internal function, it must not be called directly.');
- }
-
- $this->value = $value;
- }
}
diff --git a/vendor/brick/math/src/BigNumber.php b/vendor/brick/math/src/BigNumber.php
index 38c8c55..2fbdf69 100644
--- a/vendor/brick/math/src/BigNumber.php
+++ b/vendor/brick/math/src/BigNumber.php
@@ -8,38 +8,46 @@ use Brick\Math\Exception\DivisionByZeroException;
use Brick\Math\Exception\MathException;
use Brick\Math\Exception\NumberFormatException;
use Brick\Math\Exception\RoundingNecessaryException;
+use Override;
/**
- * Common interface for arbitrary-precision rational numbers.
+ * Base class for arbitrary-precision numbers.
*
- * @psalm-immutable
+ * This class is sealed: it is part of the public API but should not be subclassed in userland.
+ * Protected methods may change in any version.
+ *
+ * @phpstan-sealed BigInteger|BigDecimal|BigRational
*/
-abstract class BigNumber implements \Serializable, \JsonSerializable
+abstract readonly class BigNumber implements \JsonSerializable, \Stringable
{
/**
- * The regular expression used to parse integer, decimal and rational numbers.
+ * The regular expression used to parse integer or decimal numbers.
*/
- private const PARSE_REGEXP =
+ private const PARSE_REGEXP_NUMERICAL =
'/^' .
'(?[\-\+])?' .
- '(?:' .
- '(?:' .
- '(?[0-9]+)?' .
- '(?\.)?' .
- '(?[0-9]+)?' .
- '(?:[eE](?[\-\+]?[0-9]+))?' .
- ')|(?:' .
- '(?[0-9]+)' .
- '\/?' .
- '(?[0-9]+)' .
- ')' .
- ')' .
+ '(?[0-9]+)?' .
+ '(?\.)?' .
+ '(?[0-9]+)?' .
+ '(?:[eE](?[\-\+]?[0-9]+))?' .
+ '$/';
+
+ /**
+ * The regular expression used to parse rational numbers.
+ */
+ private const PARSE_REGEXP_RATIONAL =
+ '/^' .
+ '(?[\-\+])?' .
+ '(?[0-9]+)' .
+ '\/?' .
+ '(?[0-9]+)' .
'$/';
/**
* Creates a BigNumber of the given value.
*
- * The concrete return type is dependent on the given value, with the following rules:
+ * When of() is called on BigNumber, the concrete return type is dependent on the given value, with the following
+ * rules:
*
* - BigNumber instances are returned as is
* - integer numbers are returned as BigInteger
@@ -48,16 +56,35 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
* - strings containing a `.` character or using an exponential notation are returned as BigDecimal
* - strings containing only digits with an optional leading `+` or `-` sign are returned as BigInteger
*
- * @param BigNumber|int|float|string $value
+ * When of() is called on BigInteger, BigDecimal, or BigRational, the resulting number is converted to an instance
+ * of the subclass when possible; otherwise a RoundingNecessaryException exception is thrown.
*
- * @return BigNumber
+ * @throws NumberFormatException If the format of the number is not valid.
+ * @throws DivisionByZeroException If the value represents a rational number with a denominator of zero.
+ * @throws RoundingNecessaryException If the value cannot be converted to an instance of the subclass without rounding.
*
- * @throws NumberFormatException If the format of the number is not valid.
+ * @pure
+ */
+ final public static function of(BigNumber|int|float|string $value) : static
+ {
+ $value = self::_of($value);
+
+ if (static::class === BigNumber::class) {
+ assert($value instanceof static);
+
+ return $value;
+ }
+
+ return static::from($value);
+ }
+
+ /**
+ * @throws NumberFormatException If the format of the number is not valid.
* @throws DivisionByZeroException If the value represents a rational number with a denominator of zero.
*
- * @psalm-pure
+ * @pure
*/
- public static function of($value) : BigNumber
+ private static function _of(BigNumber|int|float|string $value) : BigNumber
{
if ($value instanceof BigNumber) {
return $value;
@@ -67,37 +94,22 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
return new BigInteger((string) $value);
}
- /** @psalm-suppress RedundantCastGivenDocblockType We cannot trust the untyped $value here! */
- $value = \is_float($value) ? self::floatToString($value) : (string) $value;
-
- $throw = static function() use ($value) : void {
- throw new NumberFormatException(\sprintf(
- 'The given value "%s" does not represent a valid number.',
- $value
- ));
- };
-
- if (\preg_match(self::PARSE_REGEXP, $value, $matches) !== 1) {
- $throw();
+ if (is_float($value)) {
+ $value = (string) $value;
}
- $getMatch = static function(string $value) use ($matches) : ?string {
- return isset($matches[$value]) && $matches[$value] !== '' ? $matches[$value] : null;
- };
-
- $sign = $getMatch('sign');
- $numerator = $getMatch('numerator');
- $denominator = $getMatch('denominator');
-
- if ($numerator !== null) {
- assert($denominator !== null);
-
- if ($sign !== null) {
- $numerator = $sign . $numerator;
+ if (str_contains($value, '/')) {
+ // Rational number
+ if (\preg_match(self::PARSE_REGEXP_RATIONAL, $value, $matches, PREG_UNMATCHED_AS_NULL) !== 1) {
+ throw NumberFormatException::invalidFormat($value);
}
- $numerator = self::cleanUp($numerator);
- $denominator = self::cleanUp($denominator);
+ $sign = $matches['sign'];
+ $numerator = $matches['numerator'];
+ $denominator = $matches['denominator'];
+
+ $numerator = self::cleanUp($sign, $numerator);
+ $denominator = self::cleanUp(null, $denominator);
if ($denominator === '0') {
throw DivisionByZeroException::denominatorMustNotBeZero();
@@ -108,88 +120,94 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
new BigInteger($denominator),
false
);
- }
-
- $point = $getMatch('point');
- $integral = $getMatch('integral');
- $fractional = $getMatch('fractional');
- $exponent = $getMatch('exponent');
-
- if ($integral === null && $fractional === null) {
- $throw();
- }
-
- if ($integral === null) {
- $integral = '0';
- }
-
- if ($point !== null || $exponent !== null) {
- $fractional = ($fractional ?? '');
- $exponent = ($exponent !== null) ? (int) $exponent : 0;
-
- if ($exponent === PHP_INT_MIN || $exponent === PHP_INT_MAX) {
- throw new NumberFormatException('Exponent too large.');
+ } else {
+ // Integer or decimal number
+ if (\preg_match(self::PARSE_REGEXP_NUMERICAL, $value, $matches, PREG_UNMATCHED_AS_NULL) !== 1) {
+ throw NumberFormatException::invalidFormat($value);
}
- $unscaledValue = self::cleanUp(($sign ?? ''). $integral . $fractional);
+ $sign = $matches['sign'];
+ $point = $matches['point'];
+ $integral = $matches['integral'];
+ $fractional = $matches['fractional'];
+ $exponent = $matches['exponent'];
- $scale = \strlen($fractional) - $exponent;
+ if ($integral === null && $fractional === null) {
+ throw NumberFormatException::invalidFormat($value);
+ }
- if ($scale < 0) {
- if ($unscaledValue !== '0') {
- $unscaledValue .= \str_repeat('0', - $scale);
+ if ($integral === null) {
+ $integral = '0';
+ }
+
+ if ($point !== null || $exponent !== null) {
+ $fractional ??= '';
+ $exponent = ($exponent !== null) ? (int)$exponent : 0;
+
+ if ($exponent === PHP_INT_MIN || $exponent === PHP_INT_MAX) {
+ throw new NumberFormatException('Exponent too large.');
}
- $scale = 0;
+
+ $unscaledValue = self::cleanUp($sign, $integral . $fractional);
+
+ $scale = \strlen($fractional) - $exponent;
+
+ if ($scale < 0) {
+ if ($unscaledValue !== '0') {
+ $unscaledValue .= \str_repeat('0', -$scale);
+ }
+ $scale = 0;
+ }
+
+ return new BigDecimal($unscaledValue, $scale);
}
- return new BigDecimal($unscaledValue, $scale);
+ $integral = self::cleanUp($sign, $integral);
+
+ return new BigInteger($integral);
}
-
- $integral = self::cleanUp(($sign ?? '') . $integral);
-
- return new BigInteger($integral);
}
/**
- * Safely converts float to string, avoiding locale-dependent issues.
+ * Overridden by subclasses to convert a BigNumber to an instance of the subclass.
*
- * @see https://github.com/brick/math/pull/20
+ * @throws RoundingNecessaryException If the value cannot be converted.
*
- * @param float $float
- *
- * @return string
- *
- * @psalm-pure
- * @psalm-suppress ImpureFunctionCall
+ * @pure
*/
- private static function floatToString(float $float) : string
- {
- $currentLocale = \setlocale(LC_NUMERIC, '0');
- \setlocale(LC_NUMERIC, 'C');
-
- $result = (string) $float;
-
- \setlocale(LC_NUMERIC, $currentLocale);
-
- return $result;
- }
+ abstract protected static function from(BigNumber $number): static;
/**
- * Proxy method to access protected constructors from sibling classes.
+ * Proxy method to access BigInteger's protected constructor from sibling classes.
*
+ * @pure
* @internal
- *
- * @param mixed ...$args The arguments to the constructor.
- *
- * @return static
- *
- * @psalm-pure
- * @psalm-suppress TooManyArguments
- * @psalm-suppress UnsafeInstantiation
*/
- protected static function create(... $args) : BigNumber
+ final protected function newBigInteger(string $value) : BigInteger
{
- return new static(... $args);
+ return new BigInteger($value);
+ }
+
+ /**
+ * Proxy method to access BigDecimal's protected constructor from sibling classes.
+ *
+ * @pure
+ * @internal
+ */
+ final protected function newBigDecimal(string $value, int $scale = 0) : BigDecimal
+ {
+ return new BigDecimal($value, $scale);
+ }
+
+ /**
+ * Proxy method to access BigRational's protected constructor from sibling classes.
+ *
+ * @pure
+ * @internal
+ */
+ final protected function newBigRational(BigInteger $numerator, BigInteger $denominator, bool $checkDenominator) : BigRational
+ {
+ return new BigRational($numerator, $denominator, $checkDenominator);
}
/**
@@ -198,16 +216,12 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
* @param BigNumber|int|float|string ...$values The numbers to compare. All the numbers need to be convertible
* to an instance of the class this method is called on.
*
- * @return static The minimum value.
- *
* @throws \InvalidArgumentException If no values are given.
* @throws MathException If an argument is not valid.
*
- * @psalm-suppress LessSpecificReturnStatement
- * @psalm-suppress MoreSpecificReturnType
- * @psalm-pure
+ * @pure
*/
- public static function min(...$values) : BigNumber
+ final public static function min(BigNumber|int|float|string ...$values) : static
{
$min = null;
@@ -232,16 +246,12 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
* @param BigNumber|int|float|string ...$values The numbers to compare. All the numbers need to be convertible
* to an instance of the class this method is called on.
*
- * @return static The maximum value.
- *
* @throws \InvalidArgumentException If no values are given.
* @throws MathException If an argument is not valid.
*
- * @psalm-suppress LessSpecificReturnStatement
- * @psalm-suppress MoreSpecificReturnType
- * @psalm-pure
+ * @pure
*/
- public static function max(...$values) : BigNumber
+ final public static function max(BigNumber|int|float|string ...$values) : static
{
$max = null;
@@ -263,50 +273,43 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
/**
* Returns the sum of the given values.
*
- * @param BigNumber|int|float|string ...$values The numbers to add. All the numbers need to be convertible
- * to an instance of the class this method is called on.
+ * When called on BigNumber, sum() accepts any supported type and returns a result whose type is the widest among
+ * the given values (BigInteger < BigDecimal < BigRational).
*
- * @return static The sum.
+ * When called on BigInteger, BigDecimal, or BigRational, sum() requires that all values can be converted to that
+ * specific subclass, and returns a result of the same type.
+ *
+ * @param BigNumber|int|float|string ...$values The values to add. All values must be convertible to the class on
+ * which this method is called.
*
* @throws \InvalidArgumentException If no values are given.
* @throws MathException If an argument is not valid.
*
- * @psalm-suppress LessSpecificReturnStatement
- * @psalm-suppress MoreSpecificReturnType
- * @psalm-pure
+ * @pure
*/
- public static function sum(...$values) : BigNumber
+ final public static function sum(BigNumber|int|float|string ...$values) : static
{
- /** @var BigNumber|null $sum */
- $sum = null;
+ $first = array_shift($values);
- foreach ($values as $value) {
- $value = static::of($value);
-
- $sum = $sum === null ? $value : self::add($sum, $value);
- }
-
- if ($sum === null) {
+ if ($first === null) {
throw new \InvalidArgumentException(__METHOD__ . '() expects at least one value.');
}
+ $sum = static::of($first);
+
+ foreach ($values as $value) {
+ $sum = self::add($sum, static::of($value));
+ }
+
+ assert($sum instanceof static);
+
return $sum;
}
/**
* Adds two BigNumber instances in the correct order to avoid a RoundingNecessaryException.
*
- * @todo This could be better resolved by creating an abstract protected method in BigNumber, and leaving to
- * concrete classes the responsibility to perform the addition themselves or delegate it to the given number,
- * depending on their ability to perform the operation. This will also require a version bump because we're
- * potentially breaking custom BigNumber implementations (if any...)
- *
- * @param BigNumber $a
- * @param BigNumber $b
- *
- * @return BigNumber
- *
- * @psalm-pure
+ * @pure
*/
private static function add(BigNumber $a, BigNumber $b) : BigNumber
{
@@ -326,49 +329,34 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
return $b->plus($a);
}
- /** @var BigInteger $a */
-
return $a->plus($b);
}
/**
- * Removes optional leading zeros and + sign from the given number.
+ * Removes optional leading zeros and applies sign.
*
- * @param string $number The number, validated as a non-empty string of digits with optional leading sign.
+ * @param string|null $sign The sign, '+' or '-', optional. Null is allowed for convenience and treated as '+'.
+ * @param string $number The number, validated as a string of digits.
*
- * @return string
- *
- * @psalm-pure
+ * @pure
*/
- private static function cleanUp(string $number) : string
+ private static function cleanUp(string|null $sign, string $number) : string
{
- $firstChar = $number[0];
-
- if ($firstChar === '+' || $firstChar === '-') {
- $number = \substr($number, 1);
- }
-
$number = \ltrim($number, '0');
if ($number === '') {
return '0';
}
- if ($firstChar === '-') {
- return '-' . $number;
- }
-
- return $number;
+ return $sign === '-' ? '-' . $number : $number;
}
/**
* Checks if this number is equal to the given one.
*
- * @param BigNumber|int|float|string $that
- *
- * @return bool
+ * @pure
*/
- public function isEqualTo($that) : bool
+ final public function isEqualTo(BigNumber|int|float|string $that) : bool
{
return $this->compareTo($that) === 0;
}
@@ -376,11 +364,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
/**
* Checks if this number is strictly lower than the given one.
*
- * @param BigNumber|int|float|string $that
- *
- * @return bool
+ * @pure
*/
- public function isLessThan($that) : bool
+ final public function isLessThan(BigNumber|int|float|string $that) : bool
{
return $this->compareTo($that) < 0;
}
@@ -388,11 +374,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
/**
* Checks if this number is lower than or equal to the given one.
*
- * @param BigNumber|int|float|string $that
- *
- * @return bool
+ * @pure
*/
- public function isLessThanOrEqualTo($that) : bool
+ final public function isLessThanOrEqualTo(BigNumber|int|float|string $that) : bool
{
return $this->compareTo($that) <= 0;
}
@@ -400,11 +384,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
/**
* Checks if this number is strictly greater than the given one.
*
- * @param BigNumber|int|float|string $that
- *
- * @return bool
+ * @pure
*/
- public function isGreaterThan($that) : bool
+ final public function isGreaterThan(BigNumber|int|float|string $that) : bool
{
return $this->compareTo($that) > 0;
}
@@ -412,11 +394,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
/**
* Checks if this number is greater than or equal to the given one.
*
- * @param BigNumber|int|float|string $that
- *
- * @return bool
+ * @pure
*/
- public function isGreaterThanOrEqualTo($that) : bool
+ final public function isGreaterThanOrEqualTo(BigNumber|int|float|string $that) : bool
{
return $this->compareTo($that) >= 0;
}
@@ -424,9 +404,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
/**
* Checks if this number equals zero.
*
- * @return bool
+ * @pure
*/
- public function isZero() : bool
+ final public function isZero() : bool
{
return $this->getSign() === 0;
}
@@ -434,9 +414,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
/**
* Checks if this number is strictly negative.
*
- * @return bool
+ * @pure
*/
- public function isNegative() : bool
+ final public function isNegative() : bool
{
return $this->getSign() < 0;
}
@@ -444,9 +424,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
/**
* Checks if this number is negative or zero.
*
- * @return bool
+ * @pure
*/
- public function isNegativeOrZero() : bool
+ final public function isNegativeOrZero() : bool
{
return $this->getSign() <= 0;
}
@@ -454,9 +434,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
/**
* Checks if this number is strictly positive.
*
- * @return bool
+ * @pure
*/
- public function isPositive() : bool
+ final public function isPositive() : bool
{
return $this->getSign() > 0;
}
@@ -464,9 +444,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
/**
* Checks if this number is positive or zero.
*
- * @return bool
+ * @pure
*/
- public function isPositiveOrZero() : bool
+ final public function isPositiveOrZero() : bool
{
return $this->getSign() >= 0;
}
@@ -474,58 +454,64 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
/**
* Returns the sign of this number.
*
- * @return int -1 if the number is negative, 0 if zero, 1 if positive.
+ * Returns -1 if the number is negative, 0 if zero, 1 if positive.
+ *
+ * @return -1|0|1
+ *
+ * @pure
*/
abstract public function getSign() : int;
/**
* Compares this number to the given one.
*
- * @param BigNumber|int|float|string $that
+ * Returns -1 if `$this` is lower than, 0 if equal to, 1 if greater than `$that`.
*
- * @return int [-1,0,1] If `$this` is lower than, equal to, or greater than `$that`.
+ * @return -1|0|1
*
* @throws MathException If the number is not valid.
+ *
+ * @pure
*/
- abstract public function compareTo($that) : int;
+ abstract public function compareTo(BigNumber|int|float|string $that) : int;
/**
* Converts this number to a BigInteger.
*
- * @return BigInteger The converted number.
- *
* @throws RoundingNecessaryException If this number cannot be converted to a BigInteger without rounding.
+ *
+ * @pure
*/
abstract public function toBigInteger() : BigInteger;
/**
* Converts this number to a BigDecimal.
*
- * @return BigDecimal The converted number.
- *
* @throws RoundingNecessaryException If this number cannot be converted to a BigDecimal without rounding.
+ *
+ * @pure
*/
abstract public function toBigDecimal() : BigDecimal;
/**
* Converts this number to a BigRational.
*
- * @return BigRational The converted number.
+ * @pure
*/
abstract public function toBigRational() : BigRational;
/**
* Converts this number to a BigDecimal with the given scale, using rounding if necessary.
*
- * @param int $scale The scale of the resulting `BigDecimal`.
- * @param int $roundingMode A `RoundingMode` constant.
- *
- * @return BigDecimal
+ * @param int $scale The scale of the resulting `BigDecimal`.
+ * @param RoundingMode $roundingMode An optional rounding mode, defaults to UNNECESSARY.
*
* @throws RoundingNecessaryException If this number cannot be converted to the given scale without rounding.
* This only applies when RoundingMode::UNNECESSARY is used.
+ *
+ * @pure
*/
- abstract public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal;
+ abstract public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal;
/**
* Returns the exact value of this number as a native integer.
@@ -533,9 +519,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
* If this number cannot be converted to a native integer without losing precision, an exception is thrown.
* Note that the acceptable range for an integer depends on the platform and differs for 32-bit and 64-bit.
*
- * @return int The converted value.
- *
* @throws MathException If this number cannot be exactly converted to a native integer.
+ *
+ * @pure
*/
abstract public function toInt() : int;
@@ -548,7 +534,7 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
* If the number is greater than the largest representable floating point number, positive infinity is returned.
* If the number is less than the smallest representable floating point number, negative infinity is returned.
*
- * @return float The converted value.
+ * @pure
*/
abstract public function toFloat() : float;
@@ -558,14 +544,12 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
* The output of this method can be parsed by the `of()` factory method;
* this will yield an object equal to this one, without any information loss.
*
- * @return string
+ * @pure
*/
abstract public function __toString() : string;
- /**
- * {@inheritdoc}
- */
- public function jsonSerialize() : string
+ #[Override]
+ final public function jsonSerialize() : string
{
return $this->__toString();
}
diff --git a/vendor/brick/math/src/BigRational.php b/vendor/brick/math/src/BigRational.php
index bee094f..56045e5 100644
--- a/vendor/brick/math/src/BigRational.php
+++ b/vendor/brick/math/src/BigRational.php
@@ -8,29 +8,24 @@ use Brick\Math\Exception\DivisionByZeroException;
use Brick\Math\Exception\MathException;
use Brick\Math\Exception\NumberFormatException;
use Brick\Math\Exception\RoundingNecessaryException;
+use Override;
/**
* An arbitrarily large rational number.
*
* This class is immutable.
- *
- * @psalm-immutable
*/
-final class BigRational extends BigNumber
+final readonly class BigRational extends BigNumber
{
/**
* The numerator.
- *
- * @var BigInteger
*/
- private $numerator;
+ private BigInteger $numerator;
/**
* The denominator. Always strictly positive.
- *
- * @var BigInteger
*/
- private $denominator;
+ private BigInteger $denominator;
/**
* Protected constructor. Use a factory method to obtain an instance.
@@ -40,6 +35,8 @@ final class BigRational extends BigNumber
* @param bool $checkDenominator Whether to check the denominator for negative and zero.
*
* @throws DivisionByZeroException If the denominator is zero.
+ *
+ * @pure
*/
protected function __construct(BigInteger $numerator, BigInteger $denominator, bool $checkDenominator)
{
@@ -58,20 +55,10 @@ final class BigRational extends BigNumber
$this->denominator = $denominator;
}
- /**
- * Creates a BigRational of the given value.
- *
- * @param BigNumber|int|float|string $value
- *
- * @return BigRational
- *
- * @throws MathException If the value cannot be converted to a BigRational.
- *
- * @psalm-pure
- */
- public static function of($value) : BigNumber
+ #[Override]
+ protected static function from(BigNumber $number): static
{
- return parent::of($value)->toBigRational();
+ return $number->toBigRational();
}
/**
@@ -83,16 +70,16 @@ final class BigRational extends BigNumber
* @param BigNumber|int|float|string $numerator The numerator. Must be convertible to a BigInteger.
* @param BigNumber|int|float|string $denominator The denominator. Must be convertible to a BigInteger.
*
- * @return BigRational
- *
* @throws NumberFormatException If an argument does not represent a valid number.
* @throws RoundingNecessaryException If an argument represents a non-integer number.
* @throws DivisionByZeroException If the denominator is zero.
*
- * @psalm-pure
+ * @pure
*/
- public static function nd($numerator, $denominator) : BigRational
- {
+ public static function nd(
+ BigNumber|int|float|string $numerator,
+ BigNumber|int|float|string $denominator,
+ ) : BigRational {
$numerator = BigInteger::of($numerator);
$denominator = BigInteger::of($denominator);
@@ -102,16 +89,11 @@ final class BigRational extends BigNumber
/**
* Returns a BigRational representing zero.
*
- * @return BigRational
- *
- * @psalm-pure
+ * @pure
*/
public static function zero() : BigRational
{
- /**
- * @psalm-suppress ImpureStaticVariable
- * @var BigRational|null $zero
- */
+ /** @var BigRational|null $zero */
static $zero;
if ($zero === null) {
@@ -124,16 +106,11 @@ final class BigRational extends BigNumber
/**
* Returns a BigRational representing one.
*
- * @return BigRational
- *
- * @psalm-pure
+ * @pure
*/
public static function one() : BigRational
{
- /**
- * @psalm-suppress ImpureStaticVariable
- * @var BigRational|null $one
- */
+ /** @var BigRational|null $one */
static $one;
if ($one === null) {
@@ -146,16 +123,11 @@ final class BigRational extends BigNumber
/**
* Returns a BigRational representing ten.
*
- * @return BigRational
- *
- * @psalm-pure
+ * @pure
*/
public static function ten() : BigRational
{
- /**
- * @psalm-suppress ImpureStaticVariable
- * @var BigRational|null $ten
- */
+ /** @var BigRational|null $ten */
static $ten;
if ($ten === null) {
@@ -166,7 +138,7 @@ final class BigRational extends BigNumber
}
/**
- * @return BigInteger
+ * @pure
*/
public function getNumerator() : BigInteger
{
@@ -174,7 +146,7 @@ final class BigRational extends BigNumber
}
/**
- * @return BigInteger
+ * @pure
*/
public function getDenominator() : BigInteger
{
@@ -184,7 +156,7 @@ final class BigRational extends BigNumber
/**
* Returns the quotient of the division of the numerator by the denominator.
*
- * @return BigInteger
+ * @pure
*/
public function quotient() : BigInteger
{
@@ -194,7 +166,7 @@ final class BigRational extends BigNumber
/**
* Returns the remainder of the division of the numerator by the denominator.
*
- * @return BigInteger
+ * @pure
*/
public function remainder() : BigInteger
{
@@ -204,7 +176,9 @@ final class BigRational extends BigNumber
/**
* Returns the quotient and remainder of the division of the numerator by the denominator.
*
- * @return BigInteger[]
+ * @return array{BigInteger, BigInteger}
+ *
+ * @pure
*/
public function quotientAndRemainder() : array
{
@@ -216,11 +190,11 @@ final class BigRational extends BigNumber
*
* @param BigNumber|int|float|string $that The number to add.
*
- * @return BigRational The result.
- *
* @throws MathException If the number is not valid.
+ *
+ * @pure
*/
- public function plus($that) : BigRational
+ public function plus(BigNumber|int|float|string $that) : BigRational
{
$that = BigRational::of($that);
@@ -236,11 +210,11 @@ final class BigRational extends BigNumber
*
* @param BigNumber|int|float|string $that The number to subtract.
*
- * @return BigRational The result.
- *
* @throws MathException If the number is not valid.
+ *
+ * @pure
*/
- public function minus($that) : BigRational
+ public function minus(BigNumber|int|float|string $that) : BigRational
{
$that = BigRational::of($that);
@@ -256,11 +230,11 @@ final class BigRational extends BigNumber
*
* @param BigNumber|int|float|string $that The multiplier.
*
- * @return BigRational The result.
- *
* @throws MathException If the multiplier is not a valid number.
+ *
+ * @pure
*/
- public function multipliedBy($that) : BigRational
+ public function multipliedBy(BigNumber|int|float|string $that) : BigRational
{
$that = BigRational::of($that);
@@ -275,11 +249,11 @@ final class BigRational extends BigNumber
*
* @param BigNumber|int|float|string $that The divisor.
*
- * @return BigRational The result.
- *
* @throws MathException If the divisor is not a valid number, or is zero.
+ *
+ * @pure
*/
- public function dividedBy($that) : BigRational
+ public function dividedBy(BigNumber|int|float|string $that) : BigRational
{
$that = BigRational::of($that);
@@ -292,11 +266,9 @@ final class BigRational extends BigNumber
/**
* Returns this number exponentiated to the given value.
*
- * @param int $exponent The exponent.
- *
- * @return BigRational The result.
- *
* @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000.
+ *
+ * @pure
*/
public function power(int $exponent) : BigRational
{
@@ -322,9 +294,9 @@ final class BigRational extends BigNumber
*
* The reciprocal has the numerator and denominator swapped.
*
- * @return BigRational
- *
* @throws DivisionByZeroException If the numerator is zero.
+ *
+ * @pure
*/
public function reciprocal() : BigRational
{
@@ -334,7 +306,7 @@ final class BigRational extends BigNumber
/**
* Returns the absolute value of this BigRational.
*
- * @return BigRational
+ * @pure
*/
public function abs() : BigRational
{
@@ -344,7 +316,7 @@ final class BigRational extends BigNumber
/**
* Returns the negated value of this BigRational.
*
- * @return BigRational
+ * @pure
*/
public function negated() : BigRational
{
@@ -354,7 +326,7 @@ final class BigRational extends BigNumber
/**
* Returns the simplified value of this BigRational.
*
- * @return BigRational
+ * @pure
*/
public function simplified() : BigRational
{
@@ -366,25 +338,19 @@ final class BigRational extends BigNumber
return new BigRational($numerator, $denominator, false);
}
- /**
- * {@inheritdoc}
- */
- public function compareTo($that) : int
+ #[Override]
+ public function compareTo(BigNumber|int|float|string $that) : int
{
return $this->minus($that)->getSign();
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function getSign() : int
{
return $this->numerator->getSign();
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function toBigInteger() : BigInteger
{
$simplified = $this->simplified();
@@ -396,49 +362,38 @@ final class BigRational extends BigNumber
return $simplified->numerator;
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function toBigDecimal() : BigDecimal
{
return $this->numerator->toBigDecimal()->exactlyDividedBy($this->denominator);
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function toBigRational() : BigRational
{
return $this;
}
- /**
- * {@inheritdoc}
- */
- public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
+ #[Override]
+ public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
{
return $this->numerator->toBigDecimal()->dividedBy($this->denominator, $scale, $roundingMode);
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function toInt() : int
{
return $this->toBigInteger()->toInt();
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function toFloat() : float
{
- return $this->numerator->toFloat() / $this->denominator->toFloat();
+ $simplified = $this->simplified();
+ return $simplified->numerator->toFloat() / $simplified->denominator->toFloat();
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function __toString() : string
{
$numerator = (string) $this->numerator;
@@ -448,7 +403,7 @@ final class BigRational extends BigNumber
return $numerator;
}
- return $this->numerator . '/' . $this->denominator;
+ return $numerator . '/' . $denominator;
}
/**
@@ -467,57 +422,20 @@ final class BigRational extends BigNumber
* This method is only here to allow unserializing the object and cannot be accessed directly.
*
* @internal
- * @psalm-suppress RedundantPropertyInitializationCheck
*
* @param array{numerator: BigInteger, denominator: BigInteger} $data
*
- * @return void
- *
* @throws \LogicException
*/
public function __unserialize(array $data): void
{
+ /** @phpstan-ignore isset.initializedProperty */
if (isset($this->numerator)) {
throw new \LogicException('__unserialize() is an internal function, it must not be called directly.');
}
+ /** @phpstan-ignore deadCode.unreachable */
$this->numerator = $data['numerator'];
$this->denominator = $data['denominator'];
}
-
- /**
- * This method is required by interface Serializable and SHOULD NOT be accessed directly.
- *
- * @internal
- *
- * @return string
- */
- public function serialize() : string
- {
- return $this->numerator . '/' . $this->denominator;
- }
-
- /**
- * This method is only here to implement interface Serializable and cannot be accessed directly.
- *
- * @internal
- * @psalm-suppress RedundantPropertyInitializationCheck
- *
- * @param string $value
- *
- * @return void
- *
- * @throws \LogicException
- */
- public function unserialize($value) : void
- {
- if (isset($this->numerator)) {
- throw new \LogicException('unserialize() is an internal function, it must not be called directly.');
- }
-
- [$numerator, $denominator] = \explode('/', $value);
-
- $this->numerator = BigInteger::of($numerator);
- $this->denominator = BigInteger::of($denominator);
- }
}
diff --git a/vendor/brick/math/src/Exception/DivisionByZeroException.php b/vendor/brick/math/src/Exception/DivisionByZeroException.php
index a4e4431..2daaf5e 100644
--- a/vendor/brick/math/src/Exception/DivisionByZeroException.php
+++ b/vendor/brick/math/src/Exception/DivisionByZeroException.php
@@ -7,12 +7,10 @@ namespace Brick\Math\Exception;
/**
* Exception thrown when a division by zero occurs.
*/
-class DivisionByZeroException extends MathException
+final class DivisionByZeroException extends MathException
{
/**
- * @return DivisionByZeroException
- *
- * @psalm-pure
+ * @pure
*/
public static function divisionByZero() : DivisionByZeroException
{
@@ -20,9 +18,7 @@ class DivisionByZeroException extends MathException
}
/**
- * @return DivisionByZeroException
- *
- * @psalm-pure
+ * @pure
*/
public static function modulusMustNotBeZero() : DivisionByZeroException
{
@@ -30,9 +26,7 @@ class DivisionByZeroException extends MathException
}
/**
- * @return DivisionByZeroException
- *
- * @psalm-pure
+ * @pure
*/
public static function denominatorMustNotBeZero() : DivisionByZeroException
{
diff --git a/vendor/brick/math/src/Exception/IntegerOverflowException.php b/vendor/brick/math/src/Exception/IntegerOverflowException.php
index e0b07d3..56f3cf8 100644
--- a/vendor/brick/math/src/Exception/IntegerOverflowException.php
+++ b/vendor/brick/math/src/Exception/IntegerOverflowException.php
@@ -9,14 +9,10 @@ use Brick\Math\BigInteger;
/**
* Exception thrown when an integer overflow occurs.
*/
-class IntegerOverflowException extends MathException
+final class IntegerOverflowException extends MathException
{
/**
- * @param BigInteger $value
- *
- * @return IntegerOverflowException
- *
- * @psalm-pure
+ * @pure
*/
public static function toIntOverflow(BigInteger $value) : IntegerOverflowException
{
diff --git a/vendor/brick/math/src/Exception/MathException.php b/vendor/brick/math/src/Exception/MathException.php
index 21fda90..8facd9c 100644
--- a/vendor/brick/math/src/Exception/MathException.php
+++ b/vendor/brick/math/src/Exception/MathException.php
@@ -6,8 +6,6 @@ namespace Brick\Math\Exception;
/**
* Base class for all math exceptions.
- *
- * This class is abstract to ensure that only fine-grained exceptions are thrown throughout the code.
*/
class MathException extends \RuntimeException
{
diff --git a/vendor/brick/math/src/Exception/NegativeNumberException.php b/vendor/brick/math/src/Exception/NegativeNumberException.php
index 4739113..73ed3a4 100644
--- a/vendor/brick/math/src/Exception/NegativeNumberException.php
+++ b/vendor/brick/math/src/Exception/NegativeNumberException.php
@@ -7,6 +7,6 @@ namespace Brick\Math\Exception;
/**
* Exception thrown when attempting to perform an unsupported operation, such as a square root, on a negative number.
*/
-class NegativeNumberException extends MathException
+final class NegativeNumberException extends MathException
{
}
diff --git a/vendor/brick/math/src/Exception/NumberFormatException.php b/vendor/brick/math/src/Exception/NumberFormatException.php
index 2fd0be7..0dcda34 100644
--- a/vendor/brick/math/src/Exception/NumberFormatException.php
+++ b/vendor/brick/math/src/Exception/NumberFormatException.php
@@ -7,14 +7,23 @@ namespace Brick\Math\Exception;
/**
* Exception thrown when attempting to create a number from a string with an invalid format.
*/
-class NumberFormatException extends MathException
+final class NumberFormatException extends MathException
{
+ /**
+ * @pure
+ */
+ public static function invalidFormat(string $value) : self
+ {
+ return new self(\sprintf(
+ 'The given value "%s" does not represent a valid number.',
+ $value,
+ ));
+ }
+
/**
* @param string $char The failing character.
*
- * @return NumberFormatException
- *
- * @psalm-pure
+ * @pure
*/
public static function charNotInAlphabet(string $char) : self
{
@@ -30,6 +39,6 @@ class NumberFormatException extends MathException
$char = '"' . $char . '"';
}
- return new self(sprintf('Char %s is not a valid character in the given alphabet.', $char));
+ return new self(\sprintf('Char %s is not a valid character in the given alphabet.', $char));
}
}
diff --git a/vendor/brick/math/src/Exception/RoundingNecessaryException.php b/vendor/brick/math/src/Exception/RoundingNecessaryException.php
index 1c61005..034a040 100644
--- a/vendor/brick/math/src/Exception/RoundingNecessaryException.php
+++ b/vendor/brick/math/src/Exception/RoundingNecessaryException.php
@@ -7,12 +7,10 @@ namespace Brick\Math\Exception;
/**
* Exception thrown when a number cannot be represented at the requested scale without rounding.
*/
-class RoundingNecessaryException extends MathException
+final class RoundingNecessaryException extends MathException
{
/**
- * @return RoundingNecessaryException
- *
- * @psalm-pure
+ * @pure
*/
public static function roundingNecessary() : RoundingNecessaryException
{
diff --git a/vendor/brick/math/src/Internal/Calculator.php b/vendor/brick/math/src/Internal/Calculator.php
index a6eac79..a5e000a 100644
--- a/vendor/brick/math/src/Internal/Calculator.php
+++ b/vendor/brick/math/src/Internal/Calculator.php
@@ -17,89 +17,25 @@ use Brick\Math\RoundingMode;
* All methods must return strings respecting this format, unless specified otherwise.
*
* @internal
- *
- * @psalm-immutable
*/
-abstract class Calculator
+abstract readonly class Calculator
{
/**
* The maximum exponent value allowed for the pow() method.
*/
- public const MAX_POWER = 1000000;
+ public const MAX_POWER = 1_000_000;
/**
* The alphabet for converting from and to base 2 to 36, lowercase.
*/
public const ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyz';
- /**
- * The Calculator instance in use.
- *
- * @var Calculator|null
- */
- private static $instance;
-
- /**
- * Sets the Calculator instance to use.
- *
- * An instance is typically set only in unit tests: the autodetect is usually the best option.
- *
- * @param Calculator|null $calculator The calculator instance, or NULL to revert to autodetect.
- *
- * @return void
- */
- final public static function set(?Calculator $calculator) : void
- {
- self::$instance = $calculator;
- }
-
- /**
- * Returns the Calculator instance to use.
- *
- * If none has been explicitly set, the fastest available implementation will be returned.
- *
- * @return Calculator
- *
- * @psalm-pure
- * @psalm-suppress ImpureStaticProperty
- */
- final public static function get() : Calculator
- {
- if (self::$instance === null) {
- /** @psalm-suppress ImpureMethodCall */
- self::$instance = self::detect();
- }
-
- return self::$instance;
- }
-
- /**
- * Returns the fastest available Calculator implementation.
- *
- * @codeCoverageIgnore
- *
- * @return Calculator
- */
- private static function detect() : Calculator
- {
- if (\extension_loaded('gmp')) {
- return new Calculator\GmpCalculator();
- }
-
- if (\extension_loaded('bcmath')) {
- return new Calculator\BcMathCalculator();
- }
-
- return new Calculator\NativeCalculator();
- }
-
/**
* Extracts the sign & digits of the operands.
*
- * @param string $a The first operand.
- * @param string $b The second operand.
- *
* @return array{bool, bool, string, string} Whether $a and $b are negative, followed by their digits.
+ *
+ * @pure
*/
final protected function init(string $a, string $b) : array
{
@@ -115,9 +51,7 @@ abstract class Calculator
/**
* Returns the absolute value of a number.
*
- * @param string $n The number.
- *
- * @return string The absolute value.
+ * @pure
*/
final public function abs(string $n) : string
{
@@ -127,9 +61,7 @@ abstract class Calculator
/**
* Negates a number.
*
- * @param string $n The number.
- *
- * @return string The negated value.
+ * @pure
*/
final public function neg(string $n) : string
{
@@ -147,10 +79,11 @@ abstract class Calculator
/**
* Compares two numbers.
*
- * @param string $a The first number.
- * @param string $b The second number.
+ * Returns -1 if the first number is less than, 0 if equal to, 1 if greater than the second number.
*
- * @return int [-1, 0, 1] If the first number is less than, equal to, or greater than the second number.
+ * @return -1|0|1
+ *
+ * @pure
*/
final public function cmp(string $a, string $b) : int
{
@@ -181,30 +114,21 @@ abstract class Calculator
/**
* Adds two numbers.
*
- * @param string $a The augend.
- * @param string $b The addend.
- *
- * @return string The sum.
+ * @pure
*/
abstract public function add(string $a, string $b) : string;
/**
* Subtracts two numbers.
*
- * @param string $a The minuend.
- * @param string $b The subtrahend.
- *
- * @return string The difference.
+ * @pure
*/
abstract public function sub(string $a, string $b) : string;
/**
* Multiplies two numbers.
*
- * @param string $a The multiplicand.
- * @param string $b The multiplier.
- *
- * @return string The product.
+ * @pure
*/
abstract public function mul(string $a, string $b) : string;
@@ -215,6 +139,8 @@ abstract class Calculator
* @param string $b The divisor, must not be zero.
*
* @return string The quotient.
+ *
+ * @pure
*/
abstract public function divQ(string $a, string $b) : string;
@@ -225,6 +151,8 @@ abstract class Calculator
* @param string $b The divisor, must not be zero.
*
* @return string The remainder.
+ *
+ * @pure
*/
abstract public function divR(string $a, string $b) : string;
@@ -234,7 +162,9 @@ abstract class Calculator
* @param string $a The dividend.
* @param string $b The divisor, must not be zero.
*
- * @return string[] An array containing the quotient and remainder.
+ * @return array{string, string} An array containing the quotient and remainder.
+ *
+ * @pure
*/
abstract public function divQR(string $a, string $b) : array;
@@ -245,14 +175,15 @@ abstract class Calculator
* @param int $e The exponent, validated as an integer between 0 and MAX_POWER.
*
* @return string The power.
+ *
+ * @pure
*/
abstract public function pow(string $a, int $e) : string;
/**
- * @param string $a
* @param string $b The modulus; must not be zero.
*
- * @return string
+ * @pure
*/
public function mod(string $a, string $b) : string
{
@@ -266,10 +197,9 @@ abstract class Calculator
*
* This method can be overridden by the concrete implementation if the underlying library has built-in support.
*
- * @param string $x
* @param string $m The modulus; must not be negative or zero.
*
- * @return string|null
+ * @pure
*/
public function modInverse(string $x, string $m) : ?string
{
@@ -283,9 +213,7 @@ abstract class Calculator
$modVal = $this->mod($x, $m);
}
- $x = '0';
- $y = '0';
- $g = $this->gcdExtended($modVal, $m, $x, $y);
+ [$g, $x] = $this->gcdExtended($modVal, $m);
if ($g !== '1') {
return null;
@@ -301,7 +229,7 @@ abstract class Calculator
* @param string $exp The exponent; must be positive or zero.
* @param string $mod The modulus; must be strictly positive.
*
- * @return string The power.
+ * @pure
*/
abstract public function modPow(string $base, string $exp, string $mod) : string;
@@ -311,10 +239,9 @@ abstract class Calculator
* This method can be overridden by the concrete implementation if the underlying library
* has built-in support for GCD calculations.
*
- * @param string $a The first number.
- * @param string $b The second number.
- *
* @return string The GCD, always positive, or zero if both arguments are zero.
+ *
+ * @pure
*/
public function gcd(string $a, string $b) : string
{
@@ -329,24 +256,23 @@ abstract class Calculator
return $this->gcd($b, $this->divR($a, $b));
}
- private function gcdExtended(string $a, string $b, string &$x, string &$y) : string
+ /**
+ * @return array{string, string, string} GCD, X, Y
+ *
+ * @pure
+ */
+ private function gcdExtended(string $a, string $b) : array
{
if ($a === '0') {
- $x = '0';
- $y = '1';
-
- return $b;
+ return [$b, '0', '1'];
}
- $x1 = '0';
- $y1 = '0';
-
- $gcd = $this->gcdExtended($this->mod($b, $a), $a, $x1, $y1);
+ [$gcd, $x1, $y1] = $this->gcdExtended($this->mod($b, $a), $a);
$x = $this->sub($y1, $this->mul($this->divQ($b, $a), $x1));
$y = $x1;
- return $gcd;
+ return [$gcd, $x, $y];
}
/**
@@ -355,9 +281,7 @@ abstract class Calculator
* The result is the largest x such that x² ≤ n.
* The input MUST NOT be negative.
*
- * @param string $n The number.
- *
- * @return string The square root.
+ * @pure
*/
abstract public function sqrt(string $n) : string;
@@ -371,6 +295,8 @@ abstract class Calculator
* @param int $base The base of the number, validated from 2 to 36.
*
* @return string The converted number, following the Calculator conventions.
+ *
+ * @pure
*/
public function fromBase(string $number, int $base) : string
{
@@ -387,6 +313,8 @@ abstract class Calculator
* @param int $base The base to convert to, validated from 2 to 36.
*
* @return string The converted number, lowercase.
+ *
+ * @pure
*/
public function toBase(string $number, int $base) : string
{
@@ -414,6 +342,8 @@ abstract class Calculator
* @param int $base The base of the number, validated from 2 to alphabet length.
*
* @return string The number in base 10, following the Calculator conventions.
+ *
+ * @pure
*/
final public function fromArbitraryBase(string $number, string $alphabet, int $base) : string
{
@@ -460,6 +390,8 @@ abstract class Calculator
* @param int $base The base to convert to, validated from 2 to alphabet length.
*
* @return string The converted number in the given alphabet.
+ *
+ * @pure
*/
final public function toArbitraryBase(string $number, string $alphabet, int $base) : string
{
@@ -485,16 +417,15 @@ abstract class Calculator
*
* Rounding is performed when the remainder of the division is not zero.
*
- * @param string $a The dividend.
- * @param string $b The divisor, must not be zero.
- * @param int $roundingMode The rounding mode.
+ * @param string $a The dividend.
+ * @param string $b The divisor, must not be zero.
+ * @param RoundingMode $roundingMode The rounding mode.
*
- * @return string
- *
- * @throws \InvalidArgumentException If the rounding mode is invalid.
* @throws RoundingNecessaryException If RoundingMode::UNNECESSARY is provided but rounding is necessary.
+ *
+ * @pure
*/
- final public function divRound(string $a, string $b, int $roundingMode) : string
+ final public function divRound(string $a, string $b, RoundingMode $roundingMode) : string
{
[$quotient, $remainder] = $this->divQR($a, $b);
@@ -553,9 +484,6 @@ abstract class Calculator
$lastDigitIsEven = ($lastDigit % 2 === 0);
$increment = $lastDigitIsEven ? $discardedFractionSign() > 0 : $discardedFractionSign() >= 0;
break;
-
- default:
- throw new \InvalidArgumentException('Invalid rounding mode.');
}
if ($increment) {
@@ -571,10 +499,7 @@ abstract class Calculator
* This method can be overridden by the concrete implementation if the underlying library
* has built-in support for bitwise operations.
*
- * @param string $a
- * @param string $b
- *
- * @return string
+ * @pure
*/
public function and(string $a, string $b) : string
{
@@ -587,10 +512,7 @@ abstract class Calculator
* This method can be overridden by the concrete implementation if the underlying library
* has built-in support for bitwise operations.
*
- * @param string $a
- * @param string $b
- *
- * @return string
+ * @pure
*/
public function or(string $a, string $b) : string
{
@@ -603,10 +525,7 @@ abstract class Calculator
* This method can be overridden by the concrete implementation if the underlying library
* has built-in support for bitwise operations.
*
- * @param string $a
- * @param string $b
- *
- * @return string
+ * @pure
*/
public function xor(string $a, string $b) : string
{
@@ -616,11 +535,11 @@ abstract class Calculator
/**
* Performs a bitwise operation on a decimal number.
*
- * @param string $operator The operator to use, must be "and", "or" or "xor".
- * @param string $a The left operand.
- * @param string $b The right operand.
+ * @param 'and'|'or'|'xor' $operator The operator to use.
+ * @param string $a The left operand.
+ * @param string $b The right operand.
*
- * @return string
+ * @pure
*/
private function bitwise(string $operator, string $a, string $b) : string
{
@@ -645,27 +564,17 @@ abstract class Calculator
$bBin = $this->twosComplement($bBin);
}
- switch ($operator) {
- case 'and':
- $value = $aBin & $bBin;
- $negative = ($aNeg and $bNeg);
- break;
+ $value = match ($operator) {
+ 'and' => $aBin & $bBin,
+ 'or' => $aBin | $bBin,
+ 'xor' => $aBin ^ $bBin,
+ };
- case 'or':
- $value = $aBin | $bBin;
- $negative = ($aNeg or $bNeg);
- break;
-
- case 'xor':
- $value = $aBin ^ $bBin;
- $negative = ($aNeg xor $bNeg);
- break;
-
- // @codeCoverageIgnoreStart
- default:
- throw new \InvalidArgumentException('Invalid bitwise operator.');
- // @codeCoverageIgnoreEnd
- }
+ $negative = match ($operator) {
+ 'and' => $aNeg and $bNeg,
+ 'or' => $aNeg or $bNeg,
+ 'xor' => $aNeg xor $bNeg,
+ };
if ($negative) {
$value = $this->twosComplement($value);
@@ -679,7 +588,7 @@ abstract class Calculator
/**
* @param string $number A positive, binary number.
*
- * @return string
+ * @pure
*/
private function twosComplement(string $number) : string
{
@@ -710,7 +619,7 @@ abstract class Calculator
*
* @param string $number The number to convert, positive or zero, only digits.
*
- * @return string
+ * @pure
*/
private function toBinary(string $number) : string
{
@@ -729,7 +638,7 @@ abstract class Calculator
*
* @param string $bytes The bytes representing the number.
*
- * @return string
+ * @pure
*/
private function toDecimal(string $bytes) : string
{
diff --git a/vendor/brick/math/src/Internal/Calculator/BcMathCalculator.php b/vendor/brick/math/src/Internal/Calculator/BcMathCalculator.php
index 6632b37..5ba961e 100644
--- a/vendor/brick/math/src/Internal/Calculator/BcMathCalculator.php
+++ b/vendor/brick/math/src/Internal/Calculator/BcMathCalculator.php
@@ -5,110 +5,67 @@ declare(strict_types=1);
namespace Brick\Math\Internal\Calculator;
use Brick\Math\Internal\Calculator;
+use Override;
/**
* Calculator implementation built around the bcmath library.
*
* @internal
- *
- * @psalm-immutable
*/
-class BcMathCalculator extends Calculator
+final readonly class BcMathCalculator extends Calculator
{
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function add(string $a, string $b) : string
{
return \bcadd($a, $b, 0);
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function sub(string $a, string $b) : string
{
return \bcsub($a, $b, 0);
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function mul(string $a, string $b) : string
{
return \bcmul($a, $b, 0);
}
- /**
- * {@inheritdoc}
- *
- * @psalm-suppress InvalidNullableReturnType
- * @psalm-suppress NullableReturnStatement
- */
+ #[Override]
public function divQ(string $a, string $b) : string
{
return \bcdiv($a, $b, 0);
}
- /**
- * {@inheritdoc}
- *
- * @psalm-suppress InvalidNullableReturnType
- * @psalm-suppress NullableReturnStatement
- */
+ #[Override]
public function divR(string $a, string $b) : string
{
- if (version_compare(PHP_VERSION, '7.2') >= 0) {
- return \bcmod($a, $b, 0);
- }
-
- return \bcmod($a, $b);
+ return \bcmod($a, $b, 0);
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function divQR(string $a, string $b) : array
{
$q = \bcdiv($a, $b, 0);
-
- if (version_compare(PHP_VERSION, '7.2') >= 0) {
- $r = \bcmod($a, $b, 0);
- } else {
- $r = \bcmod($a, $b);
- }
-
- assert($q !== null);
- assert($r !== null);
+ $r = \bcmod($a, $b, 0);
return [$q, $r];
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function pow(string $a, int $e) : string
{
return \bcpow($a, (string) $e, 0);
}
- /**
- * {@inheritdoc}
- *
- * @psalm-suppress InvalidNullableReturnType
- * @psalm-suppress NullableReturnStatement
- */
+ #[Override]
public function modPow(string $base, string $exp, string $mod) : string
{
return \bcpowmod($base, $exp, $mod, 0);
}
- /**
- * {@inheritDoc}
- *
- * @psalm-suppress NullableReturnStatement
- * @psalm-suppress InvalidNullableReturnType
- */
+ #[Override]
public function sqrt(string $n) : string
{
return \bcsqrt($n, 0);
diff --git a/vendor/brick/math/src/Internal/Calculator/GmpCalculator.php b/vendor/brick/math/src/Internal/Calculator/GmpCalculator.php
index 52d1880..c0f9bd5 100644
--- a/vendor/brick/math/src/Internal/Calculator/GmpCalculator.php
+++ b/vendor/brick/math/src/Internal/Calculator/GmpCalculator.php
@@ -5,80 +5,68 @@ declare(strict_types=1);
namespace Brick\Math\Internal\Calculator;
use Brick\Math\Internal\Calculator;
+use GMP;
+use Override;
/**
* Calculator implementation built around the GMP library.
*
* @internal
- *
- * @psalm-immutable
*/
-class GmpCalculator extends Calculator
+final readonly class GmpCalculator extends Calculator
{
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function add(string $a, string $b) : string
{
return \gmp_strval(\gmp_add($a, $b));
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function sub(string $a, string $b) : string
{
return \gmp_strval(\gmp_sub($a, $b));
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function mul(string $a, string $b) : string
{
return \gmp_strval(\gmp_mul($a, $b));
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function divQ(string $a, string $b) : string
{
return \gmp_strval(\gmp_div_q($a, $b));
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function divR(string $a, string $b) : string
{
return \gmp_strval(\gmp_div_r($a, $b));
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function divQR(string $a, string $b) : array
{
[$q, $r] = \gmp_div_qr($a, $b);
+ /**
+ * @var GMP $q
+ * @var GMP $r
+ */
return [
\gmp_strval($q),
\gmp_strval($r)
];
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function pow(string $a, int $e) : string
{
return \gmp_strval(\gmp_pow($a, $e));
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function modInverse(string $x, string $m) : ?string
{
$result = \gmp_invert($x, $m);
@@ -90,65 +78,49 @@ class GmpCalculator extends Calculator
return \gmp_strval($result);
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function modPow(string $base, string $exp, string $mod) : string
{
return \gmp_strval(\gmp_powm($base, $exp, $mod));
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function gcd(string $a, string $b) : string
{
return \gmp_strval(\gmp_gcd($a, $b));
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function fromBase(string $number, int $base) : string
{
return \gmp_strval(\gmp_init($number, $base));
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function toBase(string $number, int $base) : string
{
return \gmp_strval($number, $base);
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function and(string $a, string $b) : string
{
return \gmp_strval(\gmp_and($a, $b));
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function or(string $a, string $b) : string
{
return \gmp_strval(\gmp_or($a, $b));
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function xor(string $a, string $b) : string
{
return \gmp_strval(\gmp_xor($a, $b));
}
- /**
- * {@inheritDoc}
- */
+ #[Override]
public function sqrt(string $n) : string
{
return \gmp_strval(\gmp_sqrt($n));
diff --git a/vendor/brick/math/src/Internal/Calculator/NativeCalculator.php b/vendor/brick/math/src/Internal/Calculator/NativeCalculator.php
index 020a633..ee476c9 100644
--- a/vendor/brick/math/src/Internal/Calculator/NativeCalculator.php
+++ b/vendor/brick/math/src/Internal/Calculator/NativeCalculator.php
@@ -5,57 +5,43 @@ declare(strict_types=1);
namespace Brick\Math\Internal\Calculator;
use Brick\Math\Internal\Calculator;
+use Override;
/**
* Calculator implementation using only native PHP code.
*
* @internal
- *
- * @psalm-immutable
*/
-class NativeCalculator extends Calculator
+final readonly class NativeCalculator extends Calculator
{
/**
* The max number of digits the platform can natively add, subtract, multiply or divide without overflow.
* For multiplication, this represents the max sum of the lengths of both operands.
*
- * For addition, it is assumed that an extra digit can hold a carry (1) without overflowing.
+ * In addition, it is assumed that an extra digit can hold a carry (1) without overflowing.
* Example: 32-bit: max number 1,999,999,999 (9 digits + carry)
* 64-bit: max number 1,999,999,999,999,999,999 (18 digits + carry)
- *
- * @var int
*/
- private $maxDigits;
+ private int $maxDigits;
/**
- * Class constructor.
- *
+ * @pure
* @codeCoverageIgnore
*/
public function __construct()
{
- switch (PHP_INT_SIZE) {
- case 4:
- $this->maxDigits = 9;
- break;
-
- case 8:
- $this->maxDigits = 18;
- break;
-
- default:
- throw new \RuntimeException('The platform is not 32-bit or 64-bit as expected.');
- }
+ $this->maxDigits = match (PHP_INT_SIZE) {
+ 4 => 9,
+ 8 => 18,
+ };
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function add(string $a, string $b) : string
{
/**
- * @psalm-var numeric-string $a
- * @psalm-var numeric-string $b
+ * @var numeric-string $a
+ * @var numeric-string $b
*/
$result = $a + $b;
@@ -82,22 +68,18 @@ class NativeCalculator extends Calculator
return $result;
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function sub(string $a, string $b) : string
{
return $this->add($a, $this->neg($b));
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function mul(string $a, string $b) : string
{
/**
- * @psalm-var numeric-string $a
- * @psalm-var numeric-string $b
+ * @var numeric-string $a
+ * @var numeric-string $b
*/
$result = $a * $b;
@@ -136,25 +118,19 @@ class NativeCalculator extends Calculator
return $result;
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function divQ(string $a, string $b) : string
{
return $this->divQR($a, $b)[0];
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function divR(string $a, string $b): string
{
return $this->divQR($a, $b)[1];
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function divQR(string $a, string $b) : array
{
if ($a === '0') {
@@ -173,20 +149,18 @@ class NativeCalculator extends Calculator
return [$this->neg($a), '0'];
}
- /** @psalm-var numeric-string $a */
+ /** @var numeric-string $a */
$na = $a * 1; // cast to number
if (is_int($na)) {
- /** @psalm-var numeric-string $b */
+ /** @var numeric-string $b */
$nb = $b * 1;
if (is_int($nb)) {
// the only division that may overflow is PHP_INT_MIN / -1,
// which cannot happen here as we've already handled a divisor of -1 above.
+ $q = intdiv($na, $nb);
$r = $na % $nb;
- $q = ($na - $r) / $nb;
-
- assert(is_int($q));
return [
(string) $q,
@@ -210,9 +184,7 @@ class NativeCalculator extends Calculator
return [$q, $r];
}
- /**
- * {@inheritdoc}
- */
+ #[Override]
public function pow(string $a, int $e) : string
{
if ($e === 0) {
@@ -228,7 +200,6 @@ class NativeCalculator extends Calculator
$aa = $this->mul($a, $a);
- /** @psalm-suppress PossiblyInvalidArgument We're sure that $e / 2 is an int now */
$result = $this->pow($aa, $e / 2);
if ($odd === 1) {
@@ -240,9 +211,8 @@ class NativeCalculator extends Calculator
/**
* Algorithm from: https://www.geeksforgeeks.org/modular-exponentiation-power-in-modular-arithmetic/
- *
- * {@inheritdoc}
*/
+ #[Override]
public function modPow(string $base, string $exp, string $mod) : string
{
// special case: the algorithm below fails with 0 power 0 mod 1 (returns 1 instead of 0)
@@ -276,9 +246,8 @@ class NativeCalculator extends Calculator
/**
* Adapted from https://cp-algorithms.com/num_methods/roots_newton.html
- *
- * {@inheritDoc}
*/
+ #[Override]
public function sqrt(string $n) : string
{
if ($n === '0') {
@@ -307,10 +276,7 @@ class NativeCalculator extends Calculator
/**
* Performs the addition of two non-signed large integers.
*
- * @param string $a The first operand.
- * @param string $b The second operand.
- *
- * @return string
+ * @pure
*/
private function doAdd(string $a, string $b) : string
{
@@ -324,14 +290,13 @@ class NativeCalculator extends Calculator
if ($i < 0) {
$blockLength += $i;
- /** @psalm-suppress LoopInvalidation */
$i = 0;
}
- /** @psalm-var numeric-string $blockA */
+ /** @var numeric-string $blockA */
$blockA = \substr($a, $i, $blockLength);
- /** @psalm-var numeric-string $blockB */
+ /** @var numeric-string $blockB */
$blockB = \substr($b, $i, $blockLength);
$sum = (string) ($blockA + $blockB + $carry);
@@ -364,10 +329,7 @@ class NativeCalculator extends Calculator
/**
* Performs the subtraction of two non-signed large integers.
*
- * @param string $a The first operand.
- * @param string $b The second operand.
- *
- * @return string
+ * @pure
*/
private function doSub(string $a, string $b) : string
{
@@ -398,14 +360,13 @@ class NativeCalculator extends Calculator
if ($i < 0) {
$blockLength += $i;
- /** @psalm-suppress LoopInvalidation */
$i = 0;
}
- /** @psalm-var numeric-string $blockA */
+ /** @var numeric-string $blockA */
$blockA = \substr($a, $i, $blockLength);
- /** @psalm-var numeric-string $blockB */
+ /** @var numeric-string $blockB */
$blockB = \substr($b, $i, $blockLength);
$sum = $blockA - $blockB - $carry;
@@ -446,10 +407,7 @@ class NativeCalculator extends Calculator
/**
* Performs the multiplication of two non-signed large integers.
*
- * @param string $a The first operand.
- * @param string $b The second operand.
- *
- * @return string
+ * @pure
*/
private function doMul(string $a, string $b) : string
{
@@ -466,7 +424,6 @@ class NativeCalculator extends Calculator
if ($i < 0) {
$blockALength += $i;
- /** @psalm-suppress LoopInvalidation */
$i = 0;
}
@@ -480,7 +437,6 @@ class NativeCalculator extends Calculator
if ($j < 0) {
$blockBLength += $j;
- /** @psalm-suppress LoopInvalidation */
$j = 0;
}
@@ -522,10 +478,9 @@ class NativeCalculator extends Calculator
/**
* Performs the division of two non-signed large integers.
*
- * @param string $a The first operand.
- * @param string $b The second operand.
- *
* @return string[] The quotient and remainder.
+ *
+ * @pure
*/
private function doDiv(string $a, string $b) : array
{
@@ -544,6 +499,22 @@ class NativeCalculator extends Calculator
$r = $a; // remainder
$z = $y; // focus length, always $y or $y+1
+ /** @var numeric-string $b */
+ $nb = $b * 1; // cast to number
+ // performance optimization in cases where the remainder will never cause int overflow
+ if (is_int(($nb - 1) * 10 + 9)) {
+ $r = (int) \substr($a, 0, $z - 1);
+
+ for ($i = $z - 1; $i < $x; $i++) {
+ $n = $r * 10 + (int) $a[$i];
+ /** @var int $nb */
+ $q .= \intdiv($n, $nb);
+ $r = $n % $nb;
+ }
+
+ return [\ltrim($q, '0') ?: '0', (string) $r];
+ }
+
for (;;) {
$focus = \substr($a, 0, $z);
@@ -583,10 +554,9 @@ class NativeCalculator extends Calculator
/**
* Compares two non-signed large numbers.
*
- * @param string $a The first operand.
- * @param string $b The second operand.
+ * @return -1|0|1
*
- * @return int [-1, 0, 1]
+ * @pure
*/
private function doCmp(string $a, string $b) : int
{
@@ -599,7 +569,7 @@ class NativeCalculator extends Calculator
return $cmp;
}
- return \strcmp($a, $b) <=> 0; // enforce [-1, 0, 1]
+ return \strcmp($a, $b) <=> 0; // enforce -1|0|1
}
/**
@@ -607,10 +577,9 @@ class NativeCalculator extends Calculator
*
* The numbers must only consist of digits, without leading minus sign.
*
- * @param string $a The first operand.
- * @param string $b The second operand.
- *
* @return array{string, string, int}
+ *
+ * @pure
*/
private function pad(string $a, string $b) : array
{
diff --git a/vendor/brick/math/src/Internal/CalculatorRegistry.php b/vendor/brick/math/src/Internal/CalculatorRegistry.php
new file mode 100644
index 0000000..394fae6
--- /dev/null
+++ b/vendor/brick/math/src/Internal/CalculatorRegistry.php
@@ -0,0 +1,73 @@
+= 0.5; otherwise, behaves as for DOWN.
* Note that this is the rounding mode commonly taught at school.
*/
- public const HALF_UP = 5;
+ case HALF_UP;
/**
* Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round down.
*
* Behaves as for UP if the discarded fraction is > 0.5; otherwise, behaves as for DOWN.
*/
- public const HALF_DOWN = 6;
+ case HALF_DOWN;
/**
* Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round towards positive infinity.
*
* If the result is positive, behaves as for HALF_UP; if negative, behaves as for HALF_DOWN.
*/
- public const HALF_CEILING = 7;
+ case HALF_CEILING;
/**
* Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round towards negative infinity.
*
* If the result is positive, behaves as for HALF_DOWN; if negative, behaves as for HALF_UP.
*/
- public const HALF_FLOOR = 8;
+ case HALF_FLOOR;
/**
* Rounds towards the "nearest neighbor" unless both neighbors are equidistant, in which case rounds towards the even neighbor.
@@ -103,5 +94,5 @@ final class RoundingMode
* cumulative error when applied repeatedly over a sequence of calculations.
* It is sometimes known as "Banker's rounding", and is chiefly used in the USA.
*/
- public const HALF_EVEN = 9;
+ case HALF_EVEN;
}
diff --git a/vendor/composer/InstalledVersions.php b/vendor/composer/InstalledVersions.php
index 51e734a..2052022 100644
--- a/vendor/composer/InstalledVersions.php
+++ b/vendor/composer/InstalledVersions.php
@@ -26,12 +26,23 @@ use Composer\Semver\VersionParser;
*/
class InstalledVersions
{
+ /**
+ * @var string|null if set (by reflection by Composer), this should be set to the path where this class is being copied to
+ * @internal
+ */
+ private static $selfDir = null;
+
/**
* @var mixed[]|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;
+ /**
+ * @var bool
+ */
+ private static $installedIsLocalDir;
+
/**
* @var bool|null
*/
@@ -309,6 +320,24 @@ class InstalledVersions
{
self::$installed = $data;
self::$installedByVendor = array();
+
+ // when using reload, we disable the duplicate protection to ensure that self::$installed data is
+ // always returned, but we cannot know whether it comes from the installed.php in __DIR__ or not,
+ // so we have to assume it does not, and that may result in duplicate data being returned when listing
+ // all installed packages for example
+ self::$installedIsLocalDir = false;
+ }
+
+ /**
+ * @return string
+ */
+ private static function getSelfDir()
+ {
+ if (self::$selfDir === null) {
+ self::$selfDir = strtr(__DIR__, '\\', '/');
+ }
+
+ return self::$selfDir;
}
/**
@@ -322,19 +351,27 @@ class InstalledVersions
}
$installed = array();
+ $copiedLocalDir = false;
if (self::$canGetVendors) {
+ $selfDir = self::getSelfDir();
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
+ $vendorDir = strtr($vendorDir, '\\', '/');
if (isset(self::$installedByVendor[$vendorDir])) {
$installed[] = self::$installedByVendor[$vendorDir];
} elseif (is_file($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];
+ self::$installedByVendor[$vendorDir] = $required;
+ $installed[] = $required;
+ if (self::$installed === null && $vendorDir.'/composer' === $selfDir) {
+ self::$installed = $required;
+ self::$installedIsLocalDir = true;
}
}
+ if (self::$installedIsLocalDir && $vendorDir.'/composer' === $selfDir) {
+ $copiedLocalDir = true;
+ }
}
}
@@ -350,7 +387,7 @@ class InstalledVersions
}
}
- if (self::$installed !== array()) {
+ if (self::$installed !== array() && !$copiedLocalDir) {
$installed[] = self::$installed;
}
diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php
index a16ffbd..005b68e 100644
--- a/vendor/composer/autoload_classmap.php
+++ b/vendor/composer/autoload_classmap.php
@@ -6,11 +6,8 @@ $vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
- 'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
- 'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
- 'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
- 'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
- 'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
+ 'Deprecated' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/Deprecated.php',
+ 'ReflectionConstant' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/ReflectionConstant.php',
'lessc' => $vendorDir . '/wikimedia/less.php/lessc.inc.php',
);
diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php
index 39e9a0d..6eb2a75 100644
--- a/vendor/composer/autoload_files.php
+++ b/vendor/composer/autoload_files.php
@@ -8,9 +8,8 @@ $baseDir = dirname($vendorDir);
return array(
'a2c78434f64e5f5ed402f42eee19c025' => $vendorDir . '/ipl/stdlib/src/functions_include.php',
'6076de347104821999fcfc82c8f19bc5' => $vendorDir . '/ipl/i18n/src/functions_include.php',
+ '9d2b9fc6db0f153a0a149fefb182415e' => $vendorDir . '/symfony/polyfill-php84/bootstrap.php',
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
- '320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
- 'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
'e39a8b23c42d4e1452234d762b03835a' => $vendorDir . '/ramsey/uuid/src/functions.php',
'ad155f8f1cf0d418fe49e248db8c661b' => $vendorDir . '/react/promise/src/functions_include.php',
'8e4ccce73649a2b516ec3b4571432da5' => $vendorDir . '/ipl/scheduler/src/register_cron_aliases.php',
diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php
index 225315a..7b48d35 100644
--- a/vendor/composer/autoload_psr4.php
+++ b/vendor/composer/autoload_psr4.php
@@ -14,21 +14,18 @@ return array(
'ipl\\Orm\\' => array($vendorDir . '/ipl/orm/src'),
'ipl\\I18n\\' => array($vendorDir . '/ipl/i18n/src'),
'ipl\\Html\\' => array($vendorDir . '/ipl/html/src'),
- 'cweagans\\Composer\\' => array($vendorDir . '/cweagans/composer-patches/src'),
- 'Webmozart\\Assert\\' => array($vendorDir . '/webmozart/assert/src'),
- 'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'),
- 'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
+ 'Symfony\\Polyfill\\Php84\\' => array($vendorDir . '/symfony/polyfill-php84'),
'Recurr\\' => array($vendorDir . '/simshaun/recurr/src/Recurr'),
'React\\Promise\\' => array($vendorDir . '/react/promise/src'),
'React\\EventLoop\\' => array($vendorDir . '/react/event-loop/src'),
'Ramsey\\Uuid\\' => array($vendorDir . '/ramsey/uuid/src'),
'Ramsey\\Collection\\' => array($vendorDir . '/ramsey/collection/src'),
'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
- 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src', $vendorDir . '/psr/http-factory/src'),
+ 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'),
'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
'Evenement\\' => array($vendorDir . '/evenement/evenement/src'),
'Doctrine\\Deprecations\\' => array($vendorDir . '/doctrine/deprecations/src'),
- 'Doctrine\\Common\\Collections\\' => array($vendorDir . '/doctrine/collections/lib/Doctrine/Common/Collections'),
+ 'Doctrine\\Common\\Collections\\' => array($vendorDir . '/doctrine/collections/src'),
'Cron\\' => array($vendorDir . '/dragonmantank/cron-expression/src/Cron'),
'Brick\\Math\\' => array($vendorDir . '/brick/math/src'),
);
diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php
index e12b2c4..02157ed 100644
--- a/vendor/composer/autoload_real.php
+++ b/vendor/composer/autoload_real.php
@@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
-class ComposerAutoloaderInit20d4022bc196691807f55d4a47c06474
+class ComposerAutoloaderInit7a1692c86b6fc70eaaf43c4bee3673aa
{
private static $loader;
@@ -24,16 +24,16 @@ class ComposerAutoloaderInit20d4022bc196691807f55d4a47c06474
require __DIR__ . '/platform_check.php';
- spl_autoload_register(array('ComposerAutoloaderInit20d4022bc196691807f55d4a47c06474', 'loadClassLoader'), true, true);
+ spl_autoload_register(array('ComposerAutoloaderInit7a1692c86b6fc70eaaf43c4bee3673aa', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
- spl_autoload_unregister(array('ComposerAutoloaderInit20d4022bc196691807f55d4a47c06474', 'loadClassLoader'));
+ spl_autoload_unregister(array('ComposerAutoloaderInit7a1692c86b6fc70eaaf43c4bee3673aa', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
- call_user_func(\Composer\Autoload\ComposerStaticInit20d4022bc196691807f55d4a47c06474::getInitializer($loader));
+ call_user_func(\Composer\Autoload\ComposerStaticInit7a1692c86b6fc70eaaf43c4bee3673aa::getInitializer($loader));
$loader->register(true);
- $filesToLoad = \Composer\Autoload\ComposerStaticInit20d4022bc196691807f55d4a47c06474::$files;
+ $filesToLoad = \Composer\Autoload\ComposerStaticInit7a1692c86b6fc70eaaf43c4bee3673aa::$files;
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php
index c727743..09a88e3 100644
--- a/vendor/composer/autoload_static.php
+++ b/vendor/composer/autoload_static.php
@@ -4,14 +4,13 @@
namespace Composer\Autoload;
-class ComposerStaticInit20d4022bc196691807f55d4a47c06474
+class ComposerStaticInit7a1692c86b6fc70eaaf43c4bee3673aa
{
public static $files = array (
'a2c78434f64e5f5ed402f42eee19c025' => __DIR__ . '/..' . '/ipl/stdlib/src/functions_include.php',
'6076de347104821999fcfc82c8f19bc5' => __DIR__ . '/..' . '/ipl/i18n/src/functions_include.php',
+ '9d2b9fc6db0f153a0a149fefb182415e' => __DIR__ . '/..' . '/symfony/polyfill-php84/bootstrap.php',
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
- '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
- 'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
'e39a8b23c42d4e1452234d762b03835a' => __DIR__ . '/..' . '/ramsey/uuid/src/functions.php',
'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php',
'8e4ccce73649a2b516ec3b4571432da5' => __DIR__ . '/..' . '/ipl/scheduler/src/register_cron_aliases.php',
@@ -29,18 +28,9 @@ class ComposerStaticInit20d4022bc196691807f55d4a47c06474
'ipl\\I18n\\' => 9,
'ipl\\Html\\' => 9,
),
- 'c' =>
- array (
- 'cweagans\\Composer\\' => 18,
- ),
- 'W' =>
- array (
- 'Webmozart\\Assert\\' => 17,
- ),
'S' =>
array (
- 'Symfony\\Polyfill\\Php80\\' => 23,
- 'Symfony\\Polyfill\\Ctype\\' => 23,
+ 'Symfony\\Polyfill\\Php84\\' => 23,
),
'R' =>
array (
@@ -111,21 +101,9 @@ class ComposerStaticInit20d4022bc196691807f55d4a47c06474
array (
0 => __DIR__ . '/..' . '/ipl/html/src',
),
- 'cweagans\\Composer\\' =>
+ 'Symfony\\Polyfill\\Php84\\' =>
array (
- 0 => __DIR__ . '/..' . '/cweagans/composer-patches/src',
- ),
- 'Webmozart\\Assert\\' =>
- array (
- 0 => __DIR__ . '/..' . '/webmozart/assert/src',
- ),
- 'Symfony\\Polyfill\\Php80\\' =>
- array (
- 0 => __DIR__ . '/..' . '/symfony/polyfill-php80',
- ),
- 'Symfony\\Polyfill\\Ctype\\' =>
- array (
- 0 => __DIR__ . '/..' . '/symfony/polyfill-ctype',
+ 0 => __DIR__ . '/..' . '/symfony/polyfill-php84',
),
'Recurr\\' =>
array (
@@ -153,8 +131,8 @@ class ComposerStaticInit20d4022bc196691807f55d4a47c06474
),
'Psr\\Http\\Message\\' =>
array (
- 0 => __DIR__ . '/..' . '/psr/http-message/src',
- 1 => __DIR__ . '/..' . '/psr/http-factory/src',
+ 0 => __DIR__ . '/..' . '/psr/http-factory/src',
+ 1 => __DIR__ . '/..' . '/psr/http-message/src',
),
'GuzzleHttp\\Psr7\\' =>
array (
@@ -170,7 +148,7 @@ class ComposerStaticInit20d4022bc196691807f55d4a47c06474
),
'Doctrine\\Common\\Collections\\' =>
array (
- 0 => __DIR__ . '/..' . '/doctrine/collections/lib/Doctrine/Common/Collections',
+ 0 => __DIR__ . '/..' . '/doctrine/collections/src',
),
'Cron\\' =>
array (
@@ -200,22 +178,19 @@ class ComposerStaticInit20d4022bc196691807f55d4a47c06474
);
public static $classMap = array (
- 'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
- 'PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
- 'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
- 'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
- 'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
+ 'Deprecated' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/Deprecated.php',
+ 'ReflectionConstant' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/ReflectionConstant.php',
'lessc' => __DIR__ . '/..' . '/wikimedia/less.php/lessc.inc.php',
);
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
- $loader->prefixLengthsPsr4 = ComposerStaticInit20d4022bc196691807f55d4a47c06474::$prefixLengthsPsr4;
- $loader->prefixDirsPsr4 = ComposerStaticInit20d4022bc196691807f55d4a47c06474::$prefixDirsPsr4;
- $loader->prefixesPsr0 = ComposerStaticInit20d4022bc196691807f55d4a47c06474::$prefixesPsr0;
- $loader->classMap = ComposerStaticInit20d4022bc196691807f55d4a47c06474::$classMap;
+ $loader->prefixLengthsPsr4 = ComposerStaticInit7a1692c86b6fc70eaaf43c4bee3673aa::$prefixLengthsPsr4;
+ $loader->prefixDirsPsr4 = ComposerStaticInit7a1692c86b6fc70eaaf43c4bee3673aa::$prefixDirsPsr4;
+ $loader->prefixesPsr0 = ComposerStaticInit7a1692c86b6fc70eaaf43c4bee3673aa::$prefixesPsr0;
+ $loader->classMap = ComposerStaticInit7a1692c86b6fc70eaaf43c4bee3673aa::$classMap;
}, null, ClassLoader::class);
}
diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json
index d19f842..f69bb4a 100644
--- a/vendor/composer/installed.json
+++ b/vendor/composer/installed.json
@@ -2,29 +2,28 @@
"packages": [
{
"name": "brick/math",
- "version": "0.9.3",
- "version_normalized": "0.9.3.0",
+ "version": "0.14.0",
+ "version_normalized": "0.14.0.0",
"source": {
"type": "git",
"url": "https://github.com/brick/math.git",
- "reference": "ca57d18f028f84f777b2168cd1911b0dee2343ae"
+ "reference": "113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/brick/math/zipball/ca57d18f028f84f777b2168cd1911b0dee2343ae",
- "reference": "ca57d18f028f84f777b2168cd1911b0dee2343ae",
+ "url": "https://api.github.com/repos/brick/math/zipball/113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2",
+ "reference": "113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2",
"shasum": ""
},
"require": {
- "ext-json": "*",
- "php": "^7.1 || ^8.0"
+ "php": "^8.2"
},
"require-dev": {
"php-coveralls/php-coveralls": "^2.2",
- "phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.0",
- "vimeo/psalm": "4.9.2"
+ "phpstan/phpstan": "2.1.22",
+ "phpunit/phpunit": "^11.5"
},
- "time": "2021-08-15T20:50:18+00:00",
+ "time": "2025-08-29T12:40:03+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -44,107 +43,59 @@
"arithmetic",
"bigdecimal",
"bignum",
+ "bignumber",
"brick",
- "math"
+ "decimal",
+ "integer",
+ "math",
+ "mathematics",
+ "rational"
],
"support": {
"issues": "https://github.com/brick/math/issues",
- "source": "https://github.com/brick/math/tree/0.9.3"
+ "source": "https://github.com/brick/math/tree/0.14.0"
},
"funding": [
{
"url": "https://github.com/BenMorel",
"type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/brick/math",
- "type": "tidelift"
}
],
"install-path": "../brick/math"
},
- {
- "name": "cweagans/composer-patches",
- "version": "1.7.3",
- "version_normalized": "1.7.3.0",
- "source": {
- "type": "git",
- "url": "https://github.com/cweagans/composer-patches.git",
- "reference": "e190d4466fe2b103a55467dfa83fc2fecfcaf2db"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/cweagans/composer-patches/zipball/e190d4466fe2b103a55467dfa83fc2fecfcaf2db",
- "reference": "e190d4466fe2b103a55467dfa83fc2fecfcaf2db",
- "shasum": ""
- },
- "require": {
- "composer-plugin-api": "^1.0 || ^2.0",
- "php": ">=5.3.0"
- },
- "require-dev": {
- "composer/composer": "~1.0 || ~2.0",
- "phpunit/phpunit": "~4.6"
- },
- "time": "2022-12-20T22:53:13+00:00",
- "type": "composer-plugin",
- "extra": {
- "class": "cweagans\\Composer\\Patches"
- },
- "installation-source": "dist",
- "autoload": {
- "psr-4": {
- "cweagans\\Composer\\": "src"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Cameron Eagans",
- "email": "me@cweagans.net"
- }
- ],
- "description": "Provides a way to patch Composer packages.",
- "support": {
- "issues": "https://github.com/cweagans/composer-patches/issues",
- "source": "https://github.com/cweagans/composer-patches/tree/1.7.3"
- },
- "install-path": "../cweagans/composer-patches"
- },
{
"name": "doctrine/collections",
- "version": "1.8.0",
- "version_normalized": "1.8.0.0",
+ "version": "2.4.0",
+ "version_normalized": "2.4.0.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/collections.git",
- "reference": "2b44dd4cbca8b5744327de78bafef5945c7e7b5e"
+ "reference": "9acfeea2e8666536edff3d77c531261c63680160"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/collections/zipball/2b44dd4cbca8b5744327de78bafef5945c7e7b5e",
- "reference": "2b44dd4cbca8b5744327de78bafef5945c7e7b5e",
+ "url": "https://api.github.com/repos/doctrine/collections/zipball/9acfeea2e8666536edff3d77c531261c63680160",
+ "reference": "9acfeea2e8666536edff3d77c531261c63680160",
"shasum": ""
},
"require": {
- "doctrine/deprecations": "^0.5.3 || ^1",
- "php": "^7.1.3 || ^8.0"
+ "doctrine/deprecations": "^1",
+ "php": "^8.1",
+ "symfony/polyfill-php84": "^1.30"
},
"require-dev": {
- "doctrine/coding-standard": "^9.0 || ^10.0",
- "phpstan/phpstan": "^1.4.8",
- "phpunit/phpunit": "^7.5 || ^8.5 || ^9.1.5",
- "vimeo/psalm": "^4.22"
+ "doctrine/coding-standard": "^14",
+ "ext-json": "*",
+ "phpstan/phpstan": "^2.1.30",
+ "phpstan/phpstan-phpunit": "^2.0.7",
+ "phpunit/phpunit": "^10.5.58 || ^11.5.42 || ^12.4"
},
- "time": "2022-09-01T20:12:10+00:00",
+ "time": "2025-10-25T09:18:13+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
- "Doctrine\\Common\\Collections\\": "lib/Doctrine/Common/Collections"
+ "Doctrine\\Common\\Collections\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -183,8 +134,22 @@
],
"support": {
"issues": "https://github.com/doctrine/collections/issues",
- "source": "https://github.com/doctrine/collections/tree/1.8.0"
+ "source": "https://github.com/doctrine/collections/tree/2.4.0"
},
+ "funding": [
+ {
+ "url": "https://www.doctrine-project.org/sponsorship.html",
+ "type": "custom"
+ },
+ {
+ "url": "https://www.patreon.com/phpdoctrine",
+ "type": "patreon"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcollections",
+ "type": "tidelift"
+ }
+ ],
"install-path": "../doctrine/collections"
},
{
@@ -240,32 +205,31 @@
},
{
"name": "dragonmantank/cron-expression",
- "version": "v3.4.0",
- "version_normalized": "3.4.0.0",
+ "version": "v3.6.0",
+ "version_normalized": "3.6.0.0",
"source": {
"type": "git",
"url": "https://github.com/dragonmantank/cron-expression.git",
- "reference": "8c784d071debd117328803d86b2097615b457500"
+ "reference": "d61a8a9604ec1f8c3d150d09db6ce98b32675013"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/8c784d071debd117328803d86b2097615b457500",
- "reference": "8c784d071debd117328803d86b2097615b457500",
+ "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/d61a8a9604ec1f8c3d150d09db6ce98b32675013",
+ "reference": "d61a8a9604ec1f8c3d150d09db6ce98b32675013",
"shasum": ""
},
"require": {
- "php": "^7.2|^8.0",
- "webmozart/assert": "^1.0"
+ "php": "^8.2|^8.3|^8.4|^8.5"
},
"replace": {
"mtdowling/cron-expression": "^1.0"
},
"require-dev": {
- "phpstan/extension-installer": "^1.0",
- "phpstan/phpstan": "^1.0",
- "phpunit/phpunit": "^7.0|^8.0|^9.0"
+ "phpstan/extension-installer": "^1.4.3",
+ "phpstan/phpstan": "^1.12.32|^2.1.31",
+ "phpunit/phpunit": "^8.5.48|^9.0"
},
- "time": "2024-10-09T13:47:03+00:00",
+ "time": "2025-10-31T18:51:33+00:00",
"type": "library",
"extra": {
"branch-alias": {
@@ -296,7 +260,7 @@
],
"support": {
"issues": "https://github.com/dragonmantank/cron-expression/issues",
- "source": "https://github.com/dragonmantank/cron-expression/tree/v3.4.0"
+ "source": "https://github.com/dragonmantank/cron-expression/tree/v3.6.0"
},
"funding": [
{
@@ -525,17 +489,17 @@
},
{
"name": "ipl/html",
- "version": "v0.8.2",
- "version_normalized": "0.8.2.0",
+ "version": "dev-main",
+ "version_normalized": "dev-main",
"source": {
"type": "git",
"url": "https://github.com/Icinga/ipl-html.git",
- "reference": "e18bdf11abca5e477100e2c7d190ef5f424d0d98"
+ "reference": "9354c29faf807e67c4a0a365b450b7f0b64598ad"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Icinga/ipl-html/zipball/e18bdf11abca5e477100e2c7d190ef5f424d0d98",
- "reference": "e18bdf11abca5e477100e2c7d190ef5f424d0d98",
+ "url": "https://api.github.com/repos/Icinga/ipl-html/zipball/9354c29faf807e67c4a0a365b450b7f0b64598ad",
+ "reference": "9354c29faf807e67c4a0a365b450b7f0b64598ad",
"shasum": ""
},
"require": {
@@ -543,14 +507,16 @@
"guzzlehttp/psr7": "^2.5",
"ipl/stdlib": ">=0.12.0",
"ipl/validator": ">=0.5.0",
- "php": ">=7.2",
+ "php": ">=8.2",
"psr/http-message": "^1.1"
},
"require-dev": {
+ "ext-dom": "*",
"ipl/stdlib": "dev-main",
"ipl/validator": "dev-main"
},
- "time": "2025-05-21T09:00:03+00:00",
+ "time": "2025-10-29T14:21:51+00:00",
+ "default-branch": true,
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -569,23 +535,23 @@
],
"support": {
"issues": "https://github.com/Icinga/ipl-html/issues",
- "source": "https://github.com/Icinga/ipl-html/tree/v0.8.2"
+ "source": "https://github.com/Icinga/ipl-html/tree/main"
},
"install-path": "../ipl/html"
},
{
"name": "ipl/i18n",
- "version": "v0.2.2",
- "version_normalized": "0.2.2.0",
+ "version": "dev-main",
+ "version_normalized": "dev-main",
"source": {
"type": "git",
"url": "https://github.com/Icinga/ipl-i18n.git",
- "reference": "a2b6109c5a93f86ce46d5dc351dbe75e8502cf8c"
+ "reference": "692c33cf46fb8a4511da613dbf97c6216c345cc5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Icinga/ipl-i18n/zipball/a2b6109c5a93f86ce46d5dc351dbe75e8502cf8c",
- "reference": "a2b6109c5a93f86ce46d5dc351dbe75e8502cf8c",
+ "url": "https://api.github.com/repos/Icinga/ipl-i18n/zipball/692c33cf46fb8a4511da613dbf97c6216c345cc5",
+ "reference": "692c33cf46fb8a4511da613dbf97c6216c345cc5",
"shasum": ""
},
"require": {
@@ -597,7 +563,8 @@
"require-dev": {
"ipl/stdlib": "dev-main"
},
- "time": "2024-04-08T12:28:47+00:00",
+ "time": "2025-06-12T11:57:41+00:00",
+ "default-branch": true,
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -623,37 +590,38 @@
],
"support": {
"issues": "https://github.com/Icinga/ipl-i18n/issues",
- "source": "https://github.com/Icinga/ipl-i18n/tree/v0.2.2"
+ "source": "https://github.com/Icinga/ipl-i18n/tree/main"
},
"install-path": "../ipl/i18n"
},
{
"name": "ipl/orm",
- "version": "v0.6.3",
- "version_normalized": "0.6.3.0",
+ "version": "dev-main",
+ "version_normalized": "dev-main",
"source": {
"type": "git",
"url": "https://github.com/Icinga/ipl-orm.git",
- "reference": "a775a2745764a8dc7f28618cce69dcd7bbfd7915"
+ "reference": "dbcb2da01c168a02fe264e075e1c02c7233851df"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Icinga/ipl-orm/zipball/a775a2745764a8dc7f28618cce69dcd7bbfd7915",
- "reference": "a775a2745764a8dc7f28618cce69dcd7bbfd7915",
+ "url": "https://api.github.com/repos/Icinga/ipl-orm/zipball/dbcb2da01c168a02fe264e075e1c02c7233851df",
+ "reference": "dbcb2da01c168a02fe264e075e1c02c7233851df",
"shasum": ""
},
"require": {
"ext-pdo": "*",
"ipl/sql": ">=0.7.0",
"ipl/stdlib": ">=0.12.0",
- "php": ">=7.2"
+ "php": ">=8.2"
},
"require-dev": {
"ext-pdo_sqlite": "*",
"ipl/sql": "dev-main",
"ipl/stdlib": "dev-main"
},
- "time": "2025-06-12T11:57:55+00:00",
+ "time": "2025-11-06T09:05:06+00:00",
+ "default-branch": true,
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -674,23 +642,23 @@
],
"support": {
"issues": "https://github.com/Icinga/ipl-orm/issues",
- "source": "https://github.com/Icinga/ipl-orm/tree/v0.6.3"
+ "source": "https://github.com/Icinga/ipl-orm/tree/main"
},
"install-path": "../ipl/orm"
},
{
"name": "ipl/scheduler",
- "version": "v0.1.2",
- "version_normalized": "0.1.2.0",
+ "version": "dev-main",
+ "version_normalized": "dev-main",
"source": {
"type": "git",
"url": "https://github.com/Icinga/ipl-scheduler.git",
- "reference": "6119afdea07b1390bd728e350e0d80b26ec8d6ba"
+ "reference": "d15143b2db2623b42bd25a013a73800dae2c6459"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Icinga/ipl-scheduler/zipball/6119afdea07b1390bd728e350e0d80b26ec8d6ba",
- "reference": "6119afdea07b1390bd728e350e0d80b26ec8d6ba",
+ "url": "https://api.github.com/repos/Icinga/ipl-scheduler/zipball/d15143b2db2623b42bd25a013a73800dae2c6459",
+ "reference": "d15143b2db2623b42bd25a013a73800dae2c6459",
"shasum": ""
},
"require": {
@@ -710,7 +678,8 @@
"suggest": {
"ext-ev": "Improves performance, efficiency and avoids system limitations. Highly recommended! (See https://www.php.net/manual/en/intro.ev.php for details)"
},
- "time": "2023-08-30T14:14:23+00:00",
+ "time": "2025-11-03T08:42:06+00:00",
+ "default-branch": true,
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -735,23 +704,23 @@
],
"support": {
"issues": "https://github.com/Icinga/ipl-scheduler/issues",
- "source": "https://github.com/Icinga/ipl-scheduler/tree/v0.1.2"
+ "source": "https://github.com/Icinga/ipl-scheduler/tree/main"
},
"install-path": "../ipl/scheduler"
},
{
"name": "ipl/sql",
- "version": "v0.7.1",
- "version_normalized": "0.7.1.0",
+ "version": "dev-main",
+ "version_normalized": "dev-main",
"source": {
"type": "git",
"url": "https://github.com/Icinga/ipl-sql.git",
- "reference": "e80f1b712c4b96099b0bf9096e6efe317a165e3b"
+ "reference": "6f4258c4e3b20655db57d248e26edf7b54c04729"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Icinga/ipl-sql/zipball/e80f1b712c4b96099b0bf9096e6efe317a165e3b",
- "reference": "e80f1b712c4b96099b0bf9096e6efe317a165e3b",
+ "url": "https://api.github.com/repos/Icinga/ipl-sql/zipball/6f4258c4e3b20655db57d248e26edf7b54c04729",
+ "reference": "6f4258c4e3b20655db57d248e26edf7b54c04729",
"shasum": ""
},
"require": {
@@ -762,7 +731,8 @@
"require-dev": {
"ipl/stdlib": "dev-main"
},
- "time": "2024-06-25T09:55:43+00:00",
+ "time": "2025-10-08T07:03:38+00:00",
+ "default-branch": true,
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -782,23 +752,23 @@
],
"support": {
"issues": "https://github.com/Icinga/ipl-sql/issues",
- "source": "https://github.com/Icinga/ipl-sql/tree/v0.7.1"
+ "source": "https://github.com/Icinga/ipl-sql/tree/main"
},
"install-path": "../ipl/sql"
},
{
"name": "ipl/stdlib",
- "version": "v0.14.0",
- "version_normalized": "0.14.0.0",
+ "version": "dev-main",
+ "version_normalized": "dev-main",
"source": {
"type": "git",
"url": "https://github.com/Icinga/ipl-stdlib.git",
- "reference": "bf5fc8f40b86bd90337db6f3be389be2a93fa64a"
+ "reference": "9b7a903fbfc341da59f242149ac333594e4a6fa3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Icinga/ipl-stdlib/zipball/bf5fc8f40b86bd90337db6f3be389be2a93fa64a",
- "reference": "bf5fc8f40b86bd90337db6f3be389be2a93fa64a",
+ "url": "https://api.github.com/repos/Icinga/ipl-stdlib/zipball/9b7a903fbfc341da59f242149ac333594e4a6fa3",
+ "reference": "9b7a903fbfc341da59f242149ac333594e4a6fa3",
"shasum": ""
},
"require": {
@@ -806,7 +776,8 @@
"ext-openssl": "*",
"php": ">=7.2"
},
- "time": "2024-04-22T08:47:08+00:00",
+ "time": "2025-09-05T12:07:21+00:00",
+ "default-branch": true,
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -824,23 +795,23 @@
"description": "ipl Standard Library",
"support": {
"issues": "https://github.com/Icinga/ipl-stdlib/issues",
- "source": "https://github.com/Icinga/ipl-stdlib/tree/v0.14.0"
+ "source": "https://github.com/Icinga/ipl-stdlib/tree/main"
},
"install-path": "../ipl/stdlib"
},
{
"name": "ipl/validator",
- "version": "v0.5.0",
- "version_normalized": "0.5.0.0",
+ "version": "dev-main",
+ "version_normalized": "dev-main",
"source": {
"type": "git",
"url": "https://github.com/Icinga/ipl-validator.git",
- "reference": "a601fae0ed330e63cea50e4a2a6659ca1ad97bde"
+ "reference": "eac5c6c114d8007db5c24ae159fe6f55e89a946b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Icinga/ipl-validator/zipball/a601fae0ed330e63cea50e4a2a6659ca1ad97bde",
- "reference": "a601fae0ed330e63cea50e4a2a6659ca1ad97bde",
+ "url": "https://api.github.com/repos/Icinga/ipl-validator/zipball/eac5c6c114d8007db5c24ae159fe6f55e89a946b",
+ "reference": "eac5c6c114d8007db5c24ae159fe6f55e89a946b",
"shasum": ""
},
"require": {
@@ -849,12 +820,15 @@
"ipl/i18n": ">=0.2.0",
"ipl/stdlib": ">=0.12.0",
"php": ">=7.2",
- "psr/http-message": "~1.0"
+ "psr/http-message": "^1.1"
},
"require-dev": {
- "guzzlehttp/psr7": "^1"
+ "guzzlehttp/psr7": "^1",
+ "ipl/i18n": "dev-main",
+ "ipl/stdlib": "dev-main"
},
- "time": "2023-03-21T15:59:00+00:00",
+ "time": "2025-06-12T11:59:27+00:00",
+ "default-branch": true,
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -870,34 +844,34 @@
"homepage": "https://github.com/Icinga/ipl-validator",
"support": {
"issues": "https://github.com/Icinga/ipl-validator/issues",
- "source": "https://github.com/Icinga/ipl-validator/tree/v0.5.0"
+ "source": "https://github.com/Icinga/ipl-validator/tree/main"
},
"install-path": "../ipl/validator"
},
{
"name": "ipl/web",
- "version": "v0.10.2",
- "version_normalized": "0.10.2.0",
+ "version": "dev-main",
+ "version_normalized": "dev-main",
"source": {
"type": "git",
"url": "https://github.com/Icinga/ipl-web.git",
- "reference": "a3d134c0d67aa51a9b186519c76e718603fda835"
+ "reference": "3e8867cbdde8af9724f64b84830503f8fcbd90e8"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Icinga/ipl-web/zipball/a3d134c0d67aa51a9b186519c76e718603fda835",
- "reference": "a3d134c0d67aa51a9b186519c76e718603fda835",
+ "url": "https://api.github.com/repos/Icinga/ipl-web/zipball/3e8867cbdde8af9724f64b84830503f8fcbd90e8",
+ "reference": "3e8867cbdde8af9724f64b84830503f8fcbd90e8",
"shasum": ""
},
"require": {
"ext-json": "*",
"fortawesome/font-awesome": "^6",
- "ipl/html": ">=0.8.0",
+ "ipl/html": ">=0.9.0",
"ipl/i18n": ">=0.2.0",
"ipl/orm": ">=0.5.2",
"ipl/scheduler": ">=0.1.0",
"ipl/stdlib": ">=0.13.0",
- "php": ">=7.2",
+ "php": ">=8.2",
"psr/http-message": "^1.1",
"wikimedia/less.php": "^3.2.1"
},
@@ -909,7 +883,8 @@
"ipl/stdlib": "dev-main",
"shardj/zf1-future": "^1.22"
},
- "time": "2025-03-26T07:49:58+00:00",
+ "time": "2025-10-31T09:12:36+00:00",
+ "default-branch": true,
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -928,7 +903,7 @@
],
"support": {
"issues": "https://github.com/Icinga/ipl-web/issues",
- "source": "https://github.com/Icinga/ipl-web/tree/v0.10.2"
+ "source": "https://github.com/Icinga/ipl-web/tree/main"
},
"install-path": "../ipl/web"
},
@@ -1148,45 +1123,49 @@
},
{
"name": "ramsey/collection",
- "version": "1.1.4",
- "version_normalized": "1.1.4.0",
+ "version": "2.1.1",
+ "version_normalized": "2.1.1.0",
"source": {
"type": "git",
"url": "https://github.com/ramsey/collection.git",
- "reference": "ab2237657ad99667a5143e32ba2683c8029563d4"
+ "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/ramsey/collection/zipball/ab2237657ad99667a5143e32ba2683c8029563d4",
- "reference": "ab2237657ad99667a5143e32ba2683c8029563d4",
+ "url": "https://api.github.com/repos/ramsey/collection/zipball/344572933ad0181accbf4ba763e85a0306a8c5e2",
+ "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2",
"shasum": ""
},
"require": {
- "php": "^7.2 || ^8"
+ "php": "^8.1"
},
"require-dev": {
- "captainhook/captainhook": "^5.3",
- "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
- "ergebnis/composer-normalize": "^2.6",
- "fakerphp/faker": "^1.5",
- "hamcrest/hamcrest-php": "^2",
- "jangregor/phpstan-prophecy": "^0.8",
- "mockery/mockery": "^1.3",
- "phpstan/extension-installer": "^1",
- "phpstan/phpstan": "^0.12.32",
- "phpstan/phpstan-mockery": "^0.12.5",
- "phpstan/phpstan-phpunit": "^0.12.11",
- "phpunit/phpunit": "^8.5 || ^9",
- "psy/psysh": "^0.10.4",
- "slevomat/coding-standard": "^6.3",
- "squizlabs/php_codesniffer": "^3.5",
- "vimeo/psalm": "^4.4"
+ "captainhook/plugin-composer": "^5.3",
+ "ergebnis/composer-normalize": "^2.45",
+ "fakerphp/faker": "^1.24",
+ "hamcrest/hamcrest-php": "^2.0",
+ "jangregor/phpstan-prophecy": "^2.1",
+ "mockery/mockery": "^1.6",
+ "php-parallel-lint/php-console-highlighter": "^1.0",
+ "php-parallel-lint/php-parallel-lint": "^1.4",
+ "phpspec/prophecy-phpunit": "^2.3",
+ "phpstan/extension-installer": "^1.4",
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-mockery": "^2.0",
+ "phpstan/phpstan-phpunit": "^2.0",
+ "phpunit/phpunit": "^10.5",
+ "ramsey/coding-standard": "^2.3",
+ "ramsey/conventional-commits": "^1.6",
+ "roave/security-advisories": "dev-latest"
},
- "time": "2021-07-30T00:58:27+00:00",
+ "time": "2025-03-22T05:38:12+00:00",
"type": "library",
"extra": {
- "patches_applied": {
- "Collection: Add PHP 8.1 support": "patches/ramsey-collection.patch"
+ "captainhook": {
+ "force-install": true
+ },
+ "ramsey/conventional-commits": {
+ "configFile": "conventional-commits.json"
}
},
"installation-source": "dist",
@@ -1206,7 +1185,7 @@
"homepage": "https://benramsey.com"
}
],
- "description": "A PHP 7.2+ library for representing and manipulating collections.",
+ "description": "A PHP library for representing and manipulating collections.",
"keywords": [
"array",
"collection",
@@ -1217,84 +1196,64 @@
],
"support": {
"issues": "https://github.com/ramsey/collection/issues",
- "source": "https://github.com/ramsey/collection/tree/1.1.4"
+ "source": "https://github.com/ramsey/collection/tree/2.1.1"
},
- "funding": [
- {
- "url": "https://github.com/ramsey",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/ramsey/collection",
- "type": "tidelift"
- }
- ],
"install-path": "../ramsey/collection"
},
{
"name": "ramsey/uuid",
- "version": "4.2.3",
- "version_normalized": "4.2.3.0",
+ "version": "4.9.1",
+ "version_normalized": "4.9.1.0",
"source": {
"type": "git",
"url": "https://github.com/ramsey/uuid.git",
- "reference": "fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df"
+ "reference": "81f941f6f729b1e3ceea61d9d014f8b6c6800440"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/ramsey/uuid/zipball/fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df",
- "reference": "fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df",
+ "url": "https://api.github.com/repos/ramsey/uuid/zipball/81f941f6f729b1e3ceea61d9d014f8b6c6800440",
+ "reference": "81f941f6f729b1e3ceea61d9d014f8b6c6800440",
"shasum": ""
},
"require": {
- "brick/math": "^0.8 || ^0.9",
- "ext-json": "*",
- "php": "^7.2 || ^8.0",
- "ramsey/collection": "^1.0",
- "symfony/polyfill-ctype": "^1.8",
- "symfony/polyfill-php80": "^1.14"
+ "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13 || ^0.14",
+ "php": "^8.0",
+ "ramsey/collection": "^1.2 || ^2.0"
},
"replace": {
"rhumsaa/uuid": "self.version"
},
"require-dev": {
- "captainhook/captainhook": "^5.10",
+ "captainhook/captainhook": "^5.25",
"captainhook/plugin-composer": "^5.3",
- "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
- "doctrine/annotations": "^1.8",
- "ergebnis/composer-normalize": "^2.15",
- "mockery/mockery": "^1.3",
- "moontoast/math": "^1.1",
+ "dealerdirect/phpcodesniffer-composer-installer": "^1.0",
+ "ergebnis/composer-normalize": "^2.47",
+ "mockery/mockery": "^1.6",
"paragonie/random-lib": "^2",
- "php-mock/php-mock": "^2.2",
- "php-mock/php-mock-mockery": "^1.3",
- "php-parallel-lint/php-parallel-lint": "^1.1",
- "phpbench/phpbench": "^1.0",
- "phpstan/extension-installer": "^1.0",
- "phpstan/phpstan": "^0.12",
- "phpstan/phpstan-mockery": "^0.12",
- "phpstan/phpstan-phpunit": "^0.12",
- "phpunit/phpunit": "^8.5 || ^9",
- "slevomat/coding-standard": "^7.0",
- "squizlabs/php_codesniffer": "^3.5",
- "vimeo/psalm": "^4.9"
+ "php-mock/php-mock": "^2.6",
+ "php-mock/php-mock-mockery": "^1.5",
+ "php-parallel-lint/php-parallel-lint": "^1.4.0",
+ "phpbench/phpbench": "^1.2.14",
+ "phpstan/extension-installer": "^1.4",
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-mockery": "^2.0",
+ "phpstan/phpstan-phpunit": "^2.0",
+ "phpunit/phpunit": "^9.6",
+ "slevomat/coding-standard": "^8.18",
+ "squizlabs/php_codesniffer": "^3.13"
},
"suggest": {
"ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.",
- "ext-ctype": "Enables faster processing of character classification using ctype functions.",
"ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.",
"ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.",
"paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter",
"ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type."
},
- "time": "2021-09-25T23:10:38+00:00",
+ "time": "2025-09-04T20:59:21+00:00",
"type": "library",
"extra": {
"captainhook": {
"force-install": true
- },
- "branch-alias": {
- "dev-main": "4.x-dev"
}
},
"installation-source": "dist",
@@ -1318,18 +1277,8 @@
],
"support": {
"issues": "https://github.com/ramsey/uuid/issues",
- "source": "https://github.com/ramsey/uuid/tree/4.2.3"
+ "source": "https://github.com/ramsey/uuid/tree/4.9.1"
},
- "funding": [
- {
- "url": "https://github.com/ramsey",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/ramsey/uuid",
- "type": "tidelift"
- }
- ],
"install-path": "../ramsey/uuid"
},
{
@@ -1545,30 +1494,24 @@
"install-path": "../simshaun/recurr"
},
{
- "name": "symfony/polyfill-ctype",
+ "name": "symfony/polyfill-php84",
"version": "v1.33.0",
"version_normalized": "1.33.0.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/polyfill-ctype.git",
- "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638"
+ "url": "https://github.com/symfony/polyfill-php84.git",
+ "reference": "d8ced4d875142b6a7426000426b8abc631d6b191"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638",
- "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638",
+ "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191",
+ "reference": "d8ced4d875142b6a7426000426b8abc631d6b191",
"shasum": ""
},
"require": {
"php": ">=7.2"
},
- "provide": {
- "ext-ctype": "*"
- },
- "suggest": {
- "ext-ctype": "For best performance"
- },
- "time": "2024-09-09T11:45:10+00:00",
+ "time": "2025-06-24T13:30:11+00:00",
"type": "library",
"extra": {
"thanks": {
@@ -1582,87 +1525,7 @@
"bootstrap.php"
],
"psr-4": {
- "Symfony\\Polyfill\\Ctype\\": ""
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Gert de Pagter",
- "email": "BackEndTea@gmail.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Symfony polyfill for ctype functions",
- "homepage": "https://symfony.com",
- "keywords": [
- "compatibility",
- "ctype",
- "polyfill",
- "portable"
- ],
- "support": {
- "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0"
- },
- "funding": [
- {
- "url": "https://symfony.com/sponsor",
- "type": "custom"
- },
- {
- "url": "https://github.com/fabpot",
- "type": "github"
- },
- {
- "url": "https://github.com/nicolas-grekas",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
- "type": "tidelift"
- }
- ],
- "install-path": "../symfony/polyfill-ctype"
- },
- {
- "name": "symfony/polyfill-php80",
- "version": "v1.33.0",
- "version_normalized": "1.33.0.0",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/polyfill-php80.git",
- "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608",
- "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608",
- "shasum": ""
- },
- "require": {
- "php": ">=7.2"
- },
- "time": "2025-01-02T08:10:11+00:00",
- "type": "library",
- "extra": {
- "thanks": {
- "url": "https://github.com/symfony/polyfill",
- "name": "symfony/polyfill"
- }
- },
- "installation-source": "dist",
- "autoload": {
- "files": [
- "bootstrap.php"
- ],
- "psr-4": {
- "Symfony\\Polyfill\\Php80\\": ""
+ "Symfony\\Polyfill\\Php84\\": ""
},
"classmap": [
"Resources/stubs"
@@ -1673,10 +1536,6 @@
"MIT"
],
"authors": [
- {
- "name": "Ion Bazan",
- "email": "ion.bazan@gmail.com"
- },
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
@@ -1686,7 +1545,7 @@
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
+ "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
@@ -1695,7 +1554,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0"
+ "source": "https://github.com/symfony/polyfill-php84/tree/v1.33.0"
},
"funding": [
{
@@ -1715,68 +1574,7 @@
"type": "tidelift"
}
],
- "install-path": "../symfony/polyfill-php80"
- },
- {
- "name": "webmozart/assert",
- "version": "1.11.0",
- "version_normalized": "1.11.0.0",
- "source": {
- "type": "git",
- "url": "https://github.com/webmozarts/assert.git",
- "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991",
- "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991",
- "shasum": ""
- },
- "require": {
- "ext-ctype": "*",
- "php": "^7.2 || ^8.0"
- },
- "conflict": {
- "phpstan/phpstan": "<0.12.20",
- "vimeo/psalm": "<4.6.1 || 4.6.2"
- },
- "require-dev": {
- "phpunit/phpunit": "^8.5.13"
- },
- "time": "2022-06-03T18:03:27+00:00",
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.10-dev"
- }
- },
- "installation-source": "dist",
- "autoload": {
- "psr-4": {
- "Webmozart\\Assert\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Bernhard Schussek",
- "email": "bschussek@gmail.com"
- }
- ],
- "description": "Assertions to validate method input/output with nice error messages.",
- "keywords": [
- "assert",
- "check",
- "validate"
- ],
- "support": {
- "issues": "https://github.com/webmozarts/assert/issues",
- "source": "https://github.com/webmozarts/assert/tree/1.11.0"
- },
- "install-path": "../webmozart/assert"
+ "install-path": "../symfony/polyfill-php84"
},
{
"name": "wikimedia/less.php",
diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php
index 4d20577..5c31b1a 100644
--- a/vendor/composer/installed.php
+++ b/vendor/composer/installed.php
@@ -3,7 +3,7 @@
'name' => 'icinga/icinga-php-library',
'pretty_version' => 'dev-main',
'version' => 'dev-main',
- 'reference' => 'a7944e40e1b1c5f88dcb04c253e07001cb9ddb4b',
+ 'reference' => 'e15e7dee90f02adb3ae82280bfc3a803b09f12f5',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@@ -11,27 +11,18 @@
),
'versions' => array(
'brick/math' => array(
- 'pretty_version' => '0.9.3',
- 'version' => '0.9.3.0',
- 'reference' => 'ca57d18f028f84f777b2168cd1911b0dee2343ae',
+ 'pretty_version' => '0.14.0',
+ 'version' => '0.14.0.0',
+ 'reference' => '113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2',
'type' => 'library',
'install_path' => __DIR__ . '/../brick/math',
'aliases' => array(),
'dev_requirement' => false,
),
- 'cweagans/composer-patches' => array(
- 'pretty_version' => '1.7.3',
- 'version' => '1.7.3.0',
- 'reference' => 'e190d4466fe2b103a55467dfa83fc2fecfcaf2db',
- 'type' => 'composer-plugin',
- 'install_path' => __DIR__ . '/../cweagans/composer-patches',
- 'aliases' => array(),
- 'dev_requirement' => false,
- ),
'doctrine/collections' => array(
- 'pretty_version' => '1.8.0',
- 'version' => '1.8.0.0',
- 'reference' => '2b44dd4cbca8b5744327de78bafef5945c7e7b5e',
+ 'pretty_version' => '2.4.0',
+ 'version' => '2.4.0.0',
+ 'reference' => '9acfeea2e8666536edff3d77c531261c63680160',
'type' => 'library',
'install_path' => __DIR__ . '/../doctrine/collections',
'aliases' => array(),
@@ -47,9 +38,9 @@
'dev_requirement' => false,
),
'dragonmantank/cron-expression' => array(
- 'pretty_version' => 'v3.4.0',
- 'version' => '3.4.0.0',
- 'reference' => '8c784d071debd117328803d86b2097615b457500',
+ 'pretty_version' => 'v3.6.0',
+ 'version' => '3.6.0.0',
+ 'reference' => 'd61a8a9604ec1f8c3d150d09db6ce98b32675013',
'type' => 'library',
'install_path' => __DIR__ . '/../dragonmantank/cron-expression',
'aliases' => array(),
@@ -85,82 +76,106 @@
'icinga/icinga-php-library' => array(
'pretty_version' => 'dev-main',
'version' => 'dev-main',
- 'reference' => 'a7944e40e1b1c5f88dcb04c253e07001cb9ddb4b',
+ 'reference' => 'e15e7dee90f02adb3ae82280bfc3a803b09f12f5',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'dev_requirement' => false,
),
'ipl/html' => array(
- 'pretty_version' => 'v0.8.2',
- 'version' => '0.8.2.0',
- 'reference' => 'e18bdf11abca5e477100e2c7d190ef5f424d0d98',
+ 'pretty_version' => 'dev-main',
+ 'version' => 'dev-main',
+ 'reference' => '9354c29faf807e67c4a0a365b450b7f0b64598ad',
'type' => 'library',
'install_path' => __DIR__ . '/../ipl/html',
- 'aliases' => array(),
+ 'aliases' => array(
+ 0 => '99.x-dev',
+ 1 => '9999999-dev',
+ ),
'dev_requirement' => false,
),
'ipl/i18n' => array(
- 'pretty_version' => 'v0.2.2',
- 'version' => '0.2.2.0',
- 'reference' => 'a2b6109c5a93f86ce46d5dc351dbe75e8502cf8c',
+ 'pretty_version' => 'dev-main',
+ 'version' => 'dev-main',
+ 'reference' => '692c33cf46fb8a4511da613dbf97c6216c345cc5',
'type' => 'library',
'install_path' => __DIR__ . '/../ipl/i18n',
- 'aliases' => array(),
+ 'aliases' => array(
+ 0 => '99.x-dev',
+ 1 => '9999999-dev',
+ ),
'dev_requirement' => false,
),
'ipl/orm' => array(
- 'pretty_version' => 'v0.6.3',
- 'version' => '0.6.3.0',
- 'reference' => 'a775a2745764a8dc7f28618cce69dcd7bbfd7915',
+ 'pretty_version' => 'dev-main',
+ 'version' => 'dev-main',
+ 'reference' => 'dbcb2da01c168a02fe264e075e1c02c7233851df',
'type' => 'library',
'install_path' => __DIR__ . '/../ipl/orm',
- 'aliases' => array(),
+ 'aliases' => array(
+ 0 => '99.x-dev',
+ 1 => '9999999-dev',
+ ),
'dev_requirement' => false,
),
'ipl/scheduler' => array(
- 'pretty_version' => 'v0.1.2',
- 'version' => '0.1.2.0',
- 'reference' => '6119afdea07b1390bd728e350e0d80b26ec8d6ba',
+ 'pretty_version' => 'dev-main',
+ 'version' => 'dev-main',
+ 'reference' => 'd15143b2db2623b42bd25a013a73800dae2c6459',
'type' => 'library',
'install_path' => __DIR__ . '/../ipl/scheduler',
- 'aliases' => array(),
+ 'aliases' => array(
+ 0 => '99.x-dev',
+ 1 => '9999999-dev',
+ ),
'dev_requirement' => false,
),
'ipl/sql' => array(
- 'pretty_version' => 'v0.7.1',
- 'version' => '0.7.1.0',
- 'reference' => 'e80f1b712c4b96099b0bf9096e6efe317a165e3b',
+ 'pretty_version' => 'dev-main',
+ 'version' => 'dev-main',
+ 'reference' => '6f4258c4e3b20655db57d248e26edf7b54c04729',
'type' => 'library',
'install_path' => __DIR__ . '/../ipl/sql',
- 'aliases' => array(),
+ 'aliases' => array(
+ 0 => '99.x-dev',
+ 1 => '9999999-dev',
+ ),
'dev_requirement' => false,
),
'ipl/stdlib' => array(
- 'pretty_version' => 'v0.14.0',
- 'version' => '0.14.0.0',
- 'reference' => 'bf5fc8f40b86bd90337db6f3be389be2a93fa64a',
+ 'pretty_version' => 'dev-main',
+ 'version' => 'dev-main',
+ 'reference' => '9b7a903fbfc341da59f242149ac333594e4a6fa3',
'type' => 'library',
'install_path' => __DIR__ . '/../ipl/stdlib',
- 'aliases' => array(),
+ 'aliases' => array(
+ 0 => '99.x-dev',
+ 1 => '9999999-dev',
+ ),
'dev_requirement' => false,
),
'ipl/validator' => array(
- 'pretty_version' => 'v0.5.0',
- 'version' => '0.5.0.0',
- 'reference' => 'a601fae0ed330e63cea50e4a2a6659ca1ad97bde',
+ 'pretty_version' => 'dev-main',
+ 'version' => 'dev-main',
+ 'reference' => 'eac5c6c114d8007db5c24ae159fe6f55e89a946b',
'type' => 'library',
'install_path' => __DIR__ . '/../ipl/validator',
- 'aliases' => array(),
+ 'aliases' => array(
+ 0 => '99.x-dev',
+ 1 => '9999999-dev',
+ ),
'dev_requirement' => false,
),
'ipl/web' => array(
- 'pretty_version' => 'v0.10.2',
- 'version' => '0.10.2.0',
- 'reference' => 'a3d134c0d67aa51a9b186519c76e718603fda835',
+ 'pretty_version' => 'dev-main',
+ 'version' => 'dev-main',
+ 'reference' => '3e8867cbdde8af9724f64b84830503f8fcbd90e8',
'type' => 'library',
'install_path' => __DIR__ . '/../ipl/web',
- 'aliases' => array(),
+ 'aliases' => array(
+ 0 => '99.x-dev',
+ 1 => '9999999-dev',
+ ),
'dev_requirement' => false,
),
'mtdowling/cron-expression' => array(
@@ -218,18 +233,18 @@
'dev_requirement' => false,
),
'ramsey/collection' => array(
- 'pretty_version' => '1.1.4',
- 'version' => '1.1.4.0',
- 'reference' => 'ab2237657ad99667a5143e32ba2683c8029563d4',
+ 'pretty_version' => '2.1.1',
+ 'version' => '2.1.1.0',
+ 'reference' => '344572933ad0181accbf4ba763e85a0306a8c5e2',
'type' => 'library',
'install_path' => __DIR__ . '/../ramsey/collection',
'aliases' => array(),
'dev_requirement' => false,
),
'ramsey/uuid' => array(
- 'pretty_version' => '4.2.3',
- 'version' => '4.2.3.0',
- 'reference' => 'fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df',
+ 'pretty_version' => '4.9.1',
+ 'version' => '4.9.1.0',
+ 'reference' => '81f941f6f729b1e3ceea61d9d014f8b6c6800440',
'type' => 'library',
'install_path' => __DIR__ . '/../ramsey/uuid',
'aliases' => array(),
@@ -256,7 +271,7 @@
'rhumsaa/uuid' => array(
'dev_requirement' => false,
'replaced' => array(
- 0 => '4.2.3',
+ 0 => '4.9.1',
),
),
'simshaun/recurr' => array(
@@ -268,30 +283,12 @@
'aliases' => array(),
'dev_requirement' => false,
),
- 'symfony/polyfill-ctype' => array(
+ 'symfony/polyfill-php84' => array(
'pretty_version' => 'v1.33.0',
'version' => '1.33.0.0',
- 'reference' => 'a3cc8b044a6ea513310cbd48ef7333b384945638',
+ 'reference' => 'd8ced4d875142b6a7426000426b8abc631d6b191',
'type' => 'library',
- 'install_path' => __DIR__ . '/../symfony/polyfill-ctype',
- 'aliases' => array(),
- 'dev_requirement' => false,
- ),
- 'symfony/polyfill-php80' => array(
- 'pretty_version' => 'v1.33.0',
- 'version' => '1.33.0.0',
- 'reference' => '0cc9dd0f17f61d8131e7df6b84bd344899fe2608',
- 'type' => 'library',
- 'install_path' => __DIR__ . '/../symfony/polyfill-php80',
- 'aliases' => array(),
- 'dev_requirement' => false,
- ),
- 'webmozart/assert' => array(
- 'pretty_version' => '1.11.0',
- 'version' => '1.11.0.0',
- 'reference' => '11cb2199493b2f8a3b53e7f19068fc6aac760991',
- 'type' => 'library',
- 'install_path' => __DIR__ . '/../webmozart/assert',
+ 'install_path' => __DIR__ . '/../symfony/polyfill-php84',
'aliases' => array(),
'dev_requirement' => false,
),
diff --git a/vendor/composer/platform_check.php b/vendor/composer/platform_check.php
index 5da86a6..14bf88d 100644
--- a/vendor/composer/platform_check.php
+++ b/vendor/composer/platform_check.php
@@ -4,8 +4,8 @@
$issues = array();
-if (!(PHP_VERSION_ID >= 70209)) {
- $issues[] = 'Your Composer dependencies require a PHP version ">= 7.2.9". You are running ' . PHP_VERSION . '.';
+if (!(PHP_VERSION_ID >= 80200)) {
+ $issues[] = 'Your Composer dependencies require a PHP version ">= 8.2.0". You are running ' . PHP_VERSION . '.';
}
if ($issues) {
@@ -19,8 +19,7 @@ if ($issues) {
echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
}
}
- trigger_error(
- 'Composer detected issues in your platform: ' . implode(' ', $issues),
- E_USER_ERROR
+ throw new \RuntimeException(
+ 'Composer detected issues in your platform: ' . implode(' ', $issues)
);
}
diff --git a/vendor/cweagans/composer-patches/composer.json b/vendor/cweagans/composer-patches/composer.json
deleted file mode 100644
index 1565b02..0000000
--- a/vendor/cweagans/composer-patches/composer.json
+++ /dev/null
@@ -1,30 +0,0 @@
-{
- "name": "cweagans/composer-patches",
- "description": "Provides a way to patch Composer packages.",
- "minimum-stability": "dev",
- "license": "BSD-3-Clause",
- "type": "composer-plugin",
- "extra": {
- "class": "cweagans\\Composer\\Patches"
- },
- "authors": [
- {
- "name": "Cameron Eagans",
- "email": "me@cweagans.net"
- }
- ],
- "require": {
- "php": ">=5.3.0",
- "composer-plugin-api": "^1.0 || ^2.0"
- },
- "require-dev": {
- "composer/composer": "~1.0 || ~2.0",
- "phpunit/phpunit": "~4.6"
- },
- "autoload": {
- "psr-4": {"cweagans\\Composer\\": "src"}
- },
- "autoload-dev": {
- "psr-4": {"cweagans\\Composer\\Tests\\": "tests"}
- }
-}
diff --git a/vendor/cweagans/composer-patches/src/PatchEvent.php b/vendor/cweagans/composer-patches/src/PatchEvent.php
deleted file mode 100644
index 31d36f8..0000000
--- a/vendor/cweagans/composer-patches/src/PatchEvent.php
+++ /dev/null
@@ -1,70 +0,0 @@
-package = $package;
- $this->url = $url;
- $this->description = $description;
- }
-
- /**
- * Returns the package that is patched.
- *
- * @return PackageInterface
- */
- public function getPackage() {
- return $this->package;
- }
-
- /**
- * Returns the url of the patch.
- *
- * @return string
- */
- public function getUrl() {
- return $this->url;
- }
-
- /**
- * Returns the description of the patch.
- *
- * @return string
- */
- public function getDescription() {
- return $this->description;
- }
-
-}
diff --git a/vendor/cweagans/composer-patches/src/PatchEvents.php b/vendor/cweagans/composer-patches/src/PatchEvents.php
deleted file mode 100644
index ecee947..0000000
--- a/vendor/cweagans/composer-patches/src/PatchEvents.php
+++ /dev/null
@@ -1,30 +0,0 @@
-composer = $composer;
- $this->io = $io;
- $this->eventDispatcher = $composer->getEventDispatcher();
- $this->executor = new ProcessExecutor($this->io);
- $this->patches = array();
- $this->installedPatches = array();
- }
-
- /**
- * Returns an array of event names this subscriber wants to listen to.
- */
- public static function getSubscribedEvents() {
- return array(
- ScriptEvents::PRE_INSTALL_CMD => array('checkPatches'),
- ScriptEvents::PRE_UPDATE_CMD => array('checkPatches'),
- PackageEvents::PRE_PACKAGE_INSTALL => array('gatherPatches'),
- PackageEvents::PRE_PACKAGE_UPDATE => array('gatherPatches'),
- // The following is a higher weight for compatibility with
- // https://github.com/AydinHassan/magento-core-composer-installer and more generally for compatibility with
- // every Composer plugin which deploys downloaded packages to other locations.
- // In such cases you want that those plugins deploy patched files so they have to run after
- // the "composer-patches" plugin.
- // @see: https://github.com/cweagans/composer-patches/pull/153
- PackageEvents::POST_PACKAGE_INSTALL => array('postInstall', 10),
- PackageEvents::POST_PACKAGE_UPDATE => array('postInstall', 10),
- );
- }
-
- /**
- * Before running composer install,
- * @param Event $event
- */
- public function checkPatches(Event $event) {
- if (!$this->isPatchingEnabled()) {
- return;
- }
-
- try {
- $repositoryManager = $this->composer->getRepositoryManager();
- $localRepository = $repositoryManager->getLocalRepository();
- $installationManager = $this->composer->getInstallationManager();
- $packages = $localRepository->getPackages();
-
- $extra = $this->composer->getPackage()->getExtra();
- $patches_ignore = isset($extra['patches-ignore']) ? $extra['patches-ignore'] : array();
-
- $tmp_patches = $this->grabPatches();
- foreach ($packages as $package) {
- $extra = $package->getExtra();
- if (isset($extra['patches'])) {
- if (isset($patches_ignore[$package->getName()])) {
- foreach ($patches_ignore[$package->getName()] as $package_name => $patches) {
- if (isset($extra['patches'][$package_name])) {
- $extra['patches'][$package_name] = array_diff($extra['patches'][$package_name], $patches);
- }
- }
- }
- $this->installedPatches[$package->getName()] = $extra['patches'];
- }
- $patches = isset($extra['patches']) ? $extra['patches'] : array();
- $tmp_patches = $this->arrayMergeRecursiveDistinct($tmp_patches, $patches);
- }
-
- if ($tmp_patches == FALSE) {
- $this->io->write('No patches supplied.');
- return;
- }
-
- // Remove packages for which the patch set has changed.
- $promises = array();
- foreach ($packages as $package) {
- if (!($package instanceof AliasPackage)) {
- $package_name = $package->getName();
- $extra = $package->getExtra();
- $has_patches = isset($tmp_patches[$package_name]);
- $has_applied_patches = isset($extra['patches_applied']) && count($extra['patches_applied']) > 0;
- if (($has_patches && !$has_applied_patches)
- || (!$has_patches && $has_applied_patches)
- || ($has_patches && $has_applied_patches && $tmp_patches[$package_name] !== $extra['patches_applied'])) {
- $uninstallOperation = new UninstallOperation($package, 'Removing package so it can be re-installed and re-patched.');
- $this->io->write('Removing package ' . $package_name . ' so that it can be re-installed and re-patched.');
- $promises[] = $installationManager->uninstall($localRepository, $uninstallOperation);
- }
- }
- }
- $promises = array_filter($promises);
- if ($promises) {
- $this->composer->getLoop()->wait($promises);
- }
- }
- // If the Locker isn't available, then we don't need to do this.
- // It's the first time packages have been installed.
- catch (\LogicException $e) {
- return;
- }
- }
-
- /**
- * Gather patches from dependencies and store them for later use.
- *
- * @param PackageEvent $event
- */
- public function gatherPatches(PackageEvent $event) {
- // If we've already done this, then don't do it again.
- if (isset($this->patches['_patchesGathered'])) {
- $this->io->write('Patches already gathered. Skipping', TRUE, IOInterface::VERBOSE);
- return;
- }
- // If patching has been disabled, bail out here.
- elseif (!$this->isPatchingEnabled()) {
- $this->io->write('Patching is disabled. Skipping.', TRUE, IOInterface::VERBOSE);
- return;
- }
-
- $this->patches = $this->grabPatches();
- if (empty($this->patches)) {
- $this->io->write('No patches supplied.');
- }
-
- $extra = $this->composer->getPackage()->getExtra();
- $patches_ignore = isset($extra['patches-ignore']) ? $extra['patches-ignore'] : array();
-
- // Now add all the patches from dependencies that will be installed.
- $operations = $event->getOperations();
- $this->io->write('Gathering patches for dependencies. This might take a minute.');
- foreach ($operations as $operation) {
- if ($operation instanceof InstallOperation || $operation instanceof UpdateOperation) {
- $package = $this->getPackageFromOperation($operation);
- $extra = $package->getExtra();
- if (isset($extra['patches'])) {
- if (isset($patches_ignore[$package->getName()])) {
- foreach ($patches_ignore[$package->getName()] as $package_name => $patches) {
- if (isset($extra['patches'][$package_name])) {
- $extra['patches'][$package_name] = array_diff($extra['patches'][$package_name], $patches);
- }
- }
- }
- $this->patches = $this->arrayMergeRecursiveDistinct($this->patches, $extra['patches']);
- }
- // Unset installed patches for this package
- if(isset($this->installedPatches[$package->getName()])) {
- unset($this->installedPatches[$package->getName()]);
- }
- }
- }
-
- // Merge installed patches from dependencies that did not receive an update.
- foreach ($this->installedPatches as $patches) {
- $this->patches = $this->arrayMergeRecursiveDistinct($this->patches, $patches);
- }
-
- // If we're in verbose mode, list the projects we're going to patch.
- if ($this->io->isVerbose()) {
- foreach ($this->patches as $package => $patches) {
- $number = count($patches);
- $this->io->write('Found ' . $number . ' patches for ' . $package . '.');
- }
- }
-
- // Make sure we don't gather patches again. Extra keys in $this->patches
- // won't hurt anything, so we'll just stash it there.
- $this->patches['_patchesGathered'] = TRUE;
- }
-
- /**
- * Get the patches from root composer or external file
- * @return Patches
- * @throws \Exception
- */
- public function grabPatches() {
- // First, try to get the patches from the root composer.json.
- $extra = $this->composer->getPackage()->getExtra();
- if (isset($extra['patches'])) {
- $this->io->write('Gathering patches for root package.');
- $patches = $extra['patches'];
- return $patches;
- }
- // If it's not specified there, look for a patches-file definition.
- elseif (isset($extra['patches-file'])) {
- $this->io->write('Gathering patches from patch file.');
- $patches = file_get_contents($extra['patches-file']);
- $patches = json_decode($patches, TRUE);
- $error = json_last_error();
- if ($error != 0) {
- switch ($error) {
- case JSON_ERROR_DEPTH:
- $msg = ' - Maximum stack depth exceeded';
- break;
- case JSON_ERROR_STATE_MISMATCH:
- $msg = ' - Underflow or the modes mismatch';
- break;
- case JSON_ERROR_CTRL_CHAR:
- $msg = ' - Unexpected control character found';
- break;
- case JSON_ERROR_SYNTAX:
- $msg = ' - Syntax error, malformed JSON';
- break;
- case JSON_ERROR_UTF8:
- $msg = ' - Malformed UTF-8 characters, possibly incorrectly encoded';
- break;
- default:
- $msg = ' - Unknown error';
- break;
- }
- throw new \Exception('There was an error in the supplied patches file:' . $msg);
- }
- if (isset($patches['patches'])) {
- $patches = $patches['patches'];
- return $patches;
- }
- elseif(!$patches) {
- throw new \Exception('There was an error in the supplied patch file');
- }
- }
- else {
- return array();
- }
- }
-
- /**
- * @param PackageEvent $event
- * @throws \Exception
- */
- public function postInstall(PackageEvent $event) {
-
- // Check if we should exit in failure.
- $extra = $this->composer->getPackage()->getExtra();
- $exitOnFailure = getenv('COMPOSER_EXIT_ON_PATCH_FAILURE') || !empty($extra['composer-exit-on-patch-failure']);
- $skipReporting = getenv('COMPOSER_PATCHES_SKIP_REPORTING') || !empty($extra['composer-patches-skip-reporting']);
-
- // Get the package object for the current operation.
- $operation = $event->getOperation();
- /** @var PackageInterface $package */
- $package = $this->getPackageFromOperation($operation);
- $package_name = $package->getName();
-
- if (!isset($this->patches[$package_name])) {
- if ($this->io->isVerbose()) {
- $this->io->write('No patches found for ' . $package_name . '.');
- }
- return;
- }
- $this->io->write(' - Applying patches for ' . $package_name . '');
-
- // Get the install path from the package object.
- $manager = $event->getComposer()->getInstallationManager();
- $install_path = $manager->getInstaller($package->getType())->getInstallPath($package);
-
- // Set up a downloader.
- $downloader = new RemoteFilesystem($this->io, $this->composer->getConfig());
-
- // Track applied patches in the package info in installed.json
- $localRepository = $this->composer->getRepositoryManager()->getLocalRepository();
- $localPackage = $localRepository->findPackage($package_name, $package->getVersion());
- $extra = $localPackage->getExtra();
- $extra['patches_applied'] = array();
-
- foreach ($this->patches[$package_name] as $description => $url) {
- $this->io->write(' ' . $url . ' (' . $description. ')');
- try {
- $this->eventDispatcher->dispatch(NULL, new PatchEvent(PatchEvents::PRE_PATCH_APPLY, $package, $url, $description));
- $this->getAndApplyPatch($downloader, $install_path, $url, $package);
- $this->eventDispatcher->dispatch(NULL, new PatchEvent(PatchEvents::POST_PATCH_APPLY, $package, $url, $description));
- $extra['patches_applied'][$description] = $url;
- }
- catch (\Exception $e) {
- $this->io->write(' Could not apply patch! Skipping. The error was: ' . $e->getMessage() . '');
- if ($exitOnFailure) {
- throw new \Exception("Cannot apply patch $description ($url)!");
- }
- }
- }
- $localPackage->setExtra($extra);
-
- $this->io->write('');
-
- if (true !== $skipReporting) {
- $this->writePatchReport($this->patches[$package_name], $install_path);
- }
- }
-
- /**
- * Get a Package object from an OperationInterface object.
- *
- * @param OperationInterface $operation
- * @return PackageInterface
- * @throws \Exception
- */
- protected function getPackageFromOperation(OperationInterface $operation) {
- if ($operation instanceof InstallOperation) {
- $package = $operation->getPackage();
- }
- elseif ($operation instanceof UpdateOperation) {
- $package = $operation->getTargetPackage();
- }
- else {
- throw new \Exception('Unknown operation: ' . get_class($operation));
- }
-
- return $package;
- }
-
- /**
- * Apply a patch on code in the specified directory.
- *
- * @param RemoteFilesystem $downloader
- * @param $install_path
- * @param $patch_url
- * @param PackageInterface $package
- * @throws \Exception
- */
- protected function getAndApplyPatch(RemoteFilesystem $downloader, $install_path, $patch_url, PackageInterface $package) {
-
- // Local patch file.
- if (file_exists($patch_url)) {
- $filename = realpath($patch_url);
- }
- else {
- // Generate random (but not cryptographically so) filename.
- $filename = uniqid(sys_get_temp_dir().'/') . ".patch";
-
- // Download file from remote filesystem to this location.
- $hostname = parse_url($patch_url, PHP_URL_HOST);
-
- try {
- $downloader->copy($hostname, $patch_url, $filename, false);
- } catch (\Exception $e) {
- // In case of an exception, retry once as the download might
- // have failed due to intermittent network issues.
- $downloader->copy($hostname, $patch_url, $filename, false);
- }
- }
-
- // The order here is intentional. p1 is most likely to apply with git apply.
- // p0 is next likely. p2 is extremely unlikely, but for some special cases,
- // it might be useful. p4 is useful for Magento 2 patches
- $patch_levels = array('-p1', '-p0', '-p2', '-p4');
-
- // Check for specified patch level for this package.
- $extra = $this->composer->getPackage()->getExtra();
- if (!empty($extra['patchLevel'][$package->getName()])){
- $patch_levels = array($extra['patchLevel'][$package->getName()]);
- }
- // Attempt to apply with git apply.
- $patched = $this->applyPatchWithGit($install_path, $patch_levels, $filename);
-
- // In some rare cases, git will fail to apply a patch, fallback to using
- // the 'patch' command.
- if (!$patched) {
- foreach ($patch_levels as $patch_level) {
- // --no-backup-if-mismatch here is a hack that fixes some
- // differences between how patch works on windows and unix.
- if ($patched = $this->executeCommand("patch %s --no-backup-if-mismatch -d %s < %s", $patch_level, $install_path, $filename)) {
- break;
- }
- }
- }
-
- // Clean up the temporary patch file.
- if (isset($hostname)) {
- unlink($filename);
- }
- // If the patch *still* isn't applied, then give up and throw an Exception.
- // Otherwise, let the user know it worked.
- if (!$patched) {
- throw new \Exception("Cannot apply patch $patch_url");
- }
- }
-
- /**
- * Checks if the root package enables patching.
- *
- * @return bool
- * Whether patching is enabled. Defaults to TRUE.
- */
- protected function isPatchingEnabled() {
- $extra = $this->composer->getPackage()->getExtra();
-
- if (empty($extra['patches']) && empty($extra['patches-ignore']) && !isset($extra['patches-file'])) {
- // The root package has no patches of its own, so only allow patching if
- // it has specifically opted in.
- return isset($extra['enable-patching']) ? $extra['enable-patching'] : FALSE;
- }
- else {
- return TRUE;
- }
- }
-
- /**
- * Writes a patch report to the target directory.
- *
- * @param array $patches
- * @param string $directory
- */
- protected function writePatchReport($patches, $directory) {
- $output = "This file was automatically generated by Composer Patches (https://github.com/cweagans/composer-patches)\n";
- $output .= "Patches applied to this directory:\n\n";
- foreach ($patches as $description => $url) {
- $output .= $description . "\n";
- $output .= 'Source: ' . $url . "\n\n\n";
- }
- file_put_contents($directory . "/PATCHES.txt", $output);
- }
-
- /**
- * Executes a shell command with escaping.
- *
- * @param string $cmd
- * @return bool
- */
- protected function executeCommand($cmd) {
- // Shell-escape all arguments except the command.
- $args = func_get_args();
- foreach ($args as $index => $arg) {
- if ($index !== 0) {
- $args[$index] = escapeshellarg($arg);
- }
- }
-
- // And replace the arguments.
- $command = call_user_func_array('sprintf', $args);
- $output = '';
- if ($this->io->isVerbose()) {
- $this->io->write('' . $command . '');
- $io = $this->io;
- $output = function ($type, $data) use ($io) {
- if ($type == Process::ERR) {
- $io->write('' . $data . '');
- }
- else {
- $io->write('' . $data . '');
- }
- };
- }
- return ($this->executor->execute($command, $output) == 0);
- }
-
- /**
- * Recursively merge arrays without changing data types of values.
- *
- * Does not change the data types of the values in the arrays. Matching keys'
- * values in the second array overwrite those in the first array, as is the
- * case with array_merge.
- *
- * @param array $array1
- * The first array.
- * @param array $array2
- * The second array.
- * @return array
- * The merged array.
- *
- * @see http://php.net/manual/en/function.array-merge-recursive.php#92195
- */
- protected function arrayMergeRecursiveDistinct(array $array1, array $array2) {
- $merged = $array1;
-
- foreach ($array2 as $key => &$value) {
- if (is_array($value) && isset($merged[$key]) && is_array($merged[$key])) {
- $merged[$key] = $this->arrayMergeRecursiveDistinct($merged[$key], $value);
- }
- else {
- $merged[$key] = $value;
- }
- }
-
- return $merged;
- }
-
- /**
- * Attempts to apply a patch with git apply.
- *
- * @param $install_path
- * @param $patch_levels
- * @param $filename
- *
- * @return bool
- * TRUE if patch was applied, FALSE otherwise.
- */
- protected function applyPatchWithGit($install_path, $patch_levels, $filename) {
- // Do not use git apply unless the install path is itself a git repo
- // @see https://stackoverflow.com/a/27283285
- if (!is_dir($install_path . '/.git')) {
- return FALSE;
- }
-
- $patched = FALSE;
- foreach ($patch_levels as $patch_level) {
- if ($this->io->isVerbose()) {
- $comment = 'Testing ability to patch with git apply.';
- $comment .= ' This command may produce errors that can be safely ignored.';
- $this->io->write('' . $comment . '');
- }
- $checked = $this->executeCommand('git -C %s apply --check -v %s %s', $install_path, $patch_level, $filename);
- $output = $this->executor->getErrorOutput();
- if (substr($output, 0, 7) == 'Skipped') {
- // Git will indicate success but silently skip patches in some scenarios.
- //
- // @see https://github.com/cweagans/composer-patches/pull/165
- $checked = FALSE;
- }
- if ($checked) {
- // Apply the first successful style.
- $patched = $this->executeCommand('git -C %s apply %s %s', $install_path, $patch_level, $filename);
- break;
- }
- }
- return $patched;
- }
-
- /**
- * Indicates if a package has been patched.
- *
- * @param \Composer\Package\PackageInterface $package
- * The package to check.
- *
- * @return bool
- * TRUE if the package has been patched.
- */
- public static function isPackagePatched(PackageInterface $package) {
- return array_key_exists('patches_applied', $package->getExtra());
- }
-
- /**
- * {@inheritDoc}
- */
- public function deactivate(Composer $composer, IOInterface $io)
- {
- }
-
- /**
- * {@inheritDoc}
- */
- public function uninstall(Composer $composer, IOInterface $io)
- {
- }
-
-}
diff --git a/vendor/doctrine/collections/.doctrine-project.json b/vendor/doctrine/collections/.doctrine-project.json
deleted file mode 100644
index 9c89e50..0000000
--- a/vendor/doctrine/collections/.doctrine-project.json
+++ /dev/null
@@ -1,32 +0,0 @@
-{
- "active": true,
- "name": "Collections",
- "slug": "collections",
- "docsSlug": "doctrine-collections",
- "versions": [
- {
- "name": "2.0",
- "branchName": "2.0.x",
- "slug": "latest",
- "upcoming": true
- },
- {
- "name": "1.8",
- "branchName": "1.8.x",
- "slug": "1.8",
- "upcoming": true
- },
- {
- "name": "1.7",
- "branchName": "1.7.x",
- "slug": "1.7",
- "current": true
- },
- {
- "name": "1.6",
- "branchName": "1.6.x",
- "slug": "1.6",
- "maintained": false
- }
- ]
-}
diff --git a/vendor/doctrine/collections/composer.json b/vendor/doctrine/collections/composer.json
index d9422dd..c408731 100644
--- a/vendor/doctrine/collections/composer.json
+++ b/vendor/doctrine/collections/composer.json
@@ -33,23 +33,25 @@
],
"homepage": "https://www.doctrine-project.org/projects/collections.html",
"require": {
- "php": "^7.1.3 || ^8.0",
- "doctrine/deprecations": "^0.5.3 || ^1"
+ "php": "^8.1",
+ "doctrine/deprecations": "^1",
+ "symfony/polyfill-php84": "^1.30"
},
"require-dev": {
- "doctrine/coding-standard": "^9.0 || ^10.0",
- "phpstan/phpstan": "^1.4.8",
- "phpunit/phpunit": "^7.5 || ^8.5 || ^9.1.5",
- "vimeo/psalm": "^4.22"
+ "ext-json": "*",
+ "doctrine/coding-standard": "^14",
+ "phpstan/phpstan": "^2.1.30",
+ "phpstan/phpstan-phpunit": "^2.0.7",
+ "phpunit/phpunit": "^10.5.58 || ^11.5.42 || ^12.4"
},
"autoload": {
"psr-4": {
- "Doctrine\\Common\\Collections\\": "lib/Doctrine/Common/Collections"
+ "Doctrine\\Common\\Collections\\": "src"
}
},
"autoload-dev": {
"psr-4": {
- "Doctrine\\Tests\\": "tests/Doctrine/Tests"
+ "Doctrine\\Tests\\Common\\Collections\\": "tests"
}
},
"config": {
diff --git a/vendor/doctrine/collections/docs/composer.json b/vendor/doctrine/collections/docs/composer.json
new file mode 100644
index 0000000..c5a4e14
--- /dev/null
+++ b/vendor/doctrine/collections/docs/composer.json
@@ -0,0 +1,5 @@
+{
+ "require": {
+ "doctrine/docs-builder": "^1.0"
+ }
+}
diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/ClosureExpressionVisitor.php b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/ClosureExpressionVisitor.php
deleted file mode 100644
index c10b8d5..0000000
--- a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/ClosureExpressionVisitor.php
+++ /dev/null
@@ -1,269 +0,0 @@
-$accessor();
- }
- }
-
- if (preg_match('/^is[A-Z]+/', $field) === 1 && method_exists($object, $field)) {
- return $object->$field();
- }
-
- // __call should be triggered for get.
- $accessor = $accessors[0] . $field;
-
- if (method_exists($object, '__call')) {
- return $object->$accessor();
- }
-
- if ($object instanceof ArrayAccess) {
- return $object[$field];
- }
-
- if (isset($object->$field)) {
- return $object->$field;
- }
-
- // camelcase field name to support different variable naming conventions
- $ccField = preg_replace_callback('/_(.?)/', static function ($matches) {
- return strtoupper($matches[1]);
- }, $field);
-
- foreach ($accessors as $accessor) {
- $accessor .= $ccField;
-
- if (method_exists($object, $accessor)) {
- return $object->$accessor();
- }
- }
-
- return $object->$field;
- }
-
- /**
- * Helper for sorting arrays of objects based on multiple fields + orientations.
- *
- * @param string $name
- * @param int $orientation
- *
- * @return Closure
- */
- public static function sortByField($name, $orientation = 1, ?Closure $next = null)
- {
- if (! $next) {
- $next = static function (): int {
- return 0;
- };
- }
-
- return static function ($a, $b) use ($name, $next, $orientation): int {
- $aValue = ClosureExpressionVisitor::getObjectFieldValue($a, $name);
-
- $bValue = ClosureExpressionVisitor::getObjectFieldValue($b, $name);
-
- if ($aValue === $bValue) {
- return $next($a, $b);
- }
-
- return ($aValue > $bValue ? 1 : -1) * $orientation;
- };
- }
-
- /**
- * {@inheritDoc}
- */
- public function walkComparison(Comparison $comparison)
- {
- $field = $comparison->getField();
- $value = $comparison->getValue()->getValue(); // shortcut for walkValue()
-
- switch ($comparison->getOperator()) {
- case Comparison::EQ:
- return static function ($object) use ($field, $value): bool {
- return ClosureExpressionVisitor::getObjectFieldValue($object, $field) === $value;
- };
-
- case Comparison::NEQ:
- return static function ($object) use ($field, $value): bool {
- return ClosureExpressionVisitor::getObjectFieldValue($object, $field) !== $value;
- };
-
- case Comparison::LT:
- return static function ($object) use ($field, $value): bool {
- return ClosureExpressionVisitor::getObjectFieldValue($object, $field) < $value;
- };
-
- case Comparison::LTE:
- return static function ($object) use ($field, $value): bool {
- return ClosureExpressionVisitor::getObjectFieldValue($object, $field) <= $value;
- };
-
- case Comparison::GT:
- return static function ($object) use ($field, $value): bool {
- return ClosureExpressionVisitor::getObjectFieldValue($object, $field) > $value;
- };
-
- case Comparison::GTE:
- return static function ($object) use ($field, $value): bool {
- return ClosureExpressionVisitor::getObjectFieldValue($object, $field) >= $value;
- };
-
- case Comparison::IN:
- return static function ($object) use ($field, $value): bool {
- $fieldValue = ClosureExpressionVisitor::getObjectFieldValue($object, $field);
-
- return in_array($fieldValue, $value, is_scalar($fieldValue));
- };
-
- case Comparison::NIN:
- return static function ($object) use ($field, $value): bool {
- $fieldValue = ClosureExpressionVisitor::getObjectFieldValue($object, $field);
-
- return ! in_array($fieldValue, $value, is_scalar($fieldValue));
- };
-
- case Comparison::CONTAINS:
- return static function ($object) use ($field, $value) {
- return strpos(ClosureExpressionVisitor::getObjectFieldValue($object, $field), $value) !== false;
- };
-
- case Comparison::MEMBER_OF:
- return static function ($object) use ($field, $value): bool {
- $fieldValues = ClosureExpressionVisitor::getObjectFieldValue($object, $field);
-
- if (! is_array($fieldValues)) {
- $fieldValues = iterator_to_array($fieldValues);
- }
-
- return in_array($value, $fieldValues, true);
- };
-
- case Comparison::STARTS_WITH:
- return static function ($object) use ($field, $value): bool {
- return strpos(ClosureExpressionVisitor::getObjectFieldValue($object, $field), $value) === 0;
- };
-
- case Comparison::ENDS_WITH:
- return static function ($object) use ($field, $value): bool {
- return $value === substr(ClosureExpressionVisitor::getObjectFieldValue($object, $field), -strlen($value));
- };
-
- default:
- throw new RuntimeException('Unknown comparison operator: ' . $comparison->getOperator());
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public function walkValue(Value $value)
- {
- return $value->getValue();
- }
-
- /**
- * {@inheritDoc}
- */
- public function walkCompositeExpression(CompositeExpression $expr)
- {
- $expressionList = [];
-
- foreach ($expr->getExpressionList() as $child) {
- $expressionList[] = $this->dispatch($child);
- }
-
- switch ($expr->getType()) {
- case CompositeExpression::TYPE_AND:
- return $this->andExpressions($expressionList);
-
- case CompositeExpression::TYPE_OR:
- return $this->orExpressions($expressionList);
-
- default:
- throw new RuntimeException('Unknown composite ' . $expr->getType());
- }
- }
-
- /** @param callable[] $expressions */
- private function andExpressions(array $expressions): callable
- {
- return static function ($object) use ($expressions): bool {
- foreach ($expressions as $expression) {
- if (! $expression($object)) {
- return false;
- }
- }
-
- return true;
- };
- }
-
- /** @param callable[] $expressions */
- private function orExpressions(array $expressions): callable
- {
- return static function ($object) use ($expressions): bool {
- foreach ($expressions as $expression) {
- if ($expression($object)) {
- return true;
- }
- }
-
- return false;
- };
- }
-}
diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Comparison.php b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Comparison.php
deleted file mode 100644
index 6762b8b..0000000
--- a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Comparison.php
+++ /dev/null
@@ -1,74 +0,0 @@
-';
- public const LT = '<';
- public const LTE = '<=';
- public const GT = '>';
- public const GTE = '>=';
- public const IS = '='; // no difference with EQ
- public const IN = 'IN';
- public const NIN = 'NIN';
- public const CONTAINS = 'CONTAINS';
- public const MEMBER_OF = 'MEMBER_OF';
- public const STARTS_WITH = 'STARTS_WITH';
- public const ENDS_WITH = 'ENDS_WITH';
-
- /** @var string */
- private $field;
-
- /** @var string */
- private $op;
-
- /** @var Value */
- private $value;
-
- /**
- * @param string $field
- * @param string $operator
- * @param mixed $value
- */
- public function __construct($field, $operator, $value)
- {
- if (! ($value instanceof Value)) {
- $value = new Value($value);
- }
-
- $this->field = $field;
- $this->op = $operator;
- $this->value = $value;
- }
-
- /** @return string */
- public function getField()
- {
- return $this->field;
- }
-
- /** @return Value */
- public function getValue()
- {
- return $this->value;
- }
-
- /** @return string */
- public function getOperator()
- {
- return $this->op;
- }
-
- /**
- * {@inheritDoc}
- */
- public function visit(ExpressionVisitor $visitor)
- {
- return $visitor->walkComparison($this);
- }
-}
diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/ExpressionBuilder.php b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/ExpressionBuilder.php
deleted file mode 100644
index ebb21ca..0000000
--- a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/ExpressionBuilder.php
+++ /dev/null
@@ -1,181 +0,0 @@
-
*/
abstract class AbstractLazyCollection implements Collection
@@ -19,13 +21,12 @@ abstract class AbstractLazyCollection implements Collection
/**
* The backed collection to use
*
- * @psalm-var Collection|null
+ * @phpstan-var Collection|null
* @var Collection|null
*/
- protected $collection;
+ protected Collection|null $collection;
- /** @var bool */
- protected $initialized = false;
+ protected bool $initialized = false;
/**
* {@inheritDoc}
@@ -43,11 +44,11 @@ abstract class AbstractLazyCollection implements Collection
/**
* {@inheritDoc}
*/
- public function add($element)
+ public function add(mixed $element)
{
$this->initialize();
- return $this->collection->add($element);
+ $this->collection->add($element);
}
/**
@@ -61,10 +62,8 @@ abstract class AbstractLazyCollection implements Collection
/**
* {@inheritDoc}
- *
- * @template TMaybeContained
*/
- public function contains($element)
+ public function contains(mixed $element)
{
$this->initialize();
@@ -84,7 +83,7 @@ abstract class AbstractLazyCollection implements Collection
/**
* {@inheritDoc}
*/
- public function remove($key)
+ public function remove(string|int $key)
{
$this->initialize();
@@ -94,7 +93,7 @@ abstract class AbstractLazyCollection implements Collection
/**
* {@inheritDoc}
*/
- public function removeElement($element)
+ public function removeElement(mixed $element)
{
$this->initialize();
@@ -104,7 +103,7 @@ abstract class AbstractLazyCollection implements Collection
/**
* {@inheritDoc}
*/
- public function containsKey($key)
+ public function containsKey(string|int $key)
{
$this->initialize();
@@ -114,7 +113,7 @@ abstract class AbstractLazyCollection implements Collection
/**
* {@inheritDoc}
*/
- public function get($key)
+ public function get(string|int $key)
{
$this->initialize();
@@ -144,7 +143,7 @@ abstract class AbstractLazyCollection implements Collection
/**
* {@inheritDoc}
*/
- public function set($key, $value)
+ public function set(string|int $key, mixed $value)
{
$this->initialize();
$this->collection->set($key, $value);
@@ -220,6 +219,16 @@ abstract class AbstractLazyCollection implements Collection
return $this->collection->exists($p);
}
+ /**
+ * {@inheritDoc}
+ */
+ public function findFirst(Closure $p)
+ {
+ $this->initialize();
+
+ return $this->collection->findFirst($p);
+ }
+
/**
* {@inheritDoc}
*/
@@ -250,6 +259,16 @@ abstract class AbstractLazyCollection implements Collection
return $this->collection->map($func);
}
+ /**
+ * {@inheritDoc}
+ */
+ public function reduce(Closure $func, mixed $initial = null)
+ {
+ $this->initialize();
+
+ return $this->collection->reduce($func, $initial);
+ }
+
/**
* {@inheritDoc}
*/
@@ -265,7 +284,7 @@ abstract class AbstractLazyCollection implements Collection
*
* @template TMaybeContained
*/
- public function indexOf($element)
+ public function indexOf(mixed $element)
{
$this->initialize();
@@ -275,7 +294,7 @@ abstract class AbstractLazyCollection implements Collection
/**
* {@inheritDoc}
*/
- public function slice($offset, $length = null)
+ public function slice(int $offset, int|null $length = null)
{
$this->initialize();
@@ -286,7 +305,7 @@ abstract class AbstractLazyCollection implements Collection
* {@inheritDoc}
*
* @return Traversable
- * @psalm-return Traversable
+ * @phpstan-return Traversable
*/
#[ReturnTypeWillChange]
public function getIterator()
@@ -297,12 +316,14 @@ abstract class AbstractLazyCollection implements Collection
}
/**
+ * {@inheritDoc}
+ *
* @param TKey $offset
*
* @return bool
*/
#[ReturnTypeWillChange]
- public function offsetExists($offset)
+ public function offsetExists(mixed $offset)
{
$this->initialize();
@@ -310,12 +331,14 @@ abstract class AbstractLazyCollection implements Collection
}
/**
+ * {@inheritDoc}
+ *
* @param TKey $offset
*
- * @return mixed
+ * @return T|null
*/
#[ReturnTypeWillChange]
- public function offsetGet($offset)
+ public function offsetGet(mixed $offset)
{
$this->initialize();
@@ -323,13 +346,15 @@ abstract class AbstractLazyCollection implements Collection
}
/**
+ * {@inheritDoc}
+ *
* @param TKey|null $offset
* @param T $value
*
* @return void
*/
#[ReturnTypeWillChange]
- public function offsetSet($offset, $value)
+ public function offsetSet(mixed $offset, mixed $value)
{
$this->initialize();
$this->collection->offsetSet($offset, $value);
@@ -341,7 +366,7 @@ abstract class AbstractLazyCollection implements Collection
* @return void
*/
#[ReturnTypeWillChange]
- public function offsetUnset($offset)
+ public function offsetUnset(mixed $offset)
{
$this->initialize();
$this->collection->offsetUnset($offset);
@@ -352,7 +377,7 @@ abstract class AbstractLazyCollection implements Collection
*
* @return bool
*
- * @psalm-assert-if-true Collection $this->collection
+ * @phpstan-assert-if-true Collection $this->collection
*/
public function isInitialized()
{
@@ -364,7 +389,7 @@ abstract class AbstractLazyCollection implements Collection
*
* @return void
*
- * @psalm-assert Collection $this->collection
+ * @phpstan-assert Collection $this->collection
*/
protected function initialize()
{
diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/ArrayCollection.php b/vendor/doctrine/collections/src/ArrayCollection.php
similarity index 73%
rename from vendor/doctrine/collections/lib/Doctrine/Common/Collections/ArrayCollection.php
rename to vendor/doctrine/collections/src/ArrayCollection.php
index 186f6ec..b2897e7 100644
--- a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/ArrayCollection.php
+++ b/vendor/doctrine/collections/src/ArrayCollection.php
@@ -1,17 +1,24 @@
* @template-implements Selectable
- * @psalm-consistent-constructor
+ * @phpstan-consistent-constructor
*/
-class ArrayCollection implements Collection, Selectable
+class ArrayCollection implements Collection, Selectable, Stringable
{
/**
* An array containing the entries of this collection.
*
- * @psalm-var array
+ * @phpstan-var array
* @var mixed[]
*/
- private $elements;
+ private array $elements = [];
/**
* Initializes a new ArrayCollection.
*
- * @param array $elements
- * @psalm-param array $elements
+ * @phpstan-param array $elements
*/
public function __construct(array $elements = [])
{
@@ -86,13 +92,13 @@ class ArrayCollection implements Collection, Selectable
* instance should be created when constructor semantics have changed.
*
* @param array $elements Elements.
- * @psalm-param array $elements
+ * @phpstan-param array $elements
*
* @return static
- * @psalm-return static
+ * @phpstan-return static
*
- * @psalm-template K of array-key
- * @psalm-template V
+ * @phpstan-template K of array-key
+ * @phpstan-template V
*/
protected function createFrom(array $elements)
{
@@ -134,7 +140,7 @@ class ArrayCollection implements Collection, Selectable
/**
* {@inheritDoc}
*/
- public function remove($key)
+ public function remove(string|int $key)
{
if (! isset($this->elements[$key]) && ! array_key_exists($key, $this->elements)) {
return null;
@@ -149,7 +155,7 @@ class ArrayCollection implements Collection, Selectable
/**
* {@inheritDoc}
*/
- public function removeElement($element)
+ public function removeElement(mixed $element)
{
$key = array_search($element, $this->elements, true);
@@ -170,7 +176,7 @@ class ArrayCollection implements Collection, Selectable
* @return bool
*/
#[ReturnTypeWillChange]
- public function offsetExists($offset)
+ public function offsetExists(mixed $offset)
{
return $this->containsKey($offset);
}
@@ -180,10 +186,10 @@ class ArrayCollection implements Collection, Selectable
*
* @param TKey $offset
*
- * @return mixed
+ * @return T|null
*/
#[ReturnTypeWillChange]
- public function offsetGet($offset)
+ public function offsetGet(mixed $offset)
{
return $this->get($offset);
}
@@ -197,9 +203,9 @@ class ArrayCollection implements Collection, Selectable
* @return void
*/
#[ReturnTypeWillChange]
- public function offsetSet($offset, $value)
+ public function offsetSet(mixed $offset, mixed $value)
{
- if (! isset($offset)) {
+ if ($offset === null) {
$this->add($value);
return;
@@ -216,7 +222,7 @@ class ArrayCollection implements Collection, Selectable
* @return void
*/
#[ReturnTypeWillChange]
- public function offsetUnset($offset)
+ public function offsetUnset(mixed $offset)
{
$this->remove($offset);
}
@@ -224,17 +230,15 @@ class ArrayCollection implements Collection, Selectable
/**
* {@inheritDoc}
*/
- public function containsKey($key)
+ public function containsKey(string|int $key)
{
return isset($this->elements[$key]) || array_key_exists($key, $this->elements);
}
/**
* {@inheritDoc}
- *
- * @template TMaybeContained
*/
- public function contains($element)
+ public function contains(mixed $element)
{
return in_array($element, $this->elements, true);
}
@@ -244,21 +248,19 @@ class ArrayCollection implements Collection, Selectable
*/
public function exists(Closure $p)
{
- foreach ($this->elements as $key => $element) {
- if ($p($key, $element)) {
- return true;
- }
- }
-
- return false;
+ return array_any(
+ $this->elements,
+ static fn (mixed $element, mixed $key): bool => (bool) $p($key, $element),
+ );
}
/**
* {@inheritDoc}
*
- * @psalm-param TMaybeContained $element
+ * @phpstan-param TMaybeContained $element
*
- * @psalm-return (TMaybeContained is T ? TKey|false : false)
+ * @return int|string|false
+ * @phpstan-return (TMaybeContained is T ? TKey|false : false)
*
* @template TMaybeContained
*/
@@ -270,7 +272,7 @@ class ArrayCollection implements Collection, Selectable
/**
* {@inheritDoc}
*/
- public function get($key)
+ public function get(string|int $key)
{
return $this->elements[$key] ?? null;
}
@@ -294,7 +296,7 @@ class ArrayCollection implements Collection, Selectable
/**
* {@inheritDoc}
*
- * @return int
+ * @return int<0, max>
*/
#[ReturnTypeWillChange]
public function count()
@@ -305,7 +307,7 @@ class ArrayCollection implements Collection, Selectable
/**
* {@inheritDoc}
*/
- public function set($key, $value)
+ public function set(string|int $key, mixed $value)
{
$this->elements[$key] = $value;
}
@@ -313,16 +315,12 @@ class ArrayCollection implements Collection, Selectable
/**
* {@inheritDoc}
*
- * @psalm-suppress InvalidPropertyAssignmentValue
- *
* This breaks assumptions about the template type, but it would
* be a backwards-incompatible change to remove this method
*/
- public function add($element)
+ public function add(mixed $element)
{
$this->elements[] = $element;
-
- return true;
}
/**
@@ -337,7 +335,7 @@ class ArrayCollection implements Collection, Selectable
* {@inheritDoc}
*
* @return Traversable
- * @psalm-return Traversable
+ * @phpstan-return Traversable
*/
#[ReturnTypeWillChange]
public function getIterator()
@@ -348,12 +346,12 @@ class ArrayCollection implements Collection, Selectable
/**
* {@inheritDoc}
*
- * @psalm-param Closure(T):U $func
+ * @phpstan-param Closure(T):U $func
*
* @return static
- * @psalm-return static
+ * @phpstan-return static
*
- * @psalm-template U
+ * @phpstan-template U
*/
public function map(Closure $func)
{
@@ -362,27 +360,45 @@ class ArrayCollection implements Collection, Selectable
/**
* {@inheritDoc}
+ */
+ public function reduce(Closure $func, $initial = null)
+ {
+ return array_reduce($this->elements, $func, $initial);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @phpstan-param Closure(T, TKey):bool $p
*
* @return static
- * @psalm-return static
+ * @phpstan-return static
*/
public function filter(Closure $p)
{
return $this->createFrom(array_filter($this->elements, $p, ARRAY_FILTER_USE_BOTH));
}
+ /**
+ * {@inheritDoc}
+ */
+ public function findFirst(Closure $p)
+ {
+ return array_find(
+ $this->elements,
+ static fn (mixed $element, mixed $key): bool => (bool) $p($key, $element),
+ );
+ }
+
/**
* {@inheritDoc}
*/
public function forAll(Closure $p)
{
- foreach ($this->elements as $key => $element) {
- if (! $p($key, $element)) {
- return false;
- }
- }
-
- return true;
+ return array_all(
+ $this->elements,
+ static fn (mixed $element, mixed $key): bool => (bool) $p($key, $element),
+ );
}
/**
@@ -405,9 +421,11 @@ class ArrayCollection implements Collection, Selectable
/**
* Returns a string representation of this object.
+ * {@inheritDoc}
*
* @return string
*/
+ #[ReturnTypeWillChange]
public function __toString()
{
return self::class . '@' . spl_object_hash($this);
@@ -424,31 +442,31 @@ class ArrayCollection implements Collection, Selectable
/**
* {@inheritDoc}
*/
- public function slice($offset, $length = null)
+ public function slice(int $offset, int|null $length = null)
{
return array_slice($this->elements, $offset, $length, true);
}
- /**
- * {@inheritDoc}
- */
+ /** @phpstan-return Collection&Selectable */
public function matching(Criteria $criteria)
{
+ $accessRawFieldValues = $criteria->isRawFieldValueAccessEnabled();
+
$expr = $criteria->getWhereExpression();
$filtered = $this->elements;
if ($expr) {
- $visitor = new ClosureExpressionVisitor();
+ $visitor = new ClosureExpressionVisitor($accessRawFieldValues);
$filter = $visitor->dispatch($expr);
$filtered = array_filter($filtered, $filter);
}
- $orderings = $criteria->getOrderings();
+ $orderings = $criteria->orderings();
if ($orderings) {
$next = null;
foreach (array_reverse($orderings) as $field => $ordering) {
- $next = ClosureExpressionVisitor::sortByField($field, $ordering === Criteria::DESC ? -1 : 1, $next);
+ $next = ClosureExpressionVisitor::sortByField($field, $ordering === Order::Descending ? -1 : 1, $next, $accessRawFieldValues);
}
uasort($filtered, $next);
@@ -457,8 +475,8 @@ class ArrayCollection implements Collection, Selectable
$offset = $criteria->getFirstResult();
$length = $criteria->getMaxResults();
- if ($offset || $length) {
- $filtered = array_slice($filtered, (int) $offset, $length);
+ if ($offset !== null && $offset > 0 || $length !== null && $length > 0) {
+ $filtered = array_slice($filtered, (int) $offset, $length, true);
}
return $this->createFrom($filtered);
diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Collection.php b/vendor/doctrine/collections/src/Collection.php
similarity index 71%
rename from vendor/doctrine/collections/lib/Doctrine/Common/Collections/Collection.php
rename to vendor/doctrine/collections/src/Collection.php
index fb09192..265d9d8 100644
--- a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Collection.php
+++ b/vendor/doctrine/collections/src/Collection.php
@@ -1,5 +1,7 @@
* @template-extends ArrayAccess
*/
@@ -33,11 +35,11 @@ interface Collection extends ReadableCollection, ArrayAccess
* Adds an element at the end of the collection.
*
* @param mixed $element The element to add.
- * @psalm-param T $element
+ * @phpstan-param T $element
*
- * @return true Always TRUE.
+ * @return void we will require a native return type declaration in 3.0
*/
- public function add($element);
+ public function add(mixed $element);
/**
* Clears the collection, removing all elements.
@@ -50,50 +52,66 @@ interface Collection extends ReadableCollection, ArrayAccess
* Removes the element at the specified index from the collection.
*
* @param string|int $key The key/index of the element to remove.
- * @psalm-param TKey $key
+ * @phpstan-param TKey $key
*
* @return mixed The removed element or NULL, if the collection did not contain the element.
- * @psalm-return T|null
+ * @phpstan-return T|null
*/
- public function remove($key);
+ public function remove(string|int $key);
/**
* Removes the specified element from the collection, if it is found.
*
* @param mixed $element The element to remove.
- * @psalm-param T $element
+ * @phpstan-param T $element
*
* @return bool TRUE if this collection contained the specified element, FALSE otherwise.
*/
- public function removeElement($element);
+ public function removeElement(mixed $element);
/**
* Sets an element in the collection at the specified key/index.
*
* @param string|int $key The key/index of the element to set.
* @param mixed $value The element to set.
- * @psalm-param TKey $key
- * @psalm-param T $value
+ * @phpstan-param TKey $key
+ * @phpstan-param T $value
*
* @return void
*/
- public function set($key, $value);
+ public function set(string|int $key, mixed $value);
/**
- * {@inheritdoc}
+ * {@inheritDoc}
+ *
+ * @phpstan-param Closure(T):U $func
+ *
+ * @return Collection
+ * @phpstan-return Collection
+ *
+ * @phpstan-template U
+ */
+ public function map(Closure $func);
+
+ /**
+ * {@inheritDoc}
+ *
+ * @phpstan-param Closure(T, TKey):bool $p
*
* @return Collection A collection with the results of the filter operation.
- * @psalm-return Collection
+ * @phpstan-return Collection
*/
public function filter(Closure $p);
/**
- * {@inheritdoc}
+ * {@inheritDoc}
+ *
+ * @phpstan-param Closure(TKey, T):bool $p
*
* @return Collection[] An array with two elements. The first element contains the collection
* of elements where the predicate returned TRUE, the second element
* contains the collection of elements where the predicate returned FALSE.
- * @psalm-return array{0: Collection, 1: Collection}
+ * @phpstan-return array{0: Collection, 1: Collection}
*/
public function partition(Closure $p);
}
diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Criteria.php b/vendor/doctrine/collections/src/Criteria.php
similarity index 54%
rename from vendor/doctrine/collections/lib/Doctrine/Common/Collections/Criteria.php
rename to vendor/doctrine/collections/src/Criteria.php
index c1639d3..454455a 100644
--- a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Criteria.php
+++ b/vendor/doctrine/collections/src/Criteria.php
@@ -1,5 +1,7 @@
*/
+ private array $orderings = [];
- /** @var string[] */
- private $orderings = [];
-
- /** @var int|null */
- private $firstResult;
-
- /** @var int|null */
- private $maxResults;
+ private int|null $firstResult = null;
+ private int|null $maxResults = null;
/**
* Creates an instance of the class.
*
- * @return Criteria
+ * @return static
*/
- public static function create()
+ public static function create(/* bool $accessRawFieldValues = false */): self
{
- return new static();
+ $accessRawFieldValues = 0 < func_num_args() ? func_get_arg(0) : false;
+
+ return new static(firstResult: 0, accessRawFieldValues: $accessRawFieldValues);
}
/**
@@ -63,20 +63,30 @@ class Criteria
/**
* Construct a new Criteria.
*
- * @param string[]|null $orderings
- * @param int|null $firstResult
- * @param int|null $maxResults
+ * @param array|null $orderings
*/
- public function __construct(?Expression $expression = null, ?array $orderings = null, $firstResult = null, $maxResults = null)
- {
- $this->expression = $expression;
+ public function __construct(
+ private Expression|null $expression = null,
+ array|null $orderings = null,
+ int|null $firstResult = null,
+ int|null $maxResults = null,
+ private bool $accessRawFieldValues = false,
+ ) {
+ if (! $accessRawFieldValues) {
+ Deprecation::trigger(
+ 'doctrine/collections',
+ 'https://github.com/doctrine/collections/pull/472',
+ 'Not enabling raw field value access for the Criteria matching API in %s is deprecated. Raw field access will be the only supported method in 3.0',
+ self::class,
+ );
+ }
if ($firstResult === null && func_num_args() > 2) {
Deprecation::trigger(
'doctrine/collections',
'https://github.com/doctrine/collections/pull/311',
'Passing null as $firstResult to the constructor of %s is deprecated. Pass 0 instead or omit the argument.',
- self::class
+ self::class,
);
}
@@ -116,7 +126,7 @@ class Criteria
$this->expression = new CompositeExpression(
CompositeExpression::TYPE_AND,
- [$this->expression, $expression]
+ [$this->expression, $expression],
);
return $this;
@@ -136,7 +146,7 @@ class Criteria
$this->expression = new CompositeExpression(
CompositeExpression::TYPE_OR,
- [$this->expression, $expression]
+ [$this->expression, $expression],
);
return $this;
@@ -155,9 +165,32 @@ class Criteria
/**
* Gets the current orderings of this Criteria.
*
- * @return string[]
+ * @deprecated use orderings() instead
+ *
+ * @return array
*/
public function getOrderings()
+ {
+ Deprecation::trigger(
+ 'doctrine/collections',
+ 'https://github.com/doctrine/collections/pull/389',
+ 'Calling %s() is deprecated. Use %s::orderings() instead.',
+ __METHOD__,
+ self::class,
+ );
+
+ return array_map(
+ static fn (Order $ordering): string => $ordering->value,
+ $this->orderings,
+ );
+ }
+
+ /**
+ * Gets the current orderings of this Criteria.
+ *
+ * @return array
+ */
+ public function orderings(): array
{
return $this->orderings;
}
@@ -165,22 +198,40 @@ class Criteria
/**
* Sets the ordering of the result of this Criteria.
*
- * Keys are field and values are the order, being either ASC or DESC.
+ * Keys are field and values are the order, being a valid Order enum case.
*
- * @see Criteria::ASC
- * @see Criteria::DESC
+ * @see Order::Ascending
+ * @see Order::Descending
*
- * @param string[] $orderings
+ * @param array $orderings
*
* @return $this
*/
public function orderBy(array $orderings)
{
+ $method = __METHOD__;
$this->orderings = array_map(
- static function (string $ordering): string {
- return strtoupper($ordering) === Criteria::ASC ? Criteria::ASC : Criteria::DESC;
+ static function (string|Order $ordering) use ($method): Order {
+ if ($ordering instanceof Order) {
+ return $ordering;
+ }
+
+ static $triggered = false;
+
+ if (! $triggered) {
+ Deprecation::trigger(
+ 'doctrine/collections',
+ 'https://github.com/doctrine/collections/pull/389',
+ 'Passing non-Order enum values to %s() is deprecated. Pass Order enum values instead.',
+ $method,
+ );
+ }
+
+ $triggered = true;
+
+ return strtoupper($ordering) === Order::Ascending->value ? Order::Ascending : Order::Descending;
},
- $orderings
+ $orderings,
);
return $this;
@@ -203,14 +254,14 @@ class Criteria
*
* @return $this
*/
- public function setFirstResult($firstResult)
+ public function setFirstResult(int|null $firstResult)
{
if ($firstResult === null) {
Deprecation::triggerIfCalledFromOutside(
'doctrine/collections',
'https://github.com/doctrine/collections/pull/311',
'Passing null to %s() is deprecated, pass 0 instead.',
- __METHOD__
+ __METHOD__,
);
}
@@ -236,10 +287,16 @@ class Criteria
*
* @return $this
*/
- public function setMaxResults($maxResults)
+ public function setMaxResults(int|null $maxResults)
{
$this->maxResults = $maxResults;
return $this;
}
+
+ /** @internal */
+ public function isRawFieldValueAccessEnabled(): bool
+ {
+ return $this->accessRawFieldValues;
+ }
}
diff --git a/vendor/doctrine/collections/src/Expr/ClosureExpressionVisitor.php b/vendor/doctrine/collections/src/Expr/ClosureExpressionVisitor.php
new file mode 100644
index 0000000..f9e4156
--- /dev/null
+++ b/vendor/doctrine/collections/src/Expr/ClosureExpressionVisitor.php
@@ -0,0 +1,270 @@
+$accessor();
+ }
+ }
+
+ if (preg_match('/^is[A-Z]+/', $field) === 1 && method_exists($object, $field)) {
+ return $object->$field();
+ }
+
+ // __call should be triggered for get.
+ $accessor = $accessors[0] . $field;
+
+ if (method_exists($object, '__call')) {
+ return $object->$accessor();
+ }
+
+ if ($object instanceof ArrayAccess) {
+ return $object[$field];
+ }
+
+ if (isset($object->$field)) {
+ return $object->$field;
+ }
+
+ // camelcase field name to support different variable naming conventions
+ $ccField = preg_replace_callback('/_(.?)/', static fn ($matches) => strtoupper((string) $matches[1]), $field);
+
+ foreach ($accessors as $accessor) {
+ $accessor .= $ccField;
+
+ if (method_exists($object, $accessor)) {
+ return $object->$accessor();
+ }
+ }
+
+ return $object->$field;
+ }
+
+ private static function getNearestFieldValue(object $object, string $field): mixed
+ {
+ $reflectionClass = new ReflectionClass($object);
+
+ while ($reflectionClass && ! $reflectionClass->hasProperty($field)) {
+ $reflectionClass = $reflectionClass->getParentClass();
+ }
+
+ if ($reflectionClass === false) {
+ throw new RuntimeException(sprintf('Field "%s" does not exist in class "%s"', $field, $object::class));
+ }
+
+ $property = $reflectionClass->getProperty($field);
+
+ if (PHP_VERSION_ID >= 80400) {
+ return $property->getRawValue($object);
+ }
+
+ return $property->getValue($object);
+ }
+
+ /**
+ * Helper for sorting arrays of objects based on multiple fields + orientations.
+ *
+ * @return Closure
+ */
+ public static function sortByField(string $name, int $orientation = 1, Closure|null $next = null, /* bool $accessRawFieldValues = false */)
+ {
+ $accessRawFieldValues = 4 <= func_num_args() ? func_get_arg(3) : false;
+
+ if (! $accessRawFieldValues) {
+ Deprecation::trigger(
+ 'doctrine/collections',
+ 'https://github.com/doctrine/collections/pull/472',
+ 'Not enabling raw field value access for %s is deprecated. Raw field access will be the only supported method in 3.0',
+ __METHOD__,
+ );
+ }
+
+ if (! $next) {
+ $next = static fn (): int => 0;
+ }
+
+ return static function ($a, $b) use ($name, $next, $orientation, $accessRawFieldValues): int {
+ $aValue = ClosureExpressionVisitor::getObjectFieldValue($a, $name, $accessRawFieldValues);
+ $bValue = ClosureExpressionVisitor::getObjectFieldValue($b, $name, $accessRawFieldValues);
+
+ if ($aValue === $bValue) {
+ return $next($a, $b);
+ }
+
+ return ($aValue > $bValue ? 1 : -1) * $orientation;
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function walkComparison(Comparison $comparison)
+ {
+ $field = $comparison->getField();
+ $value = $comparison->getValue()->getValue();
+
+ return match ($comparison->getOperator()) {
+ Comparison::EQ => fn ($object): bool => self::getObjectFieldValue($object, $field, $this->accessRawFieldValues) === $value,
+ Comparison::NEQ => fn ($object): bool => self::getObjectFieldValue($object, $field, $this->accessRawFieldValues) !== $value,
+ Comparison::LT => fn ($object): bool => self::getObjectFieldValue($object, $field, $this->accessRawFieldValues) < $value,
+ Comparison::LTE => fn ($object): bool => self::getObjectFieldValue($object, $field, $this->accessRawFieldValues) <= $value,
+ Comparison::GT => fn ($object): bool => self::getObjectFieldValue($object, $field, $this->accessRawFieldValues) > $value,
+ Comparison::GTE => fn ($object): bool => self::getObjectFieldValue($object, $field, $this->accessRawFieldValues) >= $value,
+ Comparison::IN => function ($object) use ($field, $value): bool {
+ $fieldValue = ClosureExpressionVisitor::getObjectFieldValue($object, $field, $this->accessRawFieldValues);
+
+ return in_array($fieldValue, $value, is_scalar($fieldValue));
+ },
+ Comparison::NIN => function ($object) use ($field, $value): bool {
+ $fieldValue = ClosureExpressionVisitor::getObjectFieldValue($object, $field, $this->accessRawFieldValues);
+
+ return ! in_array($fieldValue, $value, is_scalar($fieldValue));
+ },
+ Comparison::CONTAINS => fn ($object): bool => str_contains((string) self::getObjectFieldValue($object, $field, $this->accessRawFieldValues), (string) $value),
+ Comparison::MEMBER_OF => function ($object) use ($field, $value): bool {
+ $fieldValues = ClosureExpressionVisitor::getObjectFieldValue($object, $field, $this->accessRawFieldValues);
+
+ if (! is_array($fieldValues)) {
+ $fieldValues = iterator_to_array($fieldValues);
+ }
+
+ return in_array($value, $fieldValues, true);
+ },
+ Comparison::STARTS_WITH => fn ($object): bool => str_starts_with((string) self::getObjectFieldValue($object, $field, $this->accessRawFieldValues), (string) $value),
+ Comparison::ENDS_WITH => fn ($object): bool => str_ends_with((string) self::getObjectFieldValue($object, $field, $this->accessRawFieldValues), (string) $value),
+ default => throw new RuntimeException('Unknown comparison operator: ' . $comparison->getOperator()),
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function walkValue(Value $value)
+ {
+ return $value->getValue();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function walkCompositeExpression(CompositeExpression $expr)
+ {
+ $expressionList = [];
+
+ foreach ($expr->getExpressionList() as $child) {
+ $expressionList[] = $this->dispatch($child);
+ }
+
+ return match ($expr->getType()) {
+ CompositeExpression::TYPE_AND => $this->andExpressions($expressionList),
+ CompositeExpression::TYPE_OR => $this->orExpressions($expressionList),
+ CompositeExpression::TYPE_NOT => $this->notExpression($expressionList),
+ default => throw new RuntimeException('Unknown composite ' . $expr->getType()),
+ };
+ }
+
+ /** @param callable[] $expressions */
+ private function andExpressions(array $expressions): Closure
+ {
+ return static fn ($object): bool => array_all(
+ $expressions,
+ static fn (callable $expression): bool => (bool) $expression($object),
+ );
+ }
+
+ /** @param callable[] $expressions */
+ private function orExpressions(array $expressions): Closure
+ {
+ return static fn ($object): bool => array_any(
+ $expressions,
+ static fn (callable $expression): bool => (bool) $expression($object),
+ );
+ }
+
+ /** @param callable[] $expressions */
+ private function notExpression(array $expressions): Closure
+ {
+ return static fn ($object) => ! $expressions[0]($object);
+ }
+}
diff --git a/vendor/doctrine/collections/src/Expr/Comparison.php b/vendor/doctrine/collections/src/Expr/Comparison.php
new file mode 100644
index 0000000..f1ea07f
--- /dev/null
+++ b/vendor/doctrine/collections/src/Expr/Comparison.php
@@ -0,0 +1,62 @@
+';
+ final public const LT = '<';
+ final public const LTE = '<=';
+ final public const GT = '>';
+ final public const GTE = '>=';
+ final public const IS = '='; // no difference with EQ
+ final public const IN = 'IN';
+ final public const NIN = 'NIN';
+ final public const CONTAINS = 'CONTAINS';
+ final public const MEMBER_OF = 'MEMBER_OF';
+ final public const STARTS_WITH = 'STARTS_WITH';
+ final public const ENDS_WITH = 'ENDS_WITH';
+
+ private readonly Value $value;
+
+ public function __construct(private readonly string $field, private readonly string $op, mixed $value)
+ {
+ if (! ($value instanceof Value)) {
+ $value = new Value($value);
+ }
+
+ $this->value = $value;
+ }
+
+ /** @return string */
+ public function getField()
+ {
+ return $this->field;
+ }
+
+ /** @return Value */
+ public function getValue()
+ {
+ return $this->value;
+ }
+
+ /** @return string */
+ public function getOperator()
+ {
+ return $this->op;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function visit(ExpressionVisitor $visitor)
+ {
+ return $visitor->walkComparison($this);
+ }
+}
diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/CompositeExpression.php b/vendor/doctrine/collections/src/Expr/CompositeExpression.php
similarity index 66%
rename from vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/CompositeExpression.php
rename to vendor/doctrine/collections/src/Expr/CompositeExpression.php
index 174b21b..b7b4544 100644
--- a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/CompositeExpression.php
+++ b/vendor/doctrine/collections/src/Expr/CompositeExpression.php
@@ -1,33 +1,32 @@
*/
+ private array $expressions = [];
/**
- * @param string $type
- * @param mixed[] $expressions
+ * @param Expression[] $expressions
*
* @throws RuntimeException
*/
- public function __construct($type, array $expressions)
+ public function __construct(private readonly string $type, array $expressions)
{
- $this->type = $type;
-
foreach ($expressions as $expr) {
if ($expr instanceof Value) {
throw new RuntimeException('Values are not supported expressions as children of and/or expressions.');
@@ -39,12 +38,16 @@ class CompositeExpression implements Expression
$this->expressions[] = $expr;
}
+
+ if ($type === self::TYPE_NOT && count($this->expressions) !== 1) {
+ throw new RuntimeException('Not expression only allows one expression as child.');
+ }
}
/**
* Returns the list of expressions nested in this composite.
*
- * @return Expression[]
+ * @return list
*/
public function getExpressionList()
{
diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Expression.php b/vendor/doctrine/collections/src/Expr/Expression.php
similarity index 89%
rename from vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Expression.php
rename to vendor/doctrine/collections/src/Expr/Expression.php
index 566d6d5..70ad45f 100644
--- a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Expression.php
+++ b/vendor/doctrine/collections/src/Expr/Expression.php
@@ -1,5 +1,7 @@
walkComparison($expr);
-
- case $expr instanceof Value:
- return $this->walkValue($expr);
-
- case $expr instanceof CompositeExpression:
- return $this->walkCompositeExpression($expr);
-
- default:
- throw new RuntimeException('Unknown Expression ' . get_class($expr));
- }
+ return $expr->visit($this);
}
}
diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Value.php b/vendor/doctrine/collections/src/Expr/Value.php
similarity index 70%
rename from vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Value.php
rename to vendor/doctrine/collections/src/Expr/Value.php
index 693d345..776770d 100644
--- a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Value.php
+++ b/vendor/doctrine/collections/src/Expr/Value.php
@@ -1,16 +1,13 @@
value = $value;
}
/** @return mixed */
diff --git a/vendor/doctrine/collections/src/ExpressionBuilder.php b/vendor/doctrine/collections/src/ExpressionBuilder.php
new file mode 100644
index 0000000..7bf5a09
--- /dev/null
+++ b/vendor/doctrine/collections/src/ExpressionBuilder.php
@@ -0,0 +1,128 @@
+
*/
@@ -18,14 +20,14 @@ interface ReadableCollection extends Countable, IteratorAggregate
* This is an O(n) operation, where n is the size of the collection.
*
* @param mixed $element The element to search for.
- * @psalm-param TMaybeContained $element
+ * @phpstan-param TMaybeContained $element
*
* @return bool TRUE if the collection contains the element, FALSE otherwise.
- * @psalm-return (TMaybeContained is T ? bool : false)
+ * @phpstan-return (TMaybeContained is T ? bool : false)
*
* @template TMaybeContained
*/
- public function contains($element);
+ public function contains(mixed $element);
/**
* Checks whether the collection is empty (contains no elements).
@@ -38,30 +40,30 @@ interface ReadableCollection extends Countable, IteratorAggregate
* Checks whether the collection contains an element with the specified key/index.
*
* @param string|int $key The key/index to check for.
- * @psalm-param TKey $key
+ * @phpstan-param TKey $key
*
* @return bool TRUE if the collection contains an element with the specified key/index,
* FALSE otherwise.
*/
- public function containsKey($key);
+ public function containsKey(string|int $key);
/**
* Gets the element at the specified key/index.
*
* @param string|int $key The key/index of the element to retrieve.
- * @psalm-param TKey $key
+ * @phpstan-param TKey $key
*
* @return mixed
- * @psalm-return T|null
+ * @phpstan-return T|null
*/
- public function get($key);
+ public function get(string|int $key);
/**
* Gets all keys/indices of the collection.
*
* @return int[]|string[] The keys/indices of the collection, in the order of the corresponding
* elements in the collection.
- * @psalm-return list
+ * @phpstan-return list
*/
public function getKeys();
@@ -70,7 +72,7 @@ interface ReadableCollection extends Countable, IteratorAggregate
*
* @return mixed[] The values of all elements in the collection, in the
* order they appear in the collection.
- * @psalm-return list
+ * @phpstan-return list
*/
public function getValues();
@@ -78,7 +80,7 @@ interface ReadableCollection extends Countable, IteratorAggregate
* Gets a native PHP array representation of the collection.
*
* @return mixed[]
- * @psalm-return array
+ * @phpstan-return array
*/
public function toArray();
@@ -86,7 +88,7 @@ interface ReadableCollection extends Countable, IteratorAggregate
* Sets the internal iterator to the first element in the collection and returns this element.
*
* @return mixed
- * @psalm-return T|false
+ * @phpstan-return T|false
*/
public function first();
@@ -94,7 +96,7 @@ interface ReadableCollection extends Countable, IteratorAggregate
* Sets the internal iterator to the last element in the collection and returns this element.
*
* @return mixed
- * @psalm-return T|false
+ * @phpstan-return T|false
*/
public function last();
@@ -102,7 +104,7 @@ interface ReadableCollection extends Countable, IteratorAggregate
* Gets the key/index of the element at the current iterator position.
*
* @return int|string|null
- * @psalm-return TKey|null
+ * @phpstan-return TKey|null
*/
public function key();
@@ -110,7 +112,7 @@ interface ReadableCollection extends Countable, IteratorAggregate
* Gets the element of the collection at the current iterator position.
*
* @return mixed
- * @psalm-return T|false
+ * @phpstan-return T|false
*/
public function current();
@@ -118,7 +120,7 @@ interface ReadableCollection extends Countable, IteratorAggregate
* Moves the internal iterator position to the next element and returns this element.
*
* @return mixed
- * @psalm-return T|false
+ * @phpstan-return T|false
*/
public function next();
@@ -133,15 +135,15 @@ interface ReadableCollection extends Countable, IteratorAggregate
* @param int|null $length The maximum number of elements to return, or null for no limit.
*
* @return mixed[]
- * @psalm-return array
+ * @phpstan-return array
*/
- public function slice($offset, $length = null);
+ public function slice(int $offset, int|null $length = null);
/**
* Tests for the existence of an element that satisfies the given predicate.
*
* @param Closure $p The predicate.
- * @psalm-param Closure(TKey, T):bool $p
+ * @phpstan-param Closure(TKey, T):bool $p
*
* @return bool TRUE if the predicate is TRUE for at least one element, FALSE otherwise.
*/
@@ -152,10 +154,10 @@ interface ReadableCollection extends Countable, IteratorAggregate
* The order of the elements is preserved.
*
* @param Closure $p The predicate used for filtering.
- * @psalm-param Closure(T):bool $p
+ * @phpstan-param Closure(T, TKey):bool $p
*
* @return ReadableCollection A collection with the results of the filter operation.
- * @psalm-return ReadableCollection
+ * @phpstan-return ReadableCollection
*/
public function filter(Closure $p);
@@ -163,12 +165,12 @@ interface ReadableCollection extends Countable, IteratorAggregate
* Applies the given function to each element in the collection and returns
* a new collection with the elements returned by the function.
*
- * @psalm-param Closure(T):U $func
+ * @phpstan-param Closure(T):U $func
*
- * @return Collection
- * @psalm-return Collection
+ * @return ReadableCollection
+ * @phpstan-return ReadableCollection
*
- * @psalm-template U
+ * @phpstan-template U
*/
public function map(Closure $func);
@@ -177,12 +179,12 @@ interface ReadableCollection extends Countable, IteratorAggregate
* Keys are preserved in the resulting collections.
*
* @param Closure $p The predicate on which to partition.
- * @psalm-param Closure(TKey, T):bool $p
+ * @phpstan-param Closure(TKey, T):bool $p
*
* @return ReadableCollection[] An array with two elements. The first element contains the collection
* of elements where the predicate returned TRUE, the second element
* contains the collection of elements where the predicate returned FALSE.
- * @psalm-return array{0: ReadableCollection, 1: ReadableCollection}
+ * @phpstan-return array{0: ReadableCollection, 1: ReadableCollection}
*/
public function partition(Closure $p);
@@ -190,7 +192,7 @@ interface ReadableCollection extends Countable, IteratorAggregate
* Tests whether the given predicate p holds for all elements of this collection.
*
* @param Closure $p The predicate.
- * @psalm-param Closure(TKey, T):bool $p
+ * @phpstan-param Closure(TKey, T):bool $p
*
* @return bool TRUE, if the predicate yields TRUE for all elements, FALSE otherwise.
*/
@@ -202,12 +204,39 @@ interface ReadableCollection extends Countable, IteratorAggregate
* For objects this means reference equality.
*
* @param mixed $element The element to search for.
- * @psalm-param TMaybeContained $element
+ * @phpstan-param TMaybeContained $element
*
* @return int|string|bool The key/index of the element or FALSE if the element was not found.
- * @psalm-return (TMaybeContained is T ? TKey|false : false)
+ * @phpstan-return (TMaybeContained is T ? TKey|false : false)
*
* @template TMaybeContained
*/
- public function indexOf($element);
+ public function indexOf(mixed $element);
+
+ /**
+ * Returns the first element of this collection that satisfies the predicate p.
+ *
+ * @param Closure $p The predicate.
+ * @phpstan-param Closure(TKey, T):bool $p
+ *
+ * @return mixed The first element respecting the predicate,
+ * null if no element respects the predicate.
+ * @phpstan-return T|null
+ */
+ public function findFirst(Closure $p);
+
+ /**
+ * Applies iteratively the given function to each element in the collection,
+ * so as to reduce the collection to a single value.
+ *
+ * @phpstan-param Closure(TReturn|TInitial, T):TReturn $func
+ * @phpstan-param TInitial $initial
+ *
+ * @return mixed
+ * @phpstan-return TReturn|TInitial
+ *
+ * @phpstan-template TReturn
+ * @phpstan-template TInitial
+ */
+ public function reduce(Closure $func, mixed $initial = null);
}
diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Selectable.php b/vendor/doctrine/collections/src/Selectable.php
similarity index 72%
rename from vendor/doctrine/collections/lib/Doctrine/Common/Collections/Selectable.php
rename to vendor/doctrine/collections/src/Selectable.php
index 9f7586d..eb11c93 100644
--- a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Selectable.php
+++ b/vendor/doctrine/collections/src/Selectable.php
@@ -1,5 +1,7 @@
&Selectable
- * @psalm-return Collection&Selectable
+ * @return ReadableCollection&Selectable
+ * @phpstan-return ReadableCollection&Selectable
*/
public function matching(Criteria $criteria);
}
diff --git a/vendor/dragonmantank/cron-expression/composer.json b/vendor/dragonmantank/cron-expression/composer.json
index fdb46ee..d2e23b8 100644
--- a/vendor/dragonmantank/cron-expression/composer.json
+++ b/vendor/dragonmantank/cron-expression/composer.json
@@ -12,13 +12,12 @@
}
],
"require": {
- "php": "^7.2|^8.0",
- "webmozart/assert": "^1.0"
+ "php": "^8.2|^8.3|^8.4|^8.5"
},
"require-dev": {
- "phpstan/phpstan": "^1.0",
- "phpunit/phpunit": "^7.0|^8.0|^9.0",
- "phpstan/extension-installer": "^1.0"
+ "phpstan/phpstan": "^1.12.32|^2.1.31",
+ "phpunit/phpunit": "^8.5.48|^9.0",
+ "phpstan/extension-installer": "^1.4.3"
},
"autoload": {
"psr-4": {
diff --git a/vendor/dragonmantank/cron-expression/src/Cron/AbstractField.php b/vendor/dragonmantank/cron-expression/src/Cron/AbstractField.php
index df2848d..55c9a9d 100644
--- a/vendor/dragonmantank/cron-expression/src/Cron/AbstractField.php
+++ b/vendor/dragonmantank/cron-expression/src/Cron/AbstractField.php
@@ -14,14 +14,14 @@ abstract class AbstractField implements FieldInterface
/**
* Full range of values that are allowed for this field type.
*
- * @var array
+ * @var array
*/
protected $fullRange = [];
/**
* Literal values we need to convert to integers.
*
- * @var array
+ * @var array
*/
protected $literals = [];
@@ -134,7 +134,6 @@ abstract class AbstractField implements FieldInterface
$step = $chunks[1] ?? 0;
// No step or 0 steps aren't cool
- /** @phpstan-ignore-next-line */
if (null === $step || '0' === $step || 0 === $step) {
return false;
}
@@ -167,7 +166,7 @@ abstract class AbstractField implements FieldInterface
// we will not wrap around. However, because the logic exists today
// per the above documentation, fixing the bug from #89
if ($step > $this->rangeEnd) {
- $thisRange = [$this->fullRange[$step % \count($this->fullRange)]];
+ $thisRange = [$this->fullRange[(int) $step % \count($this->fullRange)]];
} else {
if ($step > ($rangeEnd - $rangeStart)) {
$thisRange[$rangeStart] = (int) $rangeStart;
@@ -185,7 +184,7 @@ abstract class AbstractField implements FieldInterface
* @param string $expression The expression to evaluate
* @param int $max Maximum offset for range
*
- * @return array
+ * @return array
*/
public function getRangeForExpression(string $expression, int $max): array
{
@@ -219,7 +218,7 @@ abstract class AbstractField implements FieldInterface
}
$offset = '*' === $offset ? $this->rangeStart : $offset;
if ($stepSize >= $this->rangeEnd) {
- $values = [$this->fullRange[$stepSize % \count($this->fullRange)]];
+ $values = [$this->fullRange[(int) $stepSize % \count($this->fullRange)]];
} else {
for ($i = $offset; $i <= $to; $i += $stepSize) {
$values[] = (int) $i;
diff --git a/vendor/dragonmantank/cron-expression/src/Cron/CronExpression.php b/vendor/dragonmantank/cron-expression/src/Cron/CronExpression.php
index f3d8eb0..33f0d6c 100644
--- a/vendor/dragonmantank/cron-expression/src/Cron/CronExpression.php
+++ b/vendor/dragonmantank/cron-expression/src/Cron/CronExpression.php
@@ -47,7 +47,7 @@ class CronExpression
];
/**
- * @var array CRON expression parts
+ * @var array CRON expression parts
*/
protected $cronParts;
@@ -62,7 +62,7 @@ class CronExpression
protected $maxIterationCount = 1000;
/**
- * @var array Order in which to test of cron parts
+ * @var array Order in which to test of cron parts
*/
protected static $order = [
self::YEAR,
diff --git a/vendor/dragonmantank/cron-expression/src/Cron/DayOfWeekField.php b/vendor/dragonmantank/cron-expression/src/Cron/DayOfWeekField.php
index b9bbf48..6fae740 100644
--- a/vendor/dragonmantank/cron-expression/src/Cron/DayOfWeekField.php
+++ b/vendor/dragonmantank/cron-expression/src/Cron/DayOfWeekField.php
@@ -33,7 +33,7 @@ class DayOfWeekField extends AbstractField
protected $rangeEnd = 7;
/**
- * @var array Weekday range
+ * @var array Weekday range
*/
protected $nthRange;
@@ -69,7 +69,7 @@ class DayOfWeekField extends AbstractField
// Find out if this is the last specific weekday of the month
if ($lPosition = strpos($value, 'L')) {
- $weekday = $this->convertLiterals(substr($value, 0, $lPosition));
+ $weekday = (int) $this->convertLiterals(substr($value, 0, $lPosition));
$weekday %= 7;
$daysInMonth = (int) $date->format('t');
diff --git a/vendor/dragonmantank/cron-expression/src/Cron/FieldFactory.php b/vendor/dragonmantank/cron-expression/src/Cron/FieldFactory.php
index 839b275..4d3a764 100644
--- a/vendor/dragonmantank/cron-expression/src/Cron/FieldFactory.php
+++ b/vendor/dragonmantank/cron-expression/src/Cron/FieldFactory.php
@@ -14,7 +14,7 @@ use InvalidArgumentException;
class FieldFactory implements FieldFactoryInterface
{
/**
- * @var array Cache of instantiated fields
+ * @var array Cache of instantiated fields
*/
private $fields = [];
diff --git a/vendor/dragonmantank/cron-expression/src/Cron/HoursField.php b/vendor/dragonmantank/cron-expression/src/Cron/HoursField.php
index 413d138..2b39439 100644
--- a/vendor/dragonmantank/cron-expression/src/Cron/HoursField.php
+++ b/vendor/dragonmantank/cron-expression/src/Cron/HoursField.php
@@ -23,7 +23,7 @@ class HoursField extends AbstractField
protected $rangeEnd = 23;
/**
- * @var array|null Transitions returned by DateTimeZone::getTransitions()
+ * @var list>|null Transitions returned by DateTimeZone::getTransitions()
*/
protected $transitions = [];
@@ -73,6 +73,9 @@ class HoursField extends AbstractField
return $retval;
}
+ /**
+ * @return non-empty-array|null
+ */
public function getPastTransition(DateTimeInterface $date): ?array
{
$currentTimestamp = (int) $date->format('U');
@@ -160,6 +163,7 @@ class HoursField extends AbstractField
$target = (int) $hours[$position];
$originalHour = (int)$date->format('H');
+ $originalDst = (int)$date->format('I');
$originalDay = (int)$date->format('d');
$previousOffset = $date->getOffset();
@@ -200,6 +204,11 @@ class HoursField extends AbstractField
$date = $this->timezoneSafeModify($date, "-{$distance} hours");
}
+ $actualDst = (int)$date->format('I');
+ if ($originalDst < $actualDst) {
+ $date = $this->timezoneSafeModify($date, "-1 hours");
+ }
+
$date = $this->setTimeHour($date, $invert, $originalTimestamp);
$actualHour = (int)$date->format('H');
diff --git a/vendor/ipl/html/composer.json b/vendor/ipl/html/composer.json
index 99c5525..7dc6f09 100644
--- a/vendor/ipl/html/composer.json
+++ b/vendor/ipl/html/composer.json
@@ -9,7 +9,7 @@
"sort-packages": true
},
"require": {
- "php": ">=7.2",
+ "php": ">=8.2",
"ext-fileinfo": "*",
"ipl/stdlib": ">=0.12.0",
"ipl/validator": ">=0.5.0",
@@ -17,6 +17,7 @@
"guzzlehttp/psr7": "^2.5"
},
"require-dev": {
+ "ext-dom": "*",
"ipl/stdlib": "dev-main",
"ipl/validator": "dev-main"
},
diff --git a/vendor/ipl/html/src/Attribute.php b/vendor/ipl/html/src/Attribute.php
index c42485a..04405d4 100644
--- a/vendor/ipl/html/src/Attribute.php
+++ b/vendor/ipl/html/src/Attribute.php
@@ -12,6 +12,9 @@ use InvalidArgumentException;
*
* Usually attributes are not instantiated directly, but created through an HTML
* element's exposed methods.
+ *
+ * @phpstan-type _AttributeScalar string|bool|null
+ * @phpstan-type AttributeValue _AttributeScalar|array<_AttributeScalar>
*/
class Attribute
{
@@ -21,14 +24,14 @@ class Attribute
/** @var string The separator used if value is an array */
protected $separator = ' ';
- /** @var string|array|bool|null */
+ /** @var AttributeValue */
protected $value;
/**
* Create a new HTML attribute from the given name and value
*
- * @param string $name The name of the attribute
- * @param string|bool|array|null $value The value of the attribute
+ * @param string $name The name of the attribute
+ * @param AttributeValue $value The value of the attribute
*
* @throws InvalidArgumentException If the name of the attribute contains special characters
*/
@@ -40,8 +43,8 @@ class Attribute
/**
* Create a new HTML attribute from the given name and value
*
- * @param string $name The name of the attribute
- * @param string|bool|array|null $value The value of the attribute
+ * @param string $name The name of the attribute
+ * @param AttributeValue $value The value of the attribute
*
* @return static
*
@@ -68,6 +71,28 @@ class Attribute
return new static($name, null);
}
+ /**
+ * Sanitize the given ID
+ *
+ * Removes all characters that are not alphanumeric, underscore or hyphen. Additionally,
+ * the result is enforced to not start with a number by prepending the letter 'a'.
+ * Use it if you need to ensure that an ID is safe to use in CSS selectors.
+ *
+ * @param non-empty-string $id
+ *
+ * @return string
+ *
+ * @throws InvalidArgumentException If the ID is an empty string
+ */
+ public static function sanitizeId(string $id): string
+ {
+ if (empty($id)) {
+ throw new InvalidArgumentException('ID must not be empty');
+ }
+
+ return 'a' . preg_replace('/[^a-z0-9_\-]/i', '', $id);
+ }
+
/**
* Escape the name of an attribute
*
@@ -91,8 +116,8 @@ class Attribute
* Values are escaped according to the HTML5 double-quoted attribute value syntax:
* {@link https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 }.
*
- * @param string|array $value
- * @param string $glue Glue string to join elements if value is an array
+ * @param string|string[] $value
+ * @param string $glue Glue string to join elements if value is an array
*
* @return string
*/
@@ -184,7 +209,7 @@ class Attribute
/**
* Get the value of the attribute
*
- * @return string|bool|array|null
+ * @return AttributeValue
*/
public function getValue()
{
@@ -194,7 +219,7 @@ class Attribute
/**
* Set the value of the attribute
*
- * @param string|bool|array|null $value
+ * @param AttributeValue $value
*
* @return $this
*/
@@ -208,7 +233,7 @@ class Attribute
/**
* Add the given value(s) to the attribute
*
- * @param string|array $value The value(s) to add
+ * @param AttributeValue $value The value(s) to add
*
* @return $this
*/
@@ -230,7 +255,7 @@ class Attribute
*
* Does nothing if there is no such value to remove.
*
- * @param string|array $value The value(s) to remove
+ * @param AttributeValue $value The value(s) to remove
*
* @return $this
*/
diff --git a/vendor/ipl/html/src/Attributes.php b/vendor/ipl/html/src/Attributes.php
index 8df9bbd..ed7e668 100644
--- a/vendor/ipl/html/src/Attributes.php
+++ b/vendor/ipl/html/src/Attributes.php
@@ -17,6 +17,9 @@ use function ipl\Stdlib\get_php_type;
* behavior in various ways.
*
* Attributes usually come in name-value pairs and are rendered as name="value".
+ *
+ * @phpstan-import-type AttributeValue from Attribute
+ * @phpstan-type AttributesType array
*/
class Attributes implements ArrayAccess, IteratorAggregate
{
@@ -35,7 +38,7 @@ class Attributes implements ArrayAccess, IteratorAggregate
/**
* Create new HTML attributes
*
- * @param array $attributes
+ * @param AttributesType $attributes
*/
public function __construct(array $attributes = null)
{
@@ -57,7 +60,7 @@ class Attributes implements ArrayAccess, IteratorAggregate
/**
* Create new HTML attributes
*
- * @param array $attributes
+ * @param AttributesType $attributes
*
* @return static
*/
@@ -76,7 +79,7 @@ class Attributes implements ArrayAccess, IteratorAggregate
* construct and return a new Attributes instance.
* If the attributes are null, an empty new instance of Attributes is returned.
*
- * @param array|static|null $attributes
+ * @param AttributesType|static|null $attributes
*
* @return static
*
@@ -174,8 +177,8 @@ class Attributes implements ArrayAccess, IteratorAggregate
*
* If the attribute with the given name already exists, it gets overridden.
*
- * @param string|array|Attribute|self $attribute The attribute(s) to add
- * @param string|bool|array $value The value of the attribute
+ * @param string|AttributesType|Attribute|self $attribute The attribute(s) to add
+ * @param AttributeValue $value The value of the attribute
*
* @return $this
*
@@ -224,8 +227,8 @@ class Attributes implements ArrayAccess, IteratorAggregate
* If an attribute with the same name already exists, the attribute's value will be added to the current value of
* the attribute.
*
- * @param string|array|Attribute|self $attribute The attribute(s) to add
- * @param string|bool|array $value The value of the attribute
+ * @param string|AttributesType|Attribute|self $attribute The attribute(s) to add
+ * @param AttributeValue $value The value of the attribute
*
* @return $this
*
@@ -246,6 +249,7 @@ class Attributes implements ArrayAccess, IteratorAggregate
}
if (is_array($attribute)) {
+ // TODO: Handle if $attribute = [new Attribute('class', 'bar')]
foreach ($attribute as $name => $value) {
$this->add($name, $value);
}
@@ -280,7 +284,7 @@ class Attributes implements ArrayAccess, IteratorAggregate
* Remove the attribute with the given name or remove the given value from the attribute
*
* @param string $name The name of the attribute
- * @param null|string|array $value The value to remove if specified
+ * @param AttributeValue $value The value to remove if specified
*
* @return ?Attribute The removed or changed attribute, if any, otherwise null
*/
@@ -479,8 +483,8 @@ class Attributes implements ArrayAccess, IteratorAggregate
*
* If the attribute with the given name already exists, it gets overridden.
*
- * @param string $name Name of the attribute
- * @param mixed $value Value of the attribute
+ * @param string $name Name of the attribute
+ * @param AttributeValue $value Value of the attribute
*
* @throws InvalidArgumentException If the attribute name contains special characters
*/
diff --git a/vendor/ipl/html/src/BaseHtmlElement.php b/vendor/ipl/html/src/BaseHtmlElement.php
index 5dc01ce..0325186 100644
--- a/vendor/ipl/html/src/BaseHtmlElement.php
+++ b/vendor/ipl/html/src/BaseHtmlElement.php
@@ -2,7 +2,7 @@
namespace ipl\Html;
-use InvalidArgumentException;
+use ipl\Html\Contract\HtmlElementInterface;
use RuntimeException;
/**
@@ -32,7 +32,7 @@ use RuntimeException;
* }
* ```
*/
-abstract class BaseHtmlElement extends HtmlDocument
+abstract class BaseHtmlElement extends HtmlDocument implements HtmlElementInterface
{
/**
* List of void elements which must not contain end tags or content
@@ -76,11 +76,6 @@ abstract class BaseHtmlElement extends HtmlDocument
/** @var string Tag of element. Set this property in order to provide the element's tag when extending this class */
protected $tag;
- /**
- * Get the attributes of the element
- *
- * @return Attributes
- */
public function getAttributes()
{
if ($this->attributes === null) {
@@ -97,6 +92,13 @@ abstract class BaseHtmlElement extends HtmlDocument
return $this->attributes;
}
+ public function addAttributes($attributes)
+ {
+ $this->getAttributes()->add($attributes);
+
+ return $this;
+ }
+
/**
* Set the attributes of the element
*
@@ -114,44 +116,16 @@ abstract class BaseHtmlElement extends HtmlDocument
return $this;
}
- /**
- * Return true if the attribute with the given name exists, false otherwise
- *
- * @param string $name
- *
- * @return bool
- */
public function hasAttribute(string $name): bool
{
return $this->getAttributes()->has($name);
}
- /**
- * Get the attribute with the given name
- *
- * If the attribute does not already exist, an empty one is automatically created and added to the attributes.
- *
- * @param string $name
- *
- * @return Attribute
- *
- * @throws InvalidArgumentException If the attribute does not yet exist and its name contains special characters
- */
public function getAttribute(string $name): Attribute
{
return $this->getAttributes()->get($name);
}
- /**
- * Set the attribute with the given name and value
- *
- * If the attribute with the given name already exists, it gets overridden.
- *
- * @param string $name The name of the attribute
- * @param string|bool|array $value The value of the attribute
- *
- * @return $this
- */
public function setAttribute($name, $value)
{
$this->getAttributes()->set($name, $value);
@@ -159,33 +133,11 @@ abstract class BaseHtmlElement extends HtmlDocument
return $this;
}
- /**
- * Remove the attribute with the given name or remove the given value from the attribute
- *
- * @param string $name The name of the attribute
- * @param null|string|array $value The value to remove if specified
- *
- * @return ?Attribute The removed or changed attribute, if any, otherwise null
- */
public function removeAttribute(string $name, $value = null): ?Attribute
{
return $this->getAttributes()->remove($name, $value);
}
- /**
- * Add the given attributes
- *
- * @param Attributes|array $attributes
- *
- * @return $this
- */
- public function addAttributes($attributes)
- {
- $this->getAttributes()->add($attributes);
-
- return $this;
- }
-
/**
* Get the default attributes of the element
*
diff --git a/vendor/ipl/html/src/Contract/DecorableFormElement.php b/vendor/ipl/html/src/Contract/DecorableFormElement.php
new file mode 100644
index 0000000..18e688f
--- /dev/null
+++ b/vendor/ipl/html/src/Contract/DecorableFormElement.php
@@ -0,0 +1,32 @@
+
+ */
+ public function getDecorators(): DecoratorChain;
+
+ /**
+ * Get whether the element has any decorators
+ *
+ * @return bool
+ */
+ public function hasDecorators(): bool;
+
+ /**
+ * Decorate the element using its decorators
+ *
+ * @return void
+ */
+ public function applyDecoration(): void;
+}
diff --git a/vendor/ipl/html/src/Contract/DecorationResult.php b/vendor/ipl/html/src/Contract/DecorationResult.php
new file mode 100644
index 0000000..9cc71f5
--- /dev/null
+++ b/vendor/ipl/html/src/Contract/DecorationResult.php
@@ -0,0 +1,35 @@
+attributes === null) {
+ $this->attributes = new Attributes();
+ $this->registerAttributeCallbacks($this->attributes);
+ }
+
+ return $this->attributes;
+ }
+
+ /**
+ * Register attribute callbacks
+ *
+ * Override this method in order to register attribute callbacks in concrete classes.
+ *
+ * @param Attributes $attributes
+ */
+ abstract protected function registerAttributeCallbacks(Attributes $attributes): void;
+}
diff --git a/vendor/ipl/html/src/Contract/DecoratorOptionsInterface.php b/vendor/ipl/html/src/Contract/DecoratorOptionsInterface.php
new file mode 100644
index 0000000..55279da
--- /dev/null
+++ b/vendor/ipl/html/src/Contract/DecoratorOptionsInterface.php
@@ -0,0 +1,18 @@
+
+ */
+interface DefaultFormElementDecoration
+{
+ /**
+ * Set the default element decorators.
+ *
+ * The default decorators will be applied to all elements that do not have explicit decorators.
+ * The order of the decorators is important, as it determines the rendering order.
+ *
+ * Please see {@see DecoratorChain::addDecorators()} for the supported array formats.
+ *
+ * @param decoratorsFormat $decorators
+ *
+ * @return $this
+ */
+ public function setDefaultElementDecorators(array $decorators): static;
+
+ /**
+ * Add custom element decorator loader paths for the elements
+ *
+ * Each entry must be an array with index 0: class namespace, index 1: class name suffix (optional).
+ *
+ * @param loaderPaths $loaderPaths
+ *
+ * @return $this
+ */
+ public function addElementDecoratorLoaderPaths(array $loaderPaths): static;
+}
diff --git a/vendor/ipl/html/src/Contract/Form.php b/vendor/ipl/html/src/Contract/Form.php
new file mode 100644
index 0000000..1ababcd
--- /dev/null
+++ b/vendor/ipl/html/src/Contract/Form.php
@@ -0,0 +1,87 @@
+hasChanges()) {
+ * return;
+ * }
+ *
+ * $result->prepend(new HtmlElement('p', null, Text::create('You have unsaved changes.')));
+ * }
+ * ```
+ *
+ * @param DecorationResult $result
+ * @param Form $form
+ *
+ * @return void
+ */
+ public function decorateForm(DecorationResult $result, Form $form): void;
+}
diff --git a/vendor/ipl/html/src/Contract/FormElement.php b/vendor/ipl/html/src/Contract/FormElement.php
index 1467c50..da8adbd 100644
--- a/vendor/ipl/html/src/Contract/FormElement.php
+++ b/vendor/ipl/html/src/Contract/FormElement.php
@@ -7,6 +7,8 @@ use ipl\Html\Form;
/**
* Representation of form elements
+ *
+ * @phpstan-import-type AttributesType from Attributes
*/
interface FormElement extends Wrappable
{
@@ -20,7 +22,7 @@ interface FormElement extends Wrappable
/**
* Add attributes or options to the form element
*
- * @param iterable $attributes
+ * @param Attributes|AttributesType $attributes
*
* @return $this
*/
diff --git a/vendor/ipl/html/src/Contract/FormElementDecoration.php b/vendor/ipl/html/src/Contract/FormElementDecoration.php
new file mode 100644
index 0000000..1f92913
--- /dev/null
+++ b/vendor/ipl/html/src/Contract/FormElementDecoration.php
@@ -0,0 +1,43 @@
+getDescription();
+ *
+ * if ($description === null) {
+ * return;
+ * }
+ *
+ * $result->append(new HtmlElement('p', null, new Text($description)));
+ * }
+ * ```
+ *
+ * @param DecorationResult $result
+ * @param FormElement $formElement
+ *
+ * @return void
+ */
+ public function decorateFormElement(DecorationResult $result, FormElement $formElement): void;
+}
diff --git a/vendor/ipl/html/src/Contract/FormElementDecorator.php b/vendor/ipl/html/src/Contract/FormElementDecorator.php
index ca770ea..8e0b6b7 100644
--- a/vendor/ipl/html/src/Contract/FormElementDecorator.php
+++ b/vendor/ipl/html/src/Contract/FormElementDecorator.php
@@ -6,6 +6,8 @@ use ipl\Html\ValidHtml;
/**
* Representation of form element decorators
+ *
+ * @deprecated Use {@see FormElementDecoration} instead
*/
interface FormElementDecorator extends ValidHtml
{
diff --git a/vendor/ipl/html/src/Contract/FormElements.php b/vendor/ipl/html/src/Contract/FormElements.php
new file mode 100644
index 0000000..224a404
--- /dev/null
+++ b/vendor/ipl/html/src/Contract/FormElements.php
@@ -0,0 +1,103 @@
+ $options Element options as key-value pairs
+ *
+ * @return $this
+ *
+ * @throws InvalidArgumentException If the element is invalid (e.g., wrong type, no name)
+ */
+ public function addElement(string|FormElement $typeOrElement, ?string $name = null, ?array $options = null);
+
+ /**
+ * Register an element
+ *
+ * Registers the element for value and validation handling but does not add it to the render stack.
+ * Emits event {@see self::ON_ELEMENT_REGISTERED} with the element as parameter.
+ *
+ * @param FormElement $element
+ *
+ * @return $this
+ *
+ * @throws InvalidArgumentException If $element does not provide a name
+ */
+ public function registerElement(FormElement $element);
+
+ /**
+ * Remove an element
+ *
+ * @param string|FormElement $element
+ *
+ * @return $this
+ */
+ public function removeElement(string|FormElement $element);
+
+ /**
+ * Get the value of the element specified by name
+ *
+ * Returns $default if the element does not exist or has no value.
+ *
+ * @param string $name
+ * @param mixed $default
+ *
+ * @return mixed
+ */
+ public function getValue(string $name, mixed $default = null);
+
+ /**
+ * Get the values for all but ignored elements
+ *
+ * @return array Values as name-value pairs
+ */
+ public function getValues();
+
+ /**
+ * Populate values of registered elements
+ *
+ * @param iterable $values Values as name-value pairs
+ *
+ * @return $this
+ */
+ public function populate(iterable $values);
+}
diff --git a/vendor/ipl/html/src/Contract/HtmlElementInterface.php b/vendor/ipl/html/src/Contract/HtmlElementInterface.php
new file mode 100644
index 0000000..b3e4d00
--- /dev/null
+++ b/vendor/ipl/html/src/Contract/HtmlElementInterface.php
@@ -0,0 +1,90 @@
+ */
+ protected ?DecoratorChain $decorators = null;
+
+ /** @var bool Whether the form has been decorated */
+ protected bool $decorated = false;
+
protected $tag = 'form';
/**
@@ -59,10 +67,39 @@ class Form extends BaseHtmlElement
}
/**
- * Get the Form submission URL
+ * Escape reserved chars in the given string
*
- * @return string|null
+ * The characters '.', ' ' and optionally brackets are converted to unused control characters
+ * File Separator: ␜, Group Separator: ␝, Record Separator: ␝, and Unit Separator: ␟ respectively.
+ *
+ * This is done because:
+ * PHP converts dots and spaces in form element names to underscores by default in the request data.
+ * For example, becomes $_REQUEST["a_b"].
+ *
+ * And if an external variable name begins with a valid array syntax, trailing characters are silently ignored.
+ * For example, becomes $_REQUEST['foo']['bar'].
+ * See https://www.php.net/manual/en/language.variables.external.php
+ *
+ * @param string $string The string to escape
+ * @param bool $escapeBrackets Whether to escape brackets
+ *
+ * @return string
*/
+ public static function escapeReservedChars(string $string, bool $escapeBrackets = true): string
+ {
+ $escapeMap = [
+ '.' => chr(28), // File Separator
+ ' ' => chr(29) // Group Separator
+ ];
+
+ if ($escapeBrackets) {
+ $escapeMap['['] = chr(30); // Record Separator
+ $escapeMap[']'] = chr(31); // Unit Separator
+ }
+
+ return strtr($string, $escapeMap);
+ }
+
public function getAction()
{
return $this->action;
@@ -82,11 +119,6 @@ class Form extends BaseHtmlElement
return $this;
}
- /**
- * Get the HTTP method to submit the form with
- *
- * @return string
- */
public function getMethod()
{
return $this->method;
@@ -156,9 +188,6 @@ class Form extends BaseHtmlElement
return null;
}
- /**
- * @return ServerRequestInterface|null
- */
public function getRequest()
{
return $this->request;
@@ -167,7 +196,6 @@ class Form extends BaseHtmlElement
public function setRequest($request)
{
$this->request = $request;
- $this->emit(Form::ON_REQUEST, [$request]);
return $this;
}
@@ -197,15 +225,26 @@ class Form extends BaseHtmlElement
}
/**
- * @param ServerRequestInterface $request
+ * Get the decorators of this form
*
- * @return $this
+ * @return DecoratorChain
*/
+ public function getDecorators(): DecoratorChain
+ {
+ if ($this->decorators === null) {
+ $this->decorators = new DecoratorChain(FormDecoration::class);
+ }
+
+ return $this->decorators;
+ }
+
public function handleRequest(ServerRequestInterface $request)
{
$this->setRequest($request);
if (! $this->hasBeenSent()) {
+ $this->emit(Contract\Form::ON_REQUEST, [$request, $this]);
+
// Always assemble
$this->ensureAssembled();
@@ -234,32 +273,25 @@ class Form extends BaseHtmlElement
if ($this->hasBeenSubmitted()) {
if ($this->isValid()) {
try {
- $this->emit(Form::ON_SENT, [$this]);
+ $this->emit(Contract\Form::ON_SENT, [$this]);
$this->onSuccess();
- $this->emitOnce(Form::ON_SUCCESS, [$this]);
+ $this->emitOnce(Contract\Form::ON_SUBMIT, [$this]);
} catch (Throwable $e) {
$this->addMessage($e);
$this->onError();
- $this->emit(Form::ON_ERROR, [$e, $this]);
+ $this->emit(Contract\Form::ON_ERROR, [$e, $this]);
}
} else {
$this->onError();
}
} else {
$this->validatePartial();
- $this->emit(Form::ON_SENT, [$this]);
+ $this->emit(Contract\Form::ON_SENT, [$this]);
}
return $this;
}
- /**
- * Get whether the form has been sent
- *
- * A form is considered sent if the request's method equals the form's method.
- *
- * @return bool
- */
public function hasBeenSent()
{
if ($this->request === null) {
@@ -269,14 +301,6 @@ class Form extends BaseHtmlElement
return $this->request->getMethod() === $this->getMethod();
}
- /**
- * Get whether the form has been submitted
- *
- * A form is submitted when it has been sent and when the primary submit button, if set, has been pressed.
- * This method calls {@link hasBeenSent()} in order to detect whether the form has been sent.
- *
- * @return bool
- */
public function hasBeenSubmitted()
{
if (! $this->hasBeenSent()) {
@@ -290,19 +314,12 @@ class Form extends BaseHtmlElement
return true;
}
- /**
- * Get whether the form is valid
- *
- * {@link validate()} is called automatically if the form has not been validated before.
- *
- * @return bool
- */
public function isValid()
{
if ($this->isValid === null) {
$this->validate();
- $this->emit(self::ON_VALIDATE, [$this]);
+ $this->emit(Contract\Form::ON_VALIDATE, [$this]);
}
return $this->isValid;
@@ -348,17 +365,36 @@ class Form extends BaseHtmlElement
return $this;
}
- public function remove(ValidHtml $elementOrHtml)
+ public function remove(ValidHtml $content)
{
- if ($this->submitButton === $elementOrHtml) {
+ if ($this->submitButton === $content) {
$this->submitButton = null;
}
- $this->removeElement($elementOrHtml);
+ $this->baseRemove($content);
return $this;
}
+ /**
+ * Apply the form decoration
+ *
+ * @return void
+ */
+ protected function applyDecoration(): void
+ {
+ if ($this->decorated) {
+ return;
+ }
+
+ $result = new FormDecorationResult($this);
+ foreach ($this->getDecorators() as $decorator) {
+ $decorator->decorateForm($result, $this);
+ }
+
+ $this->decorated = true;
+ }
+
protected function onError()
{
$errors = Html::tag('ul', ['class' => 'errors']);
@@ -399,4 +435,11 @@ class Form extends BaseHtmlElement
->registerAttributeCallback('action', [$this, 'getAction'], [$this, 'setAction'])
->registerAttributeCallback('method', [$this, 'getMethod'], [$this, 'setMethod']);
}
+
+ protected function beforeRender(): void
+ {
+ $this->baseBeforeRender();
+
+ $this->applyDecoration();
+ }
}
diff --git a/vendor/ipl/html/src/FormDecoration/DecoratorChain.php b/vendor/ipl/html/src/FormDecoration/DecoratorChain.php
new file mode 100644
index 0000000..013f903
--- /dev/null
+++ b/vendor/ipl/html/src/FormDecoration/DecoratorChain.php
@@ -0,0 +1,368 @@
+
+ *
+ * @phpstan-type Ident string|class-string
+ * @phpstan-type decoratorOptionsFormat array
+ * @phpstan-type _decoratorsFormat1 array
+ * @phpstan-type _decoratorsFormat2 array
+ * @phpstan-type decoratorsFormat _decoratorsFormat1 | _decoratorsFormat2
+ */
+class DecoratorChain implements IteratorAggregate
+{
+ use Plugins;
+
+ /** @var class-string The type of decorator to accept */
+ private string $decoratorType;
+
+ /** @var array All registered decorators */
+ private array $decorators = [];
+
+ /**
+ * Create a new decorator chain
+ *
+ * @param class-string $decoratorType The type of decorator to accept
+ */
+ public function __construct(string $decoratorType)
+ {
+ $this->decoratorType = $decoratorType;
+
+ $this->addDefaultPluginLoader('decorator', __NAMESPACE__, 'Decorator');
+ }
+
+ /**
+ * Add a decorator loader
+ *
+ * @param string $namespace Namespace of the decorator(s)
+ * @param string $suffix Decorator class name suffix, if any
+ *
+ * @return $this
+ */
+ public function addDecoratorLoader(string $namespace, string $suffix = ''): static
+ {
+ $this->addPluginLoader('decorator', $namespace, $suffix);
+
+ return $this;
+ }
+
+ /**
+ * Get whether the chain has a decorator with the given identifier
+ *
+ * @param string $identifier
+ *
+ * @return bool
+ */
+ public function hasDecorator(string $identifier): bool
+ {
+ return isset($this->decorators[$identifier]);
+ }
+
+ /**
+ * Add a decorator to the chain
+ *
+ * @param string $identifier
+ * @param TDecorator|Ident $decorator
+ * @param decoratorOptionsFormat $options Only allowed if parameter #2 is a string
+ *
+ * @return $this
+ *
+ * @throws ValueError If the decorator with the given identifier already exists
+ * @throws InvalidArgumentException If the decorator specification is invalid
+ */
+ public function addDecorator(string $identifier, object|string $decorator, array $options = []): static
+ {
+ if (isset($this->decorators[$identifier])) {
+ throw new ValueError(sprintf(
+ 'Decorator with identifier "%s" already exists. Use replaceDecorator() to replace it.',
+ $identifier
+ ));
+ } elseif (! empty($options) && ! is_string($decorator)) {
+ throw new InvalidArgumentException('No options are allowed with parameter #2 of type Decorator');
+ }
+
+ if (is_string($decorator)) {
+ $decorator = $this->createDecorator($decorator, $options);
+ } elseif (! $decorator instanceof $this->decoratorType) {
+ throw new InvalidArgumentException(sprintf(
+ 'Expects parameter #2 to be a string or an instance of %s, got %s instead',
+ $this->decoratorType,
+ get_php_type($decorator)
+ ));
+ }
+
+ $this->decorators[$identifier] = $decorator;
+
+ return $this;
+ }
+
+ /**
+ * Replace a decorator in the chain with a new one
+ *
+ * @param string $identifier
+ * @param TDecorator|Ident $decorator
+ * @param decoratorOptionsFormat $options Only allowed if parameter #2 is a string
+ *
+ * @return $this
+ */
+ public function replaceDecorator(string $identifier, object|string $decorator, array $options = []): static
+ {
+ $this->decorators[$identifier] = null; // Preserve the placement of the previous decorator
+
+ return $this->addDecorator($identifier, $decorator, $options);
+ }
+
+ /**
+ * Add the decorators from the given decorator specification to the chain
+ *
+ * The order of the decorators is important, as it determines the rendering order.
+ *
+ * > NOTE: Decorators are registered with unique identifiers to enable easy replacement. If the decorator is
+ * provided as a string and no identifier is given, the decorator name is used as a fallback. In all other cases,
+ * an identifier must be specified explicitly.
+ *
+ * *It is recommended to use the decorator name or its purpose as the identifier, for example, 'container' for an
+ * 'HtmlTag' decorator that wraps content.*
+ *
+ * *The following array formats are supported:*
+ *
+ * ```
+ * // (1) When no options are required or defaults are sufficient
+ * $decorators = [
+ * 'Label',
+ * 'Description'
+ * ];
+ *
+ * // For the array above, the identifiers are 'Label' and 'Description'.
+ *
+ * // (2) Use Custom identifiers
+ * $decorators = [
+ * 'your-custom-identifier' => 'your-custom-decorator',
+ * ];
+ *
+ * // NOTE: For the following formats, identifiers MUST be defined manually.
+ *
+ * // (3) Override default options, key: decorator identifier, value: name and options
+ * $decorators = [
+ * 'Label' => 'Label',
+ * 'container' => [
+ * 'name' => 'HtmlTag',
+ * 'options' => ['tag' => 'div']
+ * ]
+ * ];
+ *
+ * // (4) Add Decorator instances
+ * $decorators = [
+ * 'Label' => new LabelDecorator(),
+ * 'container' => (new HtmlTagDecorator())->setTag('div')->setAttrs(['class' => 'container'])
+ * ];
+ *
+ * // (5) Class paths are also supported
+ * $decorators = [
+ * 'Label' => LabelDecorator::class,
+ * 'container' => ['name' => HtmlTagDecorator::class, 'options' => ['tag' => 'div']]
+ * ];
+ * ```
+ *
+ * @param static|decoratorsFormat $decorators
+ *
+ * @return $this
+ *
+ * @throws InvalidArgumentException If the decorator specification is invalid
+ */
+ public function addDecorators(DecoratorChain|array $decorators): static
+ {
+ if ($decorators instanceof static) {
+ foreach ($decorators->decorators as $identifier => $decorator) {
+ $this->addDecorator($identifier, $decorator);
+ }
+
+ return $this;
+ }
+
+ foreach ($decorators as $decoratorName => $decoratorOptions) {
+ $identifier = $decoratorName;
+ if (is_int($identifier)) {
+ if (! is_string($decoratorOptions)) {
+ throw new InvalidArgumentException(sprintf(
+ 'Unexpected type at position %d, string expected, got %s instead.'
+ . ' Either provide an $identifier (string) as the key, or ensure the value is of type string',
+ $identifier,
+ get_php_type($decoratorOptions)
+ ));
+ } elseif (class_exists($decoratorOptions)) {
+ throw new InvalidArgumentException(sprintf(
+ 'Unexpected type at position %d, string expected, got class %s instead.'
+ . ' Either provide an $identifier (string) as the key, or ensure the value is of type string',
+ $identifier,
+ $decoratorOptions
+ ));
+ }
+
+ $decoratorName = $decoratorOptions;
+ $identifier = $decoratorName;
+ $decoratorOptions = [];
+ } elseif (is_string($decoratorOptions) || $decoratorOptions instanceof $this->decoratorType) {
+ $decoratorName = $decoratorOptions;
+ $decoratorOptions = [];
+ } elseif (is_array($decoratorOptions)) {
+ if (! isset($decoratorOptions['name'])) {
+ throw new InvalidArgumentException(sprintf(
+ "Invalid decorator '%s'. Key 'name' is missing",
+ $identifier
+ ));
+ } elseif (! is_string($decoratorOptions['name'])) {
+ throw new InvalidArgumentException(sprintf(
+ "Invalid decorator '%s'. Value of the 'name' key must be a string, got %s instead",
+ $identifier,
+ get_php_type($decoratorOptions['name'])
+ ));
+ }
+
+ $decoratorName = $decoratorOptions['name'];
+ unset($decoratorOptions['name']);
+
+ $options = [];
+ if (isset($decoratorOptions['options'])) {
+ $options = $decoratorOptions['options'];
+
+ unset($decoratorOptions['options']);
+ }
+
+ if (! empty($decoratorOptions)) {
+ throw new InvalidArgumentException(
+ sprintf(
+ "No other keys except 'name' and 'options' are allowed, got '%s'",
+ implode("', '", array_keys($decoratorOptions))
+ )
+ );
+ }
+
+ $decoratorOptions = $options;
+ } else {
+ throw new InvalidArgumentException(sprintf(
+ "Invalid type for identifier '%s', expected an array,"
+ . " a string or an instance of %s, got %s instead",
+ $identifier,
+ $this->decoratorType,
+ get_php_type($decoratorOptions)
+ ));
+ }
+
+ if ($this->hasDecorator($identifier)) {
+ throw new InvalidArgumentException(sprintf(
+ "Decorator with identifier '%s' already exists. Duplicate identifiers are not allowed.",
+ $identifier
+ ));
+ }
+
+ $this->addDecorator($identifier, $decoratorName, $decoratorOptions);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Clear all decorators from the chain
+ *
+ * @return $this
+ */
+ public function clearDecorators(): static
+ {
+ $this->decorators = [];
+
+ return $this;
+ }
+
+ /**
+ * Create a decorator from the given name and options
+ *
+ * @param Ident $name
+ * @param decoratorOptionsFormat $options
+ *
+ * @return TDecorator
+ *
+ * @throws InvalidArgumentException If the given decorator is unknown or not an instance of the expected type
+ * @throws UnexpectedValueException If the loaded decorator is not an instance of the expected type
+ */
+ protected function createDecorator(string $name, array $options = []): object
+ {
+ if (class_exists($name)) {
+ $decorator = new $name();
+ if (! $decorator instanceof $this->decoratorType) {
+ throw new InvalidArgumentException(sprintf(
+ "Invalid decorator class '%s'. decorator must be an instance of %s",
+ $name,
+ $this->decoratorType,
+ ));
+ }
+ } else {
+ $class = $this->loadPlugin('decorator', $name);
+ if (! $class) {
+ throw new InvalidArgumentException(sprintf(
+ "Can't load decorator '%s'. decorator unknown",
+ $name
+ ));
+ }
+
+ $decorator = new $class();
+ if (! $decorator instanceof $this->decoratorType) {
+ throw new UnexpectedValueException(sprintf(
+ "%s expects loader to return an instance of %s for decorator '%s', got %s instead",
+ __METHOD__,
+ $this->decoratorType,
+ $name,
+ get_php_type($decorator)
+ ));
+ }
+ }
+
+ if (! empty($options)) {
+ if (! $decorator instanceof DecoratorOptionsInterface) {
+ throw new InvalidArgumentException(sprintf("Decorator '%s' does not support options", $name));
+ }
+
+ $decorator->getAttributes()->add($options);
+ }
+
+ return $decorator;
+ }
+
+ /**
+ * Get whether the chain has decorators
+ *
+ * @return bool
+ */
+ public function hasDecorators(): bool
+ {
+ return ! empty($this->decorators);
+ }
+
+ /**
+ * Iterate over all decorators
+ *
+ * @return Generator
+ */
+ #[\Override]
+ public function getIterator(): Generator
+ {
+ foreach ($this->decorators as $decorator) {
+ yield $decorator;
+ }
+ }
+}
diff --git a/vendor/ipl/html/src/FormDecoration/DescriptionDecorator.php b/vendor/ipl/html/src/FormDecoration/DescriptionDecorator.php
new file mode 100644
index 0000000..ed134f9
--- /dev/null
+++ b/vendor/ipl/html/src/FormDecoration/DescriptionDecorator.php
@@ -0,0 +1,100 @@
+class;
+ }
+
+ /**
+ * Set the css class(es)
+ *
+ * @param string|string[] $class
+ *
+ * @return $this
+ */
+ public function setClass(string|array $class): static
+ {
+ $this->class = $class;
+
+ return $this;
+ }
+
+ public function decorateFormElement(DecorationResult $result, FormElement $formElement): void
+ {
+ $isHtmlElement = $formElement instanceof HtmlElementInterface;
+
+ if ($formElement->getDescription() === null || ($isHtmlElement && $formElement->getTag() === 'fieldset')) {
+ return;
+ }
+
+ $elementDescription = $this->getElementDescription($formElement);
+ if ($isHtmlElement) {
+ if ($formElement->getAttributes()->has('id')) {
+ $elementId = $formElement->getAttributes()->get('id')->getValue();
+ } else {
+ $elementId = uniqid('form-element-');
+
+ // RadioElement applies all its attributes to each of its options, so we cannot set a fallback
+ // id attribute here.
+ if (! $formElement instanceof RadioElement) {
+ $formElement->getAttributes()->set('id', $elementId);
+ }
+ }
+
+ $descriptionId = 'desc_' . $elementId;
+ $formElement->getAttributes()->set('aria-describedby', $descriptionId);
+
+ $elementDescription->getAttributes()->set('id', $descriptionId);
+ }
+
+ $elementDescription->getAttributes()->add('class', $this->getClass());
+
+ $result->append($elementDescription);
+ }
+
+ /**
+ * Get the element description as HTML
+ *
+ * @param FormElement $formElement
+ *
+ * @return HtmlElementInterface & ValidHtml
+ */
+ protected function getElementDescription(FormElement $formElement): HtmlElementInterface & ValidHtml
+ {
+ return new HtmlElement('p', content: new Text($formElement->getDescription()));
+ }
+
+ protected function registerAttributeCallbacks(Attributes $attributes): void
+ {
+ $attributes->registerAttributeCallback('class', null, $this->setClass(...));
+ }
+}
diff --git a/vendor/ipl/html/src/FormDecoration/ErrorsDecorator.php b/vendor/ipl/html/src/FormDecoration/ErrorsDecorator.php
new file mode 100644
index 0000000..76769bc
--- /dev/null
+++ b/vendor/ipl/html/src/FormDecoration/ErrorsDecorator.php
@@ -0,0 +1,64 @@
+class;
+ }
+
+ /**
+ * Set the css class(es)
+ *
+ * @param string|string[] $class
+ *
+ * @return $this
+ */
+ public function setClass(string|array $class): static
+ {
+ $this->class = $class;
+
+ return $this;
+ }
+
+ public function decorateFormElement(DecorationResult $result, FormElement $formElement): void
+ {
+ $errors = new HtmlElement('ul', new Attributes(['class' => $this->getClass()]));
+ foreach ($formElement->getMessages() as $message) {
+ $errors->addHtml(new HtmlElement('li', null, Text::create($message)));
+ }
+
+ if (! $errors->isEmpty()) {
+ $result->append($errors);
+ }
+ }
+
+ protected function registerAttributeCallbacks(Attributes $attributes): void
+ {
+ $attributes->registerAttributeCallback('class', null, $this->setClass(...));
+ }
+}
diff --git a/vendor/ipl/html/src/FormDecoration/FieldsetDecorator.php b/vendor/ipl/html/src/FormDecoration/FieldsetDecorator.php
new file mode 100644
index 0000000..608482e
--- /dev/null
+++ b/vendor/ipl/html/src/FormDecoration/FieldsetDecorator.php
@@ -0,0 +1,36 @@
+getTag() !== 'fieldset') {
+ return;
+ }
+
+ // No fallback id & aria-describedby required. The legend already provides an accessible label for the fieldset
+ $description = $formElement->getDescription();
+ if ($description !== null) {
+ $formElement->prependHtml(new HtmlElement('p', content: new Text($description)));
+ }
+
+ $label = $formElement->getLabel();
+ if ($label !== null) {
+ $formElement->prependHtml(new HtmlElement('legend', null, Text::create($label)));
+ }
+ }
+}
diff --git a/vendor/ipl/html/src/FormDecoration/FormDecorationResult.php b/vendor/ipl/html/src/FormDecoration/FormDecorationResult.php
new file mode 100644
index 0000000..27d6a8d
--- /dev/null
+++ b/vendor/ipl/html/src/FormDecoration/FormDecorationResult.php
@@ -0,0 +1,54 @@
+content = $form;
+ }
+
+ public function append(ValidHtml $html): static
+ {
+ $this->content->addHtml($html);
+
+ return $this;
+ }
+
+ public function prepend(ValidHtml $html): static
+ {
+ $this->content->prependHtml($html);
+
+ return $this;
+ }
+
+ public function wrap(MutableHtml $html): static
+ {
+ if (! $html instanceof Wrappable) {
+ // If it's not a wrappable, mimic what wrapping usually means
+ $html = (new HtmlDocument())->addHtml($html);
+ }
+
+ $this->content->addWrapper($html);
+ $html->addHtml($this->content);
+ $this->content = $html;
+
+ return $this;
+ }
+}
diff --git a/vendor/ipl/html/src/FormDecoration/FormElementDecorationResult.php b/vendor/ipl/html/src/FormDecoration/FormElementDecorationResult.php
new file mode 100644
index 0000000..3dcdc91
--- /dev/null
+++ b/vendor/ipl/html/src/FormDecoration/FormElementDecorationResult.php
@@ -0,0 +1,96 @@
+>
+ */
+class FormElementDecorationResult implements DecorationResult
+{
+ /** @var content The HTML content */
+ protected array $content = [];
+
+ public function append(ValidHtml $html): static
+ {
+ $this->content[] = $html;
+
+ return $this;
+ }
+
+ public function prepend(ValidHtml $html): static
+ {
+ array_unshift($this->content, $html);
+
+ return $this;
+ }
+
+ public function wrap(MutableHtml $html): static
+ {
+ $this->content = [[$html, $this->content]];
+
+ return $this;
+ }
+
+ /**
+ * Assemble the results
+ *
+ * @return HtmlDocument
+ */
+ public function assemble(): HtmlDocument
+ {
+ $content = new HtmlDocument();
+
+ if (empty($this->content)) {
+ return $content;
+ }
+
+ $this->resolveContent($content, $this->content);
+
+ return $content;
+ }
+
+ /**
+ * Resolve content
+ *
+ * @param MutableHtml $parent The parent element
+ * @param content $content The content to be added
+ *
+ * @return void
+ */
+ protected function resolveContent(MutableHtml $parent, array $content): void
+ {
+ foreach ($content as $item) {
+ if (is_array($item)) {
+ $item = $this->resolveWrappedContent($item[0], $item[1]);
+ }
+
+ $parent->addHtml($item);
+ }
+ }
+
+ /**
+ * Resolve wrapped content
+ *
+ * @param MutableHtml $parent The parent element
+ * @param ValidHtml|content $item The content to be added
+ *
+ * @return ValidHtml The resolved parent element with content added
+ */
+ protected function resolveWrappedContent(MutableHtml $parent, ValidHtml|array $item): ValidHtml
+ {
+ if ($item instanceof ValidHtml) {
+ $parent->addHtml($item);
+ } else {
+ $this->resolveContent($parent, $item);
+ }
+
+ return $parent;
+ }
+}
diff --git a/vendor/ipl/html/src/FormDecoration/HtmlTagDecorator.php b/vendor/ipl/html/src/FormDecoration/HtmlTagDecorator.php
new file mode 100644
index 0000000..65786f7
--- /dev/null
+++ b/vendor/ipl/html/src/FormDecoration/HtmlTagDecorator.php
@@ -0,0 +1,217 @@
+ Attributes to apply */
+ protected array $attrs = [];
+
+ /**
+ * Get the HTML tag to use for the decoration
+ *
+ * @return string
+ *
+ * @throws RuntimeException if the tag is not set
+ */
+ public function getTag(): string
+ {
+ if (empty($this->tag)) {
+ throw new RuntimeException('Option "tag" must be set');
+ }
+
+ return $this->tag;
+ }
+
+ /**
+ * Set the HTML tag to use for the decoration
+ *
+ * @param string $tag
+ *
+ * @return $this
+ */
+ public function setTag(string $tag): static
+ {
+ $this->tag = $tag;
+
+ return $this;
+ }
+
+ /**
+ * Set the transformation type of the HTML tag
+ *
+ * @param Transformation $transformation
+ *
+ * @return $this
+ */
+ public function setTransformation(Transformation $transformation): static
+ {
+ $this->transformation = $transformation;
+
+ return $this;
+ }
+
+ /**
+ * Get the transformation type of the HTML tag
+ *
+ * @return Transformation
+ */
+ public function getTransformation(): Transformation
+ {
+ return $this->transformation;
+ }
+
+ /**
+ * Get the condition callable to decide whether to decorate the element
+ *
+ * @return ?callable(FormElement): bool
+ */
+ public function getCondition(): ?callable
+ {
+ return $this->condition;
+ }
+
+ /**
+ * Set the condition callable to decide whether to decorate the element
+ *
+ * @param callable(FormElement): bool $condition
+ *
+ * @return $this
+ */
+ public function setCondition(callable $condition): static
+ {
+ $this->condition = $condition;
+
+ return $this;
+ }
+
+ /**
+ * Get the css class(es)
+ *
+ * @return ?(string|string[])
+ */
+ public function getClass(): string|array|null
+ {
+ return $this->class;
+ }
+
+ /**
+ * Set the css class(es)
+ *
+ * @param string|string[] $class
+ *
+ * @return $this
+ */
+ public function setClass(string|array $class): static
+ {
+ $this->class = $class;
+
+ return $this;
+ }
+
+ /**
+ * Get attributes to apply
+ *
+ * @return array
+ */
+ public function getAttrs(): array
+ {
+ return $this->attrs;
+ }
+
+ /**
+ * Set attributes to apply
+ *
+ * @param array $attrs
+ *
+ * @return $this
+ */
+ public function setAttrs(array $attrs): static
+ {
+ $this->attrs = $attrs;
+
+ return $this;
+ }
+
+ /**
+ * @throws InvalidArgumentException if the condition callback does not return a boolean
+ * @throws RuntimeException if the condition callback throws an exception
+ */
+ public function decorateFormElement(DecorationResult $result, FormElement $formElement): void
+ {
+ $condition = $this->getCondition();
+ if ($condition !== null) {
+ try {
+ $shouldDecorate = $condition($formElement);
+ } catch (Throwable $e) {
+ throw new RuntimeException('Condition callback failed', previous: $e);
+ }
+
+ if (! is_bool($shouldDecorate)) {
+ throw new InvalidArgumentException(sprintf(
+ 'Condition callback must return a boolean, got %s',
+ get_php_type($shouldDecorate)
+ ));
+ }
+
+ if (! $shouldDecorate) {
+ return;
+ }
+ }
+
+ $class = $this->getClass();
+ $this->getTransformation()->apply(
+ $result,
+ new HtmlElement(
+ $this->getTag(),
+ $class === null
+ ? new Attributes($this->getAttrs())
+ : new Attributes(['class' => $class] + $this->getAttrs())
+ )
+ );
+ }
+
+ protected function registerAttributeCallbacks(Attributes $attributes): void
+ {
+ $attributes
+ ->registerAttributeCallback('tag', null, $this->setTag(...))
+ ->registerAttributeCallback('transformation', null, $this->setTransformation(...))
+ ->registerAttributeCallback('condition', null, $this->setCondition(...))
+ ->registerAttributeCallback('class', null, $this->setClass(...))
+ ->registerAttributeCallback('attrs', null, $this->setAttrs(...));
+ }
+}
diff --git a/vendor/ipl/html/src/FormDecoration/LabelDecorator.php b/vendor/ipl/html/src/FormDecoration/LabelDecorator.php
new file mode 100644
index 0000000..02dc5cf
--- /dev/null
+++ b/vendor/ipl/html/src/FormDecoration/LabelDecorator.php
@@ -0,0 +1,105 @@
+class;
+ }
+
+ /**
+ * Set the css class(es)
+ *
+ * @param string|string[] $class
+ *
+ * @return $this
+ */
+ public function setClass(string|array $class): static
+ {
+ $this->class = $class;
+
+ return $this;
+ }
+
+ public function decorateFormElement(DecorationResult $result, FormElement $formElement): void
+ {
+ $isHtmlElement = $formElement instanceof HtmlElementInterface;
+
+ $elementLabel = $this->getElementLabel($formElement);
+ if (
+ $formElement instanceof FormSubmitElement
+ || $elementLabel === null
+ || ($isHtmlElement && $formElement->getTag() === 'fieldset')
+ ) {
+ return;
+ }
+
+ if ($elementLabel instanceof HtmlElementInterface) {
+ $attributes['class'] = $this->getClass();
+ // RadioElement applies all its attributes to each of its options, so we cannot set a fallback
+ // id and for attribute here.
+ if ($isHtmlElement && ! $formElement instanceof RadioElement) {
+ $elementAttributes = $formElement->getAttributes();
+ if (! $elementAttributes->has('id')) {
+ $elementAttributes->set('id', uniqid('form-element-'));
+ }
+
+ $attributes['for'] = $elementAttributes->get('id')->getValue();
+ }
+
+ $elementLabel->addAttributes($attributes);
+ }
+
+ $result->append($elementLabel);
+ }
+
+ /**
+ * Get the label element for the given form element
+ *
+ * @param FormElement $formElement
+ *
+ * @return ?ValidHtml The label element or null if no label is set
+ */
+ protected function getElementLabel(FormElement $formElement): ?ValidHtml
+ {
+ $label = $formElement->getLabel();
+ if ($label === null) {
+ return null;
+ }
+
+ return new HtmlElement('label', content: new Text($label));
+ }
+
+ protected function registerAttributeCallbacks(Attributes $attributes): void
+ {
+ $attributes->registerAttributeCallback('class', null, $this->setClass(...));
+ }
+}
diff --git a/vendor/ipl/html/src/FormDecoration/RenderElementDecorator.php b/vendor/ipl/html/src/FormDecoration/RenderElementDecorator.php
new file mode 100644
index 0000000..b66bae0
--- /dev/null
+++ b/vendor/ipl/html/src/FormDecoration/RenderElementDecorator.php
@@ -0,0 +1,18 @@
+append($formElement);
+ }
+}
diff --git a/vendor/ipl/html/src/FormDecoration/Transformation.php b/vendor/ipl/html/src/FormDecoration/Transformation.php
new file mode 100644
index 0000000..91e0e8b
--- /dev/null
+++ b/vendor/ipl/html/src/FormDecoration/Transformation.php
@@ -0,0 +1,39 @@
+ $result->append($html),
+ self::Prepend => $result->prepend($html),
+ self::Wrap => $result->wrap($html)
+ };
+ }
+}
diff --git a/vendor/ipl/html/src/FormDecorator/CallbackDecorator.php b/vendor/ipl/html/src/FormDecorator/CallbackDecorator.php
index 1048bfb..7a6c1b8 100644
--- a/vendor/ipl/html/src/FormDecorator/CallbackDecorator.php
+++ b/vendor/ipl/html/src/FormDecorator/CallbackDecorator.php
@@ -7,6 +7,9 @@ use ipl\Html\Contract\FormElement;
use ipl\Html\Contract\FormElementDecorator;
use ipl\Html\HtmlDocument;
+/**
+ * @deprecated Use one of the new {@see FormElementDecoration} decorators instead
+ */
class CallbackDecorator extends HtmlDocument implements FormElementDecorator
{
/** @var Closure The decorating callback */
diff --git a/vendor/ipl/html/src/FormDecorator/DdDtDecorator.php b/vendor/ipl/html/src/FormDecorator/DdDtDecorator.php
index 9cfec20..564b924 100644
--- a/vendor/ipl/html/src/FormDecorator/DdDtDecorator.php
+++ b/vendor/ipl/html/src/FormDecorator/DdDtDecorator.php
@@ -2,11 +2,15 @@
namespace ipl\Html\FormDecorator;
+use ipl\Html\Attributes;
use ipl\Html\BaseHtmlElement;
use ipl\Html\FormElement\BaseFormElement;
use ipl\Html\Html;
use ipl\Html\ValidHtml;
+/**
+ * @deprecated Use one of the new {@see FormElementDecoration} decorators instead
+ */
class DdDtDecorator extends BaseHtmlElement implements DecoratorInterface
{
protected $tag = 'dl';
@@ -92,7 +96,7 @@ class DdDtDecorator extends BaseHtmlElement implements DecoratorInterface
return null;
}
- public function addHtml(ValidHtml ...$content)
+ public function addHtml(ValidHtml ...$content): static
{
// TODO: is this required?
if (! in_array($this->wrappedElement, $content, true)) {
diff --git a/vendor/ipl/html/src/FormDecorator/DecoratorInterface.php b/vendor/ipl/html/src/FormDecorator/DecoratorInterface.php
index 1ed1a38..a9af63f 100644
--- a/vendor/ipl/html/src/FormDecorator/DecoratorInterface.php
+++ b/vendor/ipl/html/src/FormDecorator/DecoratorInterface.php
@@ -2,10 +2,10 @@
namespace ipl\Html\FormDecorator;
-use ipl\Html\Contract\FormElementDecorator;
+use ipl\Html\Contract\FormElementDecoration;
use ipl\Html\FormElement\BaseFormElement;
-/** @deprecated Use {@link FormElementDecorator} instead */
+/** @deprecated Use {@see FormElementDecoration} instead */
interface DecoratorInterface
{
/**
diff --git a/vendor/ipl/html/src/FormDecorator/DivDecorator.php b/vendor/ipl/html/src/FormDecorator/DivDecorator.php
index 4935f01..9553d9b 100644
--- a/vendor/ipl/html/src/FormDecorator/DivDecorator.php
+++ b/vendor/ipl/html/src/FormDecorator/DivDecorator.php
@@ -5,6 +5,7 @@ namespace ipl\Html\FormDecorator;
use ipl\Html\Attributes;
use ipl\Html\BaseHtmlElement;
use ipl\Html\Contract\FormElement;
+use ipl\Html\Contract\FormElementDecoration;
use ipl\Html\Contract\FormElementDecorator;
use ipl\Html\Contract\FormSubmitElement;
use ipl\Html\FormElement\FieldsetElement;
@@ -15,6 +16,8 @@ use ipl\Html\Text;
/**
* Form element decorator based on div elements
+ *
+ * @deprecated Use one of the new {@see FormElementDecoration} decorators instead
*/
class DivDecorator extends BaseHtmlElement implements FormElementDecorator
{
diff --git a/vendor/ipl/html/src/FormElement/BaseFormElement.php b/vendor/ipl/html/src/FormElement/BaseFormElement.php
index 837ac45..1e9a260 100644
--- a/vendor/ipl/html/src/FormElement/BaseFormElement.php
+++ b/vendor/ipl/html/src/FormElement/BaseFormElement.php
@@ -5,15 +5,24 @@ namespace ipl\Html\FormElement;
use ipl\Html\Attribute;
use ipl\Html\Attributes;
use ipl\Html\BaseHtmlElement;
+use ipl\Html\Contract\DecorableFormElement;
use ipl\Html\Contract\FormElement;
+use ipl\Html\Contract\FormElementDecoration;
use ipl\Html\Contract\ValueCandidates;
use ipl\Html\Form;
+use ipl\Html\FormDecoration\DecoratorChain;
+use ipl\Html\FormDecoration\FormElementDecorationResult;
use ipl\I18n\Translation;
use ipl\Stdlib\Messages;
use ipl\Validator\ValidatorChain;
use ReflectionProperty;
-abstract class BaseFormElement extends BaseHtmlElement implements FormElement, ValueCandidates
+/**
+ * Base implementation of a form element
+ *
+ * @phpstan-import-type decoratorsFormat from DecoratorChain
+ */
+abstract class BaseFormElement extends BaseHtmlElement implements FormElement, ValueCandidates, DecorableFormElement
{
use Messages;
use Translation;
@@ -27,6 +36,9 @@ abstract class BaseFormElement extends BaseHtmlElement implements FormElement, V
/** @var string Name of the element */
protected $name;
+ /** @var string Escaped name of the element */
+ protected string $escapedName;
+
/** @var bool Whether the element is ignored */
protected $ignored = false;
@@ -45,6 +57,9 @@ abstract class BaseFormElement extends BaseHtmlElement implements FormElement, V
/** @var array Value candidates of the element */
protected $valueCandidates = [];
+ /** @var ?DecoratorChain All registered decorators */
+ protected ?DecoratorChain $decorators = null;
+
/**
* Create a new form element
*
@@ -115,6 +130,9 @@ abstract class BaseFormElement extends BaseHtmlElement implements FormElement, V
{
$this->name = $name;
+ // Name is always escaped
+ $this->escapedName = Form::escapeReservedChars($name);
+
return $this;
}
@@ -137,6 +155,16 @@ abstract class BaseFormElement extends BaseHtmlElement implements FormElement, V
return $this;
}
+ /**
+ * Get the escaped name of the element
+ *
+ * @return string
+ */
+ public function getEscapedName(): string
+ {
+ return $this->escapedName;
+ }
+
public function isRequired()
{
return $this->required;
@@ -289,7 +317,7 @@ abstract class BaseFormElement extends BaseHtmlElement implements FormElement, V
*/
public function getNameAttribute()
{
- return $this->getName();
+ return $this->getEscapedName();
}
/**
@@ -351,7 +379,8 @@ abstract class BaseFormElement extends BaseHtmlElement implements FormElement, V
->registerAttributeCallback('description', null, [$this, 'setDescription'])
->registerAttributeCallback('validators', null, [$this, 'setValidators'])
->registerAttributeCallback('ignore', null, [$this, 'setIgnored'])
- ->registerAttributeCallback('required', [$this, 'getRequiredAttribute'], [$this, 'setRequired']);
+ ->registerAttributeCallback('required', [$this, 'getRequiredAttribute'], [$this, 'setRequired'])
+ ->registerAttributeCallback('decorators', null, [$this, 'setDecorators']);
$this->registerCallbacks();
}
@@ -385,6 +414,49 @@ abstract class BaseFormElement extends BaseHtmlElement implements FormElement, V
return $name;
}
- return $this->getName();
+ return $this->getEscapedName();
+ }
+
+ public function getDecorators(): DecoratorChain
+ {
+ if ($this->decorators === null) {
+ $this->decorators = new DecoratorChain(FormElementDecoration::class);
+ }
+
+ return $this->decorators;
+ }
+
+ /**
+ * Set the decorators
+ *
+ * @param decoratorsFormat $decorators
+ *
+ * @return $this
+ */
+ public function setDecorators(array $decorators): static
+ {
+ $this->getDecorators()
+ ->clearDecorators()
+ ->addDecorators($decorators);
+
+ return $this;
+ }
+
+ public function hasDecorators(): bool
+ {
+ return $this->getDecorators()->hasDecorators();
+ }
+
+ public function applyDecoration(): void
+ {
+ $results = new FormElementDecorationResult();
+ foreach ($this->getDecorators() as $decorator) {
+ $decorator->decorateFormElement($results, $this);
+ }
+
+ $wrapper = $results->assemble();
+ if (! $wrapper->isEmpty()) {
+ $this->addWrapper($wrapper);
+ }
}
}
diff --git a/vendor/ipl/html/src/FormElement/FieldsetElement.php b/vendor/ipl/html/src/FormElement/FieldsetElement.php
index c18d472..978745f 100644
--- a/vendor/ipl/html/src/FormElement/FieldsetElement.php
+++ b/vendor/ipl/html/src/FormElement/FieldsetElement.php
@@ -4,6 +4,7 @@ namespace ipl\Html\FormElement;
use InvalidArgumentException;
use ipl\Html\Common\MultipleAttribute;
+use ipl\Html\Contract\DefaultFormElementDecoration;
use ipl\Html\Contract\FormElement;
use ipl\Html\Contract\FormElementDecorator;
use ipl\Html\Contract\Wrappable;
@@ -11,7 +12,7 @@ use LogicException;
use function ipl\Stdlib\get_php_type;
-class FieldsetElement extends BaseFormElement
+class FieldsetElement extends BaseFormElement implements \ipl\Html\Contract\FormElements, DefaultFormElementDecoration
{
use FormElements {
FormElements::getValue as private getElementValue;
@@ -26,6 +27,8 @@ class FieldsetElement extends BaseFormElement
*/
public function hasValue()
{
+ $this->ensureAssembled();
+
foreach ($this->getElements() as $element) {
if ($element->hasValue()) {
return true;
@@ -113,6 +116,14 @@ class FieldsetElement extends BaseFormElement
$multiple = $element->isMultiple();
}
+ // This check is required as the getEscapedName method is not implemented in
+ // the FormElement interface
+ if ($element instanceof BaseFormElement) {
+ $name = $element->getEscapedName();
+ } else {
+ $name = $element->getName();
+ }
+
/**
* We don't change the {@see BaseFormElement::$name} property of the element,
* otherwise methods like {@see FormElements::populate() and {@see FormElements::getElement()} would fail,
@@ -121,7 +132,7 @@ class FieldsetElement extends BaseFormElement
return sprintf(
'%s[%s]%s',
$this->getValueOfNameAttribute(),
- $element->getName(),
+ $name,
$multiple ? '[]' : ''
);
});
diff --git a/vendor/ipl/html/src/FormElement/FileElement.php b/vendor/ipl/html/src/FormElement/FileElement.php
index d9ca8fd..c284368 100644
--- a/vendor/ipl/html/src/FormElement/FileElement.php
+++ b/vendor/ipl/html/src/FormElement/FileElement.php
@@ -93,7 +93,7 @@ class FileElement extends InputElement
public function getNameAttribute()
{
- $name = $this->getName();
+ $name = $this->getEscapedName();
return $this->isMultiple() ? ($name . '[]') : $name;
}
@@ -260,12 +260,12 @@ class FileElement extends InputElement
$form->setAttribute('enctype', 'multipart/form-data');
}
- $chosenFiles = (array) $form->getPopulatedValue('chosen_file_' . $this->getName(), []);
+ $chosenFiles = (array) $form->getPopulatedValue('chosen_file_' . $this->getEscapedName(), []);
foreach ($chosenFiles as $chosenFile) {
$this->files[$chosenFile] = null;
}
- $this->filesToRemove = (array) $form->getPopulatedValue('remove_file_' . $this->getName(), []);
+ $this->filesToRemove = (array) $form->getPopulatedValue('remove_file_' . $this->getEscapedName(), []);
}
protected function addDefaultValidators(ValidatorChain $chain): void
diff --git a/vendor/ipl/html/src/FormElement/FormElements.php b/vendor/ipl/html/src/FormElement/FormElements.php
index 4a2c598..6121b76 100644
--- a/vendor/ipl/html/src/FormElement/FormElements.php
+++ b/vendor/ipl/html/src/FormElement/FormElements.php
@@ -3,18 +3,29 @@
namespace ipl\Html\FormElement;
use InvalidArgumentException;
+use ipl\Html\Contract\DecorableFormElement;
+use ipl\Html\Contract\DefaultFormElementDecoration;
use ipl\Html\Contract\FormElement;
+use ipl\Html\Contract\FormElementDecoration;
use ipl\Html\Contract\FormElementDecorator;
use ipl\Html\Contract\ValueCandidates;
use ipl\Html\Form;
+use ipl\Html\FormDecoration\DecoratorChain;
use ipl\Html\FormDecorator\DecoratorInterface;
+use ipl\Html\HtmlDocument;
use ipl\Html\ValidHtml;
use ipl\Stdlib\Events;
use ipl\Stdlib\Plugins;
+use RuntimeException;
use UnexpectedValueException;
+use WeakMap;
use function ipl\Stdlib\get_php_type;
+/**
+ * @phpstan-import-type decoratorsFormat from DecoratorChain
+ * @phpstan-import-type loaderPaths from DefaultFormElementDecoration
+ */
trait FormElements
{
use Events;
@@ -29,6 +40,29 @@ trait FormElements
/** @var bool Whether the default element loader has been registered */
protected $defaultElementLoaderRegistered = false;
+ /** @var ?WeakMap The decorated elements */
+ private ?WeakMap $decoratedElements = null;
+
+ /**
+ * Custom Element decorator loader paths
+ *
+ * Override this property to add custom decorator loader paths.
+ *
+ * @var loaderPaths
+ */
+ protected array $elementDecoratorLoaderPaths = [];
+
+ /**
+ * Default element decorators
+ *
+ * Override this property to change the default decorators of the elements.
+ *
+ * Please see {@see DecoratorChain::addDecorators()} for the supported array formats.
+ *
+ * @var decoratorsFormat
+ */
+ protected array $defaultElementDecorators = [];
+
/** @var FormElement[] */
private $elements = [];
@@ -36,22 +70,42 @@ trait FormElements
private $populatedValues = [];
/**
- * Get all elements
+ * Get the default element decorators.
*
- * @return FormElement[]
+ * @return decoratorsFormat
*/
+ public function getDefaultElementDecorators(): array
+ {
+ return $this->defaultElementDecorators;
+ }
+
+ public function setDefaultElementDecorators(array $decorators): static
+ {
+ if ($this->hasDefaultElementDecorator()) {
+ throw new RuntimeException(sprintf(
+ 'Cannot use element decorators of type %s and legacy decorator of type %s together',
+ FormElementDecoration::class,
+ FormElementDecorator::class
+ ));
+ }
+
+ $this->defaultElementDecorators = $decorators;
+
+ return $this;
+ }
+
+ public function addElementDecoratorLoaderPaths(array $loaderPaths): static
+ {
+ $this->elementDecoratorLoaderPaths = $loaderPaths;
+
+ return $this;
+ }
+
public function getElements()
{
return $this->elements;
}
- /**
- * Get whether the given element exists
- *
- * @param string|FormElement $element
- *
- * @return bool
- */
public function hasElement($element)
{
if (is_string($element)) {
@@ -65,15 +119,6 @@ trait FormElements
return false;
}
- /**
- * Get the element by the given name
- *
- * @param string $name
- *
- * @return FormElement
- *
- * @throws InvalidArgumentException If no element with the given name exists
- */
public function getElement($name)
{
if (! array_key_exists($name, $this->elements)) {
@@ -86,20 +131,6 @@ trait FormElements
return $this->elements[$name];
}
- /**
- * Add an element
- *
- * @param string|FormElement $typeOrElement Type of the element as string or an instance of FormElement
- * @param string $name Name of the element
- * @param mixed $options Element options as key-value pairs
- *
- * @return $this
- *
- * @throws InvalidArgumentException If $typeOrElement is neither a string nor an instance of FormElement
- * or if $typeOrElement is a string and $name is not set
- * or if $typeOrElement is a string but type is unknown
- * or if $typeOrElement is an instance of FormElement but does not have a name
- */
public function addElement($typeOrElement, $name = null, $options = null)
{
if (is_string($typeOrElement)) {
@@ -157,6 +188,37 @@ trait FormElements
/** @var FormElement $element */
$element = new $class($name);
+ if ($element instanceof DecorableFormElement) {
+ $customDecoratorPaths = $this->elementDecoratorLoaderPaths;
+ $elementDecoratorChain = $element->getDecorators();
+ if (! empty($customDecoratorPaths)) {
+ if ($element instanceof DefaultFormElementDecoration) {
+ $element->addElementDecoratorLoaderPaths($customDecoratorPaths);
+ }
+
+ foreach ($customDecoratorPaths as $path) {
+ $elementDecoratorChain->addDecoratorLoader($path[0], $path[1] ?? '');
+ }
+ }
+
+ $defaultDecorators = $this->getDefaultElementDecorators();
+ if (
+ ! empty($defaultDecorators)
+ && ! $this->hasDefaultElementDecorator()
+ && empty($options['hidden'])
+ && ! $element instanceof HiddenElement
+ && $element->getAttributes()->get('hidden')->isEmpty()
+ ) {
+ if ($element instanceof DefaultFormElementDecoration) {
+ $element->setDefaultElementDecorators($defaultDecorators);
+ }
+
+ if (! isset($options['decorators'])) {
+ $elementDecoratorChain->addDecorators($defaultDecorators);
+ }
+ }
+ }
+
if ($options !== null) {
$element->addAttributes($options);
}
@@ -164,21 +226,18 @@ trait FormElements
return $element;
}
- /**
- * Register an element
- *
- * Registers the element for value and validation handling but does not add it to the render stack.
- *
- * @param FormElement $element
- *
- * @return $this
- *
- * @throws InvalidArgumentException If $element does not provide a name
- */
public function registerElement(FormElement $element)
{
$name = $element->getName();
+ // This check is required as the getEscapedName method is not implemented in
+ // the FormElement interface
+ if ($element instanceof BaseFormElement) {
+ $escapedName = $element->getEscapedName();
+ } else {
+ $escapedName = $name;
+ }
+
if ($name === null) {
throw new InvalidArgumentException(sprintf(
'%s expects the element to provide a name',
@@ -188,11 +247,13 @@ trait FormElements
$this->elements[$name] = $element;
- if (array_key_exists($name, $this->populatedValues)) {
- $element->setValue($this->populatedValues[$name][count($this->populatedValues[$name]) - 1]);
+ if (array_key_exists($escapedName, $this->populatedValues)) {
+ $element->setValue(
+ $this->populatedValues[$escapedName][count($this->populatedValues[$escapedName]) - 1]
+ );
if ($element instanceof ValueCandidates) {
- $element->setValueCandidates($this->populatedValues[$name]);
+ $element->setValueCandidates($this->populatedValues[$escapedName]);
}
}
@@ -206,6 +267,8 @@ trait FormElements
* Get whether a default element decorator exists
*
* @return bool
+ * @deprecated This is not of general use anymore. The new decorator implementation handles defaults entirely
+ * internally now. Use {@see getDefaultElementDecorators()} instead only if you absolutely have to.
*/
public function hasDefaultElementDecorator()
{
@@ -216,6 +279,7 @@ trait FormElements
* Get the default element decorator, if any
*
* @return FormElementDecorator|null
+ * @deprecated Use {@see getDefaultElementDecorators()} instead
*/
public function getDefaultElementDecorator()
{
@@ -233,12 +297,21 @@ trait FormElements
*
* @return $this
*
+ * @deprecated Use {@see setDefaultElementDecorators()} instead
* @throws InvalidArgumentException If $decorator is a string and can't be loaded from registered decorator loaders
* or if a decorator loader does not return an instance of
* {@link FormElementDecorator}
*/
public function setDefaultElementDecorator($decorator)
{
+ if (! empty($this->getDefaultElementDecorators())) {
+ throw new RuntimeException(sprintf(
+ 'Cannot use element decorators of type %s and legacy decorator of type %s together',
+ FormElementDecoration::class,
+ FormElementDecorator::class
+ ));
+ }
+
if ($decorator instanceof FormElementDecorator || $decorator instanceof DecoratorInterface) {
$this->defaultElementDecorator = $decorator;
} else {
@@ -269,16 +342,6 @@ trait FormElements
return $this;
}
- /**
- * Get the value of the element specified by name
- *
- * Returns $default if the element does not exist or has no value.
- *
- * @param string $name
- * @param mixed $default
- *
- * @return mixed
- */
public function getValue($name, $default = null)
{
if ($this->hasElement($name)) {
@@ -291,11 +354,6 @@ trait FormElements
return $default;
}
- /**
- * Get the values for all but ignored elements
- *
- * @return array Values as name-value pairs
- */
public function getValues()
{
$values = [];
@@ -308,17 +366,10 @@ trait FormElements
return $values;
}
- /**
- * Populate values of registered elements
- *
- * @param iterable $values Values as name-value pairs
- *
- * @return $this
- */
public function populate($values)
{
foreach ($values as $name => $value) {
- $this->populatedValues[$name][] = $value;
+ $this->populatedValues[Form::escapeReservedChars($name)][] = $value;
if ($this->hasElement($name)) {
$this->getElement($name)->setValue($value);
}
@@ -339,6 +390,7 @@ trait FormElements
*/
public function getPopulatedValue($name, $default = null)
{
+ $name = Form::escapeReservedChars($name);
return isset($this->populatedValues[$name])
? $this->populatedValues[$name][count($this->populatedValues[$name]) - 1]
: $default;
@@ -353,6 +405,7 @@ trait FormElements
*/
public function clearPopulatedValue($name)
{
+ $name = Form::escapeReservedChars($name);
if (isset($this->populatedValues[$name])) {
unset($this->populatedValues[$name]);
}
@@ -383,6 +436,7 @@ trait FormElements
* @param string $postfix Decorator name postfix, if any
*
* @return $this
+ * @deprecated Use {@see addElementDecoratorLoaderPaths()} instead
*/
public function addDecoratorLoader($namespace, $postfix = null)
{
@@ -454,6 +508,16 @@ trait FormElements
*/
protected function decorate(FormElement $element)
{
+ if ($element instanceof DecorableFormElement && $element->hasDecorators()) {
+ // new decorator implementation in use
+ $this->decoratedElements ??= new WeakMap();
+ if (! isset($this->decoratedElements[$element])) {
+ $this->decoratedElements[$element] = false;
+ }
+
+ return $this;
+ }
+
if ($this->hasDefaultElementDecorator()) {
$decorator = $this->getDefaultElementDecorator();
@@ -475,7 +539,7 @@ trait FormElements
public function isValidEvent($event)
{
return in_array($event, [
- Form::ON_SUCCESS,
+ Form::ON_SUBMIT,
Form::ON_SENT,
Form::ON_ERROR,
Form::ON_REQUEST,
@@ -484,18 +548,49 @@ trait FormElements
]);
}
- public function remove(ValidHtml $elementOrHtml)
+ public function removeElement(string|FormElement $element)
{
- if ($elementOrHtml instanceof FormElement) {
- if ($this->hasElement($elementOrHtml)) {
- $name = array_search($elementOrHtml, $this->elements, true);
+ if (is_string($element)) {
+ if (! $this->hasElement($element)) {
+ return $this;
+ }
+
+ $element = $this->getElement($element);
+ }
+
+ return $this->remove($element);
+ }
+
+ public function remove(ValidHtml $content)
+ {
+ if ($content instanceof FormElement) {
+ if ($this->hasElement($content)) {
+ if (isset($this->decoratedElements[$content])) {
+ unset($this->decoratedElements[$content]);
+ }
+
+ $name = array_search($content, $this->elements, true);
if ($name !== false) {
unset($this->elements[$name]);
}
}
}
- return parent::remove($elementOrHtml);
+ return parent::remove($content);
+ }
+
+ protected function beforeRender(): void
+ {
+ if ($this instanceof HtmlDocument) {
+ parent::beforeRender();
+ }
+
+ foreach ($this->decoratedElements ?? [] as $element => &$decorated) {
+ if (! $decorated) {
+ $element->applyDecoration();
+ $decorated = true;
+ }
+ }
}
/**
diff --git a/vendor/ipl/html/src/FormElement/RadioElement.php b/vendor/ipl/html/src/FormElement/RadioElement.php
index 831671c..39ce438 100644
--- a/vendor/ipl/html/src/FormElement/RadioElement.php
+++ b/vendor/ipl/html/src/FormElement/RadioElement.php
@@ -24,6 +24,14 @@ class RadioElement extends BaseFormElement
/** @var array Disabled radio options */
protected $disabledOptions = [];
+ protected function tag(): string
+ {
+ // In order to be able to decorate this element, we need to return a tag.
+ // If we'd have a distinct form element base implementation, that doesn't
+ // extend BaseHtmlElement, this wouldn't be necessary.
+ return 'bogus';
+ }
+
/**
* Set the options
*
@@ -101,6 +109,8 @@ class RadioElement extends BaseFormElement
protected function assemble()
{
+ // To avoid duplicate ids for options. Required for tests or if someone sets explicitly.
+ $this->getAttributes()->remove('id');
foreach ($this->options as $option) {
$radio = (new InputElement($this->getValueOfNameAttribute()))
->setType($this->type)
diff --git a/vendor/ipl/html/src/FormElement/SelectElement.php b/vendor/ipl/html/src/FormElement/SelectElement.php
index e6b4f21..cef7a8e 100644
--- a/vendor/ipl/html/src/FormElement/SelectElement.php
+++ b/vendor/ipl/html/src/FormElement/SelectElement.php
@@ -111,7 +111,7 @@ class SelectElement extends BaseFormElement
public function getNameAttribute()
{
- $name = $this->getName();
+ $name = $this->getEscapedName();
return $this->isMultiple() ? ($name . '[]') : $name;
}
diff --git a/vendor/ipl/html/src/FormElement/TextElement.php b/vendor/ipl/html/src/FormElement/TextElement.php
index 0e3423d..b650209 100644
--- a/vendor/ipl/html/src/FormElement/TextElement.php
+++ b/vendor/ipl/html/src/FormElement/TextElement.php
@@ -2,7 +2,43 @@
namespace ipl\Html\FormElement;
+use ipl\Html\Attributes;
+
class TextElement extends InputElement
{
protected $type = 'text';
+
+ /** @var ?string Placeholder text for the input */
+ protected ?string $placeholder = null;
+
+ /**
+ * Get the placeholder
+ *
+ * @return ?string
+ */
+ public function getPlaceholder(): ?string
+ {
+ return $this->placeholder;
+ }
+
+ /**
+ * Set the placeholder
+ *
+ * @param ?string $placeholder
+ *
+ * @return $this
+ */
+ public function setPlaceholder(?string $placeholder): self
+ {
+ $this->placeholder = $placeholder;
+
+ return $this;
+ }
+
+ protected function registerAttributeCallbacks(Attributes $attributes): void
+ {
+ parent::registerAttributeCallbacks($attributes);
+
+ $attributes->registerAttributeCallback('placeholder', [$this, 'getPlaceholder'], [$this, 'setPlaceholder']);
+ }
}
diff --git a/vendor/ipl/html/src/HtmlDocument.php b/vendor/ipl/html/src/HtmlDocument.php
index d9a153a..58fad73 100644
--- a/vendor/ipl/html/src/HtmlDocument.php
+++ b/vendor/ipl/html/src/HtmlDocument.php
@@ -4,6 +4,7 @@ namespace ipl\Html;
use Countable;
use InvalidArgumentException;
+use ipl\Html\Contract\MutableHtml;
use ipl\Html\Contract\Wrappable;
use ipl\Stdlib\Events;
use RuntimeException;
@@ -14,7 +15,7 @@ use Throwable;
*
* An HTML document is composed of a tree of HTML nodes, i.e. text nodes and HTML elements.
*/
-class HtmlDocument implements Countable, Wrappable
+class HtmlDocument implements Countable, Wrappable, MutableHtml
{
use Events;
@@ -27,14 +28,14 @@ class HtmlDocument implements Countable, Wrappable
/** @var bool Whether the document has been assembled */
protected $hasBeenAssembled = false;
- /** @var Wrappable Wrapper */
+ /** @var ?Wrappable Wrapper */
protected $wrapper;
- /** @var Wrappable Wrapped element */
- private $wrapped;
+ /** @var ?Wrappable Wrapped element */
+ private null|Wrappable $wrapped = null;
- /** @var HtmlDocument The currently responsible wrapper */
- private $renderedBy;
+ /** @var ?Wrappable The currently responsible wrapper */
+ private null|Wrappable $renderedBy = null;
/** @var ValidHtml[] Content */
private $content = [];
@@ -59,7 +60,7 @@ class HtmlDocument implements Countable, Wrappable
/**
* Consume the wrapped element
*
- * @return Wrappable
+ * @return ?Wrappable
*/
private function consumeWrapped()
{
@@ -69,11 +70,6 @@ class HtmlDocument implements Countable, Wrappable
return $wrapped;
}
- /**
- * Get the content
- *
- * return ValidHtml[]
- */
public function getContent()
{
return $this->content;
@@ -94,13 +90,6 @@ class HtmlDocument implements Countable, Wrappable
return $this;
}
- /**
- * Set content
- *
- * @param ValidHtml ...$content
- *
- * @return $this
- */
public function setHtmlContent(ValidHtml ...$content)
{
$this->content = [];
@@ -158,14 +147,6 @@ class HtmlDocument implements Countable, Wrappable
));
}
- /**
- * Insert Html after an existing Html node
- *
- * @param ValidHtml $newNode
- * @param ValidHtml $existingNode
- *
- * @return $this
- */
public function insertAfter(ValidHtml $newNode, ValidHtml $existingNode): self
{
$index = array_search($existingNode, $this->content, true);
@@ -180,14 +161,6 @@ class HtmlDocument implements Countable, Wrappable
return $this;
}
- /**
- * Insert Html after an existing Html node
- *
- * @param ValidHtml $newNode
- * @param ValidHtml $existingNode
- *
- * @return $this
- */
public function insertBefore(ValidHtml $newNode, ValidHtml $existingNode): self
{
$index = array_search($existingNode, $this->content);
@@ -216,13 +189,6 @@ class HtmlDocument implements Countable, Wrappable
return $this;
}
- /**
- * Add content
- *
- * @param ValidHtml ...$content
- *
- * @return $this
- */
public function addHtml(ValidHtml ...$content)
{
foreach ($content as $element) {
@@ -252,25 +218,15 @@ class HtmlDocument implements Countable, Wrappable
return $this;
}
- /**
- * Check whether the given element is a direct or indirect child of this document
- *
- * A direct child is one that is part of this document's content. An indirect child
- * is one that is part of a direct child's content (recursively).
- *
- * @param ValidHtml $element
- *
- * @return bool
- */
- public function contains(ValidHtml $element)
+ public function contains(ValidHtml $content)
{
- $key = spl_object_hash($element);
+ $key = spl_object_hash($content);
if (array_key_exists($key, $this->contentIndex)) {
return true;
}
foreach ($this->content as $child) {
- if ($child instanceof self && $child->contains($element)) {
+ if ($child instanceof self && $child->contains($content)) {
return true;
}
}
@@ -292,13 +248,6 @@ class HtmlDocument implements Countable, Wrappable
return $this;
}
- /**
- * Prepend content
- *
- * @param ValidHtml ...$content
- *
- * @return $this
- */
public function prependHtml(ValidHtml ...$content)
{
foreach (array_reverse($content) as $html) {
@@ -310,16 +259,9 @@ class HtmlDocument implements Countable, Wrappable
return $this;
}
- /**
- * Remove content
- *
- * @param ValidHtml $html
- *
- * @return $this
- */
- public function remove(ValidHtml $html)
+ public function remove(ValidHtml $content)
{
- $key = spl_object_hash($html);
+ $key = spl_object_hash($content);
if (array_key_exists($key, $this->contentIndex)) {
foreach ($this->contentIndex[$key] as $pos) {
unset($this->content[$pos]);
@@ -349,11 +291,6 @@ class HtmlDocument implements Countable, Wrappable
return $this;
}
- /**
- * Get whether the document is empty
- *
- * @return bool
- */
public function isEmpty()
{
$this->ensureAssembled();
@@ -442,7 +379,10 @@ class HtmlDocument implements Countable, Wrappable
$wrapper = $this->wrapper;
if (isset($this->renderedBy)) {
- if ($wrapper === $this->renderedBy || $wrapper->contains($this->renderedBy)) {
+ if (
+ $wrapper === $this->renderedBy
+ || ($wrapper instanceof self && $wrapper->contains($this->renderedBy))
+ ) {
// $this might be an intermediate wrapper that's already about to be rendered.
// In case of an element (referencing $this as a wrapper) that is a child of an
// outer wrapper, it is required to ignore $wrapper as otherwise it's a loop.
@@ -553,7 +493,7 @@ class HtmlDocument implements Countable, Wrappable
protected function isIntermediateWrapper(ValidHtml $element): bool
{
foreach ($this->content as $child) {
- if ($child instanceof self && $child->wrappedBy($element)) {
+ if ($child instanceof self && ($child->wrappedBy($element) || $child->isIntermediateWrapper($element))) {
return true;
}
}
@@ -561,9 +501,19 @@ class HtmlDocument implements Countable, Wrappable
return false;
}
+ /**
+ * Last call before rendering the document
+ *
+ * @return void
+ */
+ protected function beforeRender(): void
+ {
+ }
+
public function render()
{
$this->ensureAssembled();
+ $this->beforeRender();
if ($this->wrapper === null) {
return $this->renderUnwrapped();
} else {
diff --git a/vendor/ipl/orm/composer.json b/vendor/ipl/orm/composer.json
index 71f17de..83f7cde 100644
--- a/vendor/ipl/orm/composer.json
+++ b/vendor/ipl/orm/composer.json
@@ -10,7 +10,7 @@
],
"homepage": "https://github.com/Icinga/ipl-orm",
"require": {
- "php": ">=7.2",
+ "php": ">=8.2",
"ext-pdo": "*",
"ipl/sql": ">=0.7.0",
"ipl/stdlib": ">=0.12.0"
diff --git a/vendor/ipl/orm/src/Compat/FilterProcessor.php b/vendor/ipl/orm/src/Compat/FilterProcessor.php
index 361aabb..1b3aab9 100644
--- a/vendor/ipl/orm/src/Compat/FilterProcessor.php
+++ b/vendor/ipl/orm/src/Compat/FilterProcessor.php
@@ -9,6 +9,7 @@ use ipl\Orm\Exception\ValueConversionException;
use ipl\Orm\Query;
use ipl\Orm\Relation;
use ipl\Orm\UnionQuery;
+use ipl\Sql\Adapter\Pgsql;
use ipl\Sql\Filter\Exists;
use ipl\Sql\Filter\In;
use ipl\Sql\Filter\NotExists;
@@ -323,15 +324,17 @@ class FilterProcessor extends \ipl\Sql\Compat\FilterProcessor
$subQuerySelect = $subQuery->assembleSelect()->resetOrderBy();
if ($count !== null && ($negate || $filter instanceof Filter\All)) {
- $targetKeys = join(
- ',',
- array_values(
- $subQuery->getResolver()->qualifyColumns(
- (array) $subQuery->getModel()->getKeyName(),
- $subQuery->getModel()
- )
+ $targetKeys = array_values(
+ $subQuery->getResolver()->qualifyColumns(
+ (array) $subQuery->getModel()->getKeyName(),
+ $subQuery->getModel()
)
);
+ if (count($targetKeys) > 1 && $query->getDb()->getAdapter() instanceof Pgsql) {
+ $targetKeys = '(' . join(', ', $targetKeys) . ')';
+ } else {
+ $targetKeys = join(', ', $targetKeys);
+ }
$subQuerySelect->having(["COUNT(DISTINCT $targetKeys) >= ?" => $count]);
$subQuerySelect->groupBy(array_values($subQuerySelect->getColumns()));
diff --git a/vendor/ipl/orm/src/Relation/BelongsToMany.php b/vendor/ipl/orm/src/Relation/BelongsToMany.php
index aad4f03..fa69245 100644
--- a/vendor/ipl/orm/src/Relation/BelongsToMany.php
+++ b/vendor/ipl/orm/src/Relation/BelongsToMany.php
@@ -22,6 +22,9 @@ class BelongsToMany extends Relation
/** @var string Name of the join table or junction model class */
protected $throughClass;
+ /** @var ?string Alias for the join table or junction model class */
+ protected ?string $throughAlias = null;
+
/** @var Model The junction model */
protected $through;
@@ -55,6 +58,30 @@ class BelongsToMany extends Relation
return $this;
}
+ /**
+ * Get the alias for the join table or junction model class
+ *
+ * @return string
+ */
+ public function getThroughAlias(): string
+ {
+ return $this->throughAlias ?? $this->getThrough()->getTableAlias();
+ }
+
+ /**
+ * Set the alias for the join table or junction model class
+ *
+ * @param string $throughAlias
+ *
+ * @return $this
+ */
+ public function setThroughAlias(string $throughAlias): self
+ {
+ $this->throughAlias = $throughAlias;
+
+ return $this;
+ }
+
/**
* Get the junction model
*
@@ -179,7 +206,7 @@ class BelongsToMany extends Relation
$junctionClass = static::RELATION_CLASS;
$toJunction = (new $junctionClass())
- ->setName($junction->getTableAlias())
+ ->setName($this->getThroughAlias())
->setSource($source)
->setTarget($junction)
->setCandidateKey($this->extractKey($possibleCandidateKey))
diff --git a/vendor/ipl/orm/src/Resolver.php b/vendor/ipl/orm/src/Resolver.php
index a3b99b3..fd4f658 100644
--- a/vendor/ipl/orm/src/Resolver.php
+++ b/vendor/ipl/orm/src/Resolver.php
@@ -567,10 +567,9 @@ class Resolver
$resolvedRelations[$relationPath] = $relation;
if ($relation instanceof BelongsToMany) {
- $through = $relation->getThrough();
- $this->setAlias($through, join('_', array_merge(
+ $this->setAlias($relation->getThrough(), join('_', array_merge(
array_slice($segments, 0, -1),
- [$through->getTableAlias()]
+ [$relation->getThroughAlias()]
)));
}
diff --git a/vendor/ipl/scheduler/src/RRule.php b/vendor/ipl/scheduler/src/RRule.php
index bfad0e5..0251756 100644
--- a/vendor/ipl/scheduler/src/RRule.php
+++ b/vendor/ipl/scheduler/src/RRule.php
@@ -64,12 +64,13 @@ class RRule implements Frequency
* Construct a new rrule instance
*
* @param string|array $rule
+ * @param ?string $timezone
*
* @throws InvalidRRule
*/
- public function __construct($rule)
+ public function __construct($rule, ?string $timezone = null)
{
- $this->rrule = new RecurrRule($rule);
+ $this->rrule = new RecurrRule($rule, timezone: $timezone);
$this->frequency = $this->rrule->getFreqAsText();
$this->transformerConfig = new ArrayTransformerConfig();
$this->transformerConfig->setVirtualLimit(self::DEFAULT_LIMIT);
diff --git a/vendor/ipl/sql/src/Connection.php b/vendor/ipl/sql/src/Connection.php
index de84c72..9480fe7 100644
--- a/vendor/ipl/sql/src/Connection.php
+++ b/vendor/ipl/sql/src/Connection.php
@@ -8,6 +8,7 @@ use InvalidArgumentException;
use ipl\Sql\Contract\Adapter;
use ipl\Sql\Contract\Quoter;
use ipl\Stdlib\Plugins;
+use LogicException;
use PDO;
use PDOStatement;
@@ -438,6 +439,25 @@ class Connection implements Quoter
return $this->prepexec($insert);
}
+ /**
+ * Get the ID of the last inserted row
+ *
+ * @param ?string $name The name of the sequence object from which the ID should be returned.
+ *
+ * @throws LogicException If no connection to the database is established
+ * @return false|string
+ */
+ public function lastInsertId(?string $name = null): false|string
+ {
+ if ($this->pdo === null) {
+ throw new LogicException(
+ 'Cannot get last insert ID because no connection to the database is established.'
+ );
+ }
+
+ return $this->pdo->lastInsertId($name);
+ }
+
/**
* Update table rows with the specified data, optionally based on a given condition
*
diff --git a/vendor/ipl/sql/src/Test/SharedDatabases.php b/vendor/ipl/sql/src/Test/SharedDatabases.php
new file mode 100644
index 0000000..5c54fb2
--- /dev/null
+++ b/vendor/ipl/sql/src/Test/SharedDatabases.php
@@ -0,0 +1,175 @@
+
+ */
+ final public static function sharedDatabases(): array
+ {
+ self::initializeDatabases();
+
+ return self::$connections;
+ }
+
+ /**
+ * Get the current database connection
+ *
+ * @return Connection
+ * @throws RuntimeException if the connection cannot be retrieved
+ */
+ final protected function getConnection(): Connection
+ {
+ if (method_exists($this, 'getProvidedData')) {
+ $connections = $this->getProvidedData();
+ } elseif (method_exists($this, 'providedData')) {
+ $connections = $this->providedData();
+ } else {
+ throw new RuntimeException('Cannot get connection: Unsupported PHPUnit version?');
+ }
+
+ $connection = $connections[0];
+ if (! $connection instanceof Connection) {
+ throw new RuntimeException('Cannot get connection: Are all test cases using the same provider?');
+ }
+
+ return $connection;
+ }
+
+ /**
+ * Get the value of an environment variable
+ *
+ * @param string $name
+ *
+ * @return string
+ *
+ * @throws RuntimeException if the environment variable is not set
+ */
+ final protected static function getEnvironmentVariable(string $name): string
+ {
+ $value = getenv($name);
+ if ($value === false) {
+ throw new RuntimeException("Environment variable $name is not set");
+ }
+
+ return $value;
+ }
+
+ /**
+ * Get the connection configuration for the test database
+ *
+ * @param string $driver
+ *
+ * @return Config
+ */
+ final protected static function getConnectionConfig(string $driver): Config
+ {
+ return new Config([
+ 'db' => $driver,
+ 'host' => self::getEnvironmentVariable(strtoupper($driver) . '_TESTDB_HOST'),
+ 'port' => self::getEnvironmentVariable(strtoupper($driver) . '_TESTDB_PORT'),
+ 'username' => self::getEnvironmentVariable(strtoupper($driver) . '_TESTDB_USER'),
+ 'password' => self::getEnvironmentVariable(strtoupper($driver) . '_TESTDB_PASSWORD'),
+ 'dbname' => self::getEnvironmentVariable(strtoupper($driver) . '_TESTDB')
+ ]);
+ }
+
+ /**
+ * Create a database connection
+ *
+ * @param string $driver
+ *
+ * @return Connection
+ *
+ * @internal Only the trait itself should call this method
+ */
+ final protected static function connectToDatabase(string $driver): Connection
+ {
+ return new Connection(self::getConnectionConfig($driver));
+ }
+
+ /**
+ * Set up the database connections
+ *
+ * @return void
+ *
+ * @internal Only the trait itself should call this method
+ */
+ final protected static function initializeDatabases(): void
+ {
+ foreach (self::SUPPORTED_ADAPTERS as $driver) {
+ if (isset($_SERVER[strtoupper($driver) . '_TESTDB'])) {
+ if (! isset(self::$connections[$driver])) {
+ self::$connections[$driver] = [self::connectToDatabase($driver)];
+ static::tearDownSchema(self::$connections[$driver][0], $driver);
+ static::setUpSchema(self::$connections[$driver][0], $driver);
+ }
+ }
+ }
+ }
+}
diff --git a/vendor/ipl/sql/src/Test/TestConnection.php b/vendor/ipl/sql/src/Test/TestConnection.php
index 981696b..913070f 100644
--- a/vendor/ipl/sql/src/Test/TestConnection.php
+++ b/vendor/ipl/sql/src/Test/TestConnection.php
@@ -13,4 +13,53 @@ class TestConnection extends Connection
{
$this->adapter = new TestAdapter();
}
+
+ public function connect()
+ {
+ return $this;
+ }
+
+ public function beginTransaction()
+ {
+ throw new \LogicException('Transactions are not supported by the test connection');
+ }
+
+ public function commitTransaction()
+ {
+ throw new \LogicException('Transactions are not supported by the test connection');
+ }
+
+ public function rollbackTransaction()
+ {
+ throw new \LogicException('Transactions are not supported by the test connection');
+ }
+
+ public function prepexec($stmt, $values = null)
+ {
+ if (PHP_MAJOR_VERSION >= 8) {
+ return new class extends \PDOStatement {
+ public function getIterator(): \Iterator
+ {
+ return new \ArrayIterator([]);
+ }
+
+ public function setFetchMode($mode, ...$args): bool
+ {
+ return true;
+ }
+ };
+ } else {
+ return new class extends \PDOStatement {
+ public function getIterator(): \Iterator
+ {
+ return new \ArrayIterator([]);
+ }
+
+ public function setFetchMode($mode, $params = null): bool
+ {
+ return true;
+ }
+ };
+ }
+ }
}
diff --git a/vendor/ipl/validator/composer.json b/vendor/ipl/validator/composer.json
index 51ba68d..260b7d9 100644
--- a/vendor/ipl/validator/composer.json
+++ b/vendor/ipl/validator/composer.json
@@ -10,7 +10,7 @@
"ext-openssl": "*",
"ipl/stdlib": ">=0.12.0",
"ipl/i18n": ">=0.2.0",
- "psr/http-message": "~1.0"
+ "psr/http-message": "^1.1"
},
"autoload": {
"psr-4": {
@@ -23,6 +23,8 @@
}
},
"require-dev": {
- "guzzlehttp/psr7": "^1"
+ "guzzlehttp/psr7": "^1",
+ "ipl/stdlib": "dev-main",
+ "ipl/i18n": "dev-main"
}
}
diff --git a/vendor/ipl/validator/src/BetweenValidator.php b/vendor/ipl/validator/src/BetweenValidator.php
index 3d7faaf..c8dc026 100644
--- a/vendor/ipl/validator/src/BetweenValidator.php
+++ b/vendor/ipl/validator/src/BetweenValidator.php
@@ -12,10 +12,10 @@ class BetweenValidator extends BaseValidator
{
use Translation;
- /** @var mixed Min value */
+ /** @var int|float Min value */
protected $min;
- /** @var mixed Max value */
+ /** @var int|float Max value */
protected $max;
/**
@@ -33,14 +33,14 @@ class BetweenValidator extends BaseValidator
*
* Required options:
*
- * - min: (scalar) Minimum border
- * - max: (scalar) Maximum border
+ * - min: (int|float) Minimum border
+ * - max: (int|float) Maximum border
*
* Optional options:
*
* - inclusive: (bool) Whether inclusive border values, default true
*
- * @param array $options
+ * @param array{min: int|float, max: int|float, inclusive?: bool} $options
*
* @throws Exception When required option is missing
*/
@@ -58,7 +58,7 @@ class BetweenValidator extends BaseValidator
/**
* Return the min option
*
- * @return mixed
+ * @return int|float
*/
public function getMin()
{
@@ -68,7 +68,7 @@ class BetweenValidator extends BaseValidator
/**
* Set the min option
*
- * @param mixed $min
+ * @param int|float $min
*
* @return $this
*/
@@ -82,7 +82,7 @@ class BetweenValidator extends BaseValidator
/**
* Return the max option
*
- * @return mixed
+ * @return int|float
*/
public function getMax()
{
@@ -92,7 +92,7 @@ class BetweenValidator extends BaseValidator
/**
* Set the max option
*
- * @param mixed $max
+ * @param int|float $max
*
* @return $this
*/
@@ -120,14 +120,19 @@ class BetweenValidator extends BaseValidator
*
* @return $this
*/
- public function setInclusive($inclusive = true): self
+ public function setInclusive(bool $inclusive = true): self
{
- $this->inclusive = (bool) $inclusive;
+ $this->inclusive = $inclusive;
return $this;
}
- public function isValid($value)
+ /**
+ * @param int|float $value
+ *
+ * @return bool
+ */
+ public function isValid($value): bool
{
// Multiple isValid() calls must not stack validation messages
$this->clearMessages();
diff --git a/vendor/ipl/validator/src/CallbackValidator.php b/vendor/ipl/validator/src/CallbackValidator.php
index 611a45e..29b8e7f 100644
--- a/vendor/ipl/validator/src/CallbackValidator.php
+++ b/vendor/ipl/validator/src/CallbackValidator.php
@@ -35,7 +35,7 @@ class CallbackValidator extends BaseValidator
$this->callback = $callback;
}
- public function isValid($value)
+ public function isValid($value): bool
{
// Multiple isValid() calls must not stack validation messages
$this->clearMessages();
diff --git a/vendor/ipl/validator/src/CidrValidator.php b/vendor/ipl/validator/src/CidrValidator.php
index 32c1162..248c589 100644
--- a/vendor/ipl/validator/src/CidrValidator.php
+++ b/vendor/ipl/validator/src/CidrValidator.php
@@ -12,6 +12,10 @@ class CidrValidator extends BaseValidator
{
use Translation;
+ /**
+ * @param string $value
+ * @return bool
+ */
public function isValid($value): bool
{
$this->clearMessages();
diff --git a/vendor/ipl/validator/src/DateTimeValidator.php b/vendor/ipl/validator/src/DateTimeValidator.php
index 1e35d61..602724b 100644
--- a/vendor/ipl/validator/src/DateTimeValidator.php
+++ b/vendor/ipl/validator/src/DateTimeValidator.php
@@ -23,9 +23,9 @@ class DateTimeValidator extends BaseValidator
*
* @param bool $local
*/
- public function __construct($local = true)
+ public function __construct(bool $local = true)
{
- $this->local = (bool) $local;
+ $this->local = $local;
}
/**
@@ -35,7 +35,7 @@ class DateTimeValidator extends BaseValidator
*
* @return bool
*/
- public function isValid($value)
+ public function isValid($value): bool
{
// Multiple isValid() calls must not stack validation messages
$this->clearMessages();
diff --git a/vendor/ipl/validator/src/DeferredInArrayValidator.php b/vendor/ipl/validator/src/DeferredInArrayValidator.php
index 55b9b83..fa0ba5d 100644
--- a/vendor/ipl/validator/src/DeferredInArrayValidator.php
+++ b/vendor/ipl/validator/src/DeferredInArrayValidator.php
@@ -15,7 +15,7 @@ class DeferredInArrayValidator extends InArrayValidator
*
* **Required parameter:**
*
- * - `callback`: (`callable`) The callback to create haystack
+ * - `callback`: (`callable`) The callback to create the haystack
*
* **Optional parameter:**
*
@@ -23,8 +23,8 @@ class DeferredInArrayValidator extends InArrayValidator
*
* * `strict`: (`bool`) Whether the types of the needle in the haystack should also match, default `false`
*
- * @param callable $callback Validation callback
- * @param array $options
+ * @param callable $callback The callback to create the haystack
+ * @param array{haystack?: mixed[], strict?: bool} $options
*/
public function __construct(callable $callback, array $options = [])
{
diff --git a/vendor/ipl/validator/src/EmailAddressValidator.php b/vendor/ipl/validator/src/EmailAddressValidator.php
index 52c3697..e9dc2a7 100644
--- a/vendor/ipl/validator/src/EmailAddressValidator.php
+++ b/vendor/ipl/validator/src/EmailAddressValidator.php
@@ -40,7 +40,7 @@ class EmailAddressValidator extends BaseValidator
* 'mx' => If an MX check should be enabled, boolean
* 'deep' => If a deep MX check should be enabled, boolean
*
- * @param array $options
+ * @param array{max?: bool, deep?: bool} $options
*
* @throws Exception
*/
@@ -266,7 +266,8 @@ class EmailAddressValidator extends BaseValidator
//decode IDN domain name
$decodedHostname = idn_to_ascii($hostname, 0, INTL_IDNA_VARIANT_UTS46);
- $result = getmxrr($decodedHostname, $mxHosts);
+ $result = $decodedHostname && getmxrr($decodedHostname, $mxHosts);
+
if (! $result) {
$this->addMessage(sprintf(
$this->translate("'%s' does not appear to have a valid MX record for the email address '%s'"),
diff --git a/vendor/ipl/validator/src/FileValidator.php b/vendor/ipl/validator/src/FileValidator.php
index 8c5b90e..bc435cc 100644
--- a/vendor/ipl/validator/src/FileValidator.php
+++ b/vendor/ipl/validator/src/FileValidator.php
@@ -34,6 +34,8 @@ class FileValidator extends BaseValidator
* - maxSize: (int) Maximum allowed file size, by default no limit
* - maxFileNameLength: (int) Maximum allowed file name length, by default no limit
* - mimeType: (array) Allowed mime types, by default no restriction
+ *
+ * @param array{minSize?: int, maxSize?: int, maxFileNameLength?: int, mimeType?: string[]} $options
*/
public function __construct(array $options = [])
{
@@ -160,7 +162,11 @@ class FileValidator extends BaseValidator
return $this;
}
- public function isValid($value)
+ /**
+ * @param UploadedFileInterface|UploadedFileInterface[] $value
+ * @return bool
+ */
+ public function isValid($value): bool
{
// Multiple isValid() calls must not stack validation messages
$this->clearMessages();
@@ -185,7 +191,7 @@ class FileValidator extends BaseValidator
if ($this->getMaxSize() && $file->getSize() > $this->getMaxSize()) {
$this->addMessage(sprintf(
$this->translate('File %s is bigger than the allowed maximum size of %d'),
- $file->getClientFileName(),
+ $file->getClientFilename(),
$this->getMaxSize()
));
@@ -195,7 +201,7 @@ class FileValidator extends BaseValidator
if ($this->getMinSize() && $file->getSize() < $this->getMinSize()) {
$this->addMessage(sprintf(
$this->translate('File %s is smaller than the minimum required size of %d'),
- $file->getClientFileName(),
+ $file->getClientFilename(),
$this->getMinSize()
));
@@ -205,7 +211,7 @@ class FileValidator extends BaseValidator
if ($this->getMaxFileNameLength()) {
$strValidator = new StringLengthValidator(['max' => $this->getMaxFileNameLength()]);
- if (! $strValidator->isValid($file->getClientFilename())) {
+ if (! $strValidator->isValid($file->getClientFilename() ?? '')) {
$this->addMessage(sprintf(
$this->translate('File name is longer than the allowed length of %d characters.'),
$this->maxFileNameLength
@@ -217,26 +223,29 @@ class FileValidator extends BaseValidator
if (! empty($this->getAllowedMimeTypes())) {
$hasAllowedMimeType = false;
- foreach ($this->getAllowedMimeTypes() as $type) {
- $fileMimetype = $file->getClientMediaType();
- if (($pos = strpos($type, '/*')) !== false) { // image/*
- $typePrefix = substr($type, 0, $pos);
- if (Str::startsWith($fileMimetype, $typePrefix)) {
+ $fileMimetype = $file->getClientMediaType();
+
+ if ($fileMimetype) {
+ foreach ($this->getAllowedMimeTypes() as $type) {
+ if (($pos = strpos($type, '/*')) !== false) { // image/*
+ $typePrefix = substr($type, 0, $pos);
+ if (Str::startsWith($fileMimetype, $typePrefix)) {
+ $hasAllowedMimeType = true;
+ break;
+ }
+ } elseif ($fileMimetype === $type) { // image/png
$hasAllowedMimeType = true;
break;
}
- } elseif ($fileMimetype === $type) { // image/png
- $hasAllowedMimeType = true;
- break;
}
}
if (! $hasAllowedMimeType) {
$this->addMessage(sprintf(
$this->translate('File %s is of type %s. Only %s allowed.'),
- $file->getClientFileName(),
+ $file->getClientFilename(),
$file->getClientMediaType(),
- implode(', ', $this->allowedMimeTypes)
+ implode(', ', $this->allowedMimeTypes ?? [])
));
$isValid = false;
diff --git a/vendor/ipl/validator/src/GreaterThanValidator.php b/vendor/ipl/validator/src/GreaterThanValidator.php
index e5de3d0..177fa42 100644
--- a/vendor/ipl/validator/src/GreaterThanValidator.php
+++ b/vendor/ipl/validator/src/GreaterThanValidator.php
@@ -11,14 +11,16 @@ class GreaterThanValidator extends BaseValidator
{
use Translation;
- /** @var mixed Comparison value for greater than */
+ /** @var int|float Comparison value for greater than */
protected $min;
/**
* Create a new GreaterThanValidator
*
* Optional options:
- * - min: (scalar) Comparison value for greater than, default 0
+ * - min: (int|float) Comparison value for greater than, default 0
+ *
+ * @param array{min?: int|float} $options
*/
public function __construct(array $options = [])
{
@@ -28,7 +30,7 @@ class GreaterThanValidator extends BaseValidator
/**
* Get the min option
*
- * @return mixed
+ * @return int|float
*/
public function getMin()
{
@@ -38,7 +40,7 @@ class GreaterThanValidator extends BaseValidator
/**
* Set the min option
*
- * @param mixed $min
+ * @param int|float $min
*
* @return $this
*/
@@ -49,7 +51,12 @@ class GreaterThanValidator extends BaseValidator
return $this;
}
- public function isValid($value)
+ /**
+ * @param int|float $value
+ *
+ * @return bool
+ */
+ public function isValid($value): bool
{
// Multiple isValid() calls must not stack validation messages
$this->clearMessages();
diff --git a/vendor/ipl/validator/src/HostnameValidator.php b/vendor/ipl/validator/src/HostnameValidator.php
index 3bb9b66..8c658d0 100644
--- a/vendor/ipl/validator/src/HostnameValidator.php
+++ b/vendor/ipl/validator/src/HostnameValidator.php
@@ -18,7 +18,7 @@ class HostnameValidator extends BaseValidator
*
* @return boolean
*/
- public function isValid($value)
+ public function isValid($value): bool
{
$this->clearMessages();
@@ -26,7 +26,7 @@ class HostnameValidator extends BaseValidator
if (filter_var($asciiHostname, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME) === false) {
$this->addMessage(sprintf(
$this->translate("%s is not a valid host name."),
- $value ?? ''
+ $value
));
return false;
diff --git a/vendor/ipl/validator/src/InArrayValidator.php b/vendor/ipl/validator/src/InArrayValidator.php
index f8c18ef..f3e67e7 100644
--- a/vendor/ipl/validator/src/InArrayValidator.php
+++ b/vendor/ipl/validator/src/InArrayValidator.php
@@ -11,7 +11,7 @@ class InArrayValidator extends BaseValidator
{
use Translation;
- /** @var array The array */
+ /** @var ?mixed[] The array */
protected $haystack;
/** @var bool Whether the types of the needle in the haystack should also match */
@@ -25,7 +25,7 @@ class InArrayValidator extends BaseValidator
* * `haystack`: (`array`) The array
* * `strict`: (`bool`) Whether the types of the needle in the haystack should also match, default `false`
*
- * @param array $options
+ * @param array{haystack?: mixed[], strict?: bool} $options
*/
public function __construct(array $options = [])
{
@@ -39,7 +39,7 @@ class InArrayValidator extends BaseValidator
/**
* Get the haystack
*
- * @return array
+ * @return mixed[]
*/
public function getHaystack(): array
{
@@ -49,7 +49,7 @@ class InArrayValidator extends BaseValidator
/**
* Set the haystack
*
- * @param array $haystack
+ * @param mixed[] $haystack
*
* @return $this
*/
@@ -84,7 +84,7 @@ class InArrayValidator extends BaseValidator
return $this;
}
- public function isValid($value)
+ public function isValid($value): bool
{
// Multiple isValid() calls must not stack validation messages
$this->clearMessages();
@@ -110,9 +110,9 @@ class InArrayValidator extends BaseValidator
/**
* Get the values from the specified array that are not present in the haystack
*
- * @param array $values
+ * @param mixed[] $values
*
- * @return array Values not found in the haystack
+ * @return mixed[] Values not found in the haystack
*/
protected function findInvalid(array $values = []): array
{
diff --git a/vendor/ipl/validator/src/LessThanValidator.php b/vendor/ipl/validator/src/LessThanValidator.php
index 68e3daf..db80e1a 100644
--- a/vendor/ipl/validator/src/LessThanValidator.php
+++ b/vendor/ipl/validator/src/LessThanValidator.php
@@ -11,14 +11,16 @@ class LessThanValidator extends BaseValidator
{
use Translation;
- /** @var mixed Comparison value for less than */
+ /** @var int|float Comparison value for less than */
protected $max;
/**
* Create a new LessThanValidator
*
* Optional options:
- * - max: (int) Comparison value for less than, default 0
+ * - max: (int|float) Comparison value for less than, default 0
+ *
+ * @param array{max?: int|float} $options
*/
public function __construct(array $options = [])
{
@@ -28,7 +30,7 @@ class LessThanValidator extends BaseValidator
/**
* Get the max option
*
- * @return mixed
+ * @return int|float
*/
public function getMax()
{
@@ -38,7 +40,7 @@ class LessThanValidator extends BaseValidator
/**
* Set the max option
*
- * @param mixed $max
+ * @param int|float $max
*
* @return $this
*/
@@ -49,7 +51,12 @@ class LessThanValidator extends BaseValidator
return $this;
}
- public function isValid($value)
+ /**
+ * @param int|float $value
+ *
+ * @return bool
+ */
+ public function isValid($value): bool
{
// Multiple isValid() calls must not stack validation messages
$this->clearMessages();
diff --git a/vendor/ipl/validator/src/PrivateKeyValidator.php b/vendor/ipl/validator/src/PrivateKeyValidator.php
index b629398..a207170 100644
--- a/vendor/ipl/validator/src/PrivateKeyValidator.php
+++ b/vendor/ipl/validator/src/PrivateKeyValidator.php
@@ -11,7 +11,12 @@ class PrivateKeyValidator extends BaseValidator
{
use Translation;
- public function isValid($value)
+ /**
+ * @param string $value
+ *
+ * @return bool
+ */
+ public function isValid($value): bool
{
// Multiple isValid() calls must not stack validation messages
$this->clearMessages();
diff --git a/vendor/ipl/validator/src/StringLengthValidator.php b/vendor/ipl/validator/src/StringLengthValidator.php
index 57df1eb..d4dd44b 100644
--- a/vendor/ipl/validator/src/StringLengthValidator.php
+++ b/vendor/ipl/validator/src/StringLengthValidator.php
@@ -13,10 +13,10 @@ class StringLengthValidator extends BaseValidator
{
use Translation;
- /** @var mixed Minimum required length */
+ /** @var int Minimum required length */
protected $min;
- /** @var mixed Maximum required length */
+ /** @var ?int Maximum required length */
protected $max;
/** @var ?string Encoding to use */
@@ -26,9 +26,11 @@ class StringLengthValidator extends BaseValidator
* Create a new StringLengthValidator
*
* Optional options:
- * - min: (scalar) Minimum required string length, default 0
- * - max: (scalar) Maximum required string length, default null
- * - encoding: (string) Encoding type, default null
+ * - min: (int) Minimum required string length, default 0
+ * - max: (int) Maximum required string length, default none
+ * - encoding: (string) Encoding type, default none
+ *
+ * @param array{min?: int, max?: int, encoding?: string} $options
*/
public function __construct(array $options = [])
{
@@ -41,9 +43,9 @@ class StringLengthValidator extends BaseValidator
/**
* Get the minimum required string length
*
- * @return mixed
+ * @return int
*/
- public function getMin()
+ public function getMin(): int
{
return $this->min;
}
@@ -51,13 +53,13 @@ class StringLengthValidator extends BaseValidator
/**
* Set the minimum required string length
*
- * @param mixed $min
+ * @param int $min
*
* @return $this
*
* @throws LogicException When the $min is greater than the $max value
*/
- public function setMin($min): self
+ public function setMin(int $min): self
{
if ($this->getMax() !== null && $min > $this->getMax()) {
throw new LogicException(
@@ -77,9 +79,9 @@ class StringLengthValidator extends BaseValidator
/**
* Get the maximum required string length
*
- * @return mixed
+ * @return ?int
*/
- public function getMax()
+ public function getMax(): ?int
{
return $this->max;
}
@@ -87,13 +89,13 @@ class StringLengthValidator extends BaseValidator
/**
* Set the minimum required string length
*
- * @param mixed $max
+ * @param ?int $max
*
* @return $this
*
* @throws LogicException When the $min is greater than the $max value
*/
- public function setMax($max): self
+ public function setMax(?int $max): self
{
if ($max !== null && $this->getMin() > $max) {
throw new LogicException(
@@ -143,7 +145,12 @@ class StringLengthValidator extends BaseValidator
return $this;
}
- public function isValid($value)
+ /**
+ * @param string $value
+ *
+ * @return bool
+ */
+ public function isValid($value): bool
{
// Multiple isValid() calls must not stack validation messages
$this->clearMessages();
diff --git a/vendor/ipl/validator/src/ValidatorChain.php b/vendor/ipl/validator/src/ValidatorChain.php
index 2860a12..8f0b9f3 100644
--- a/vendor/ipl/validator/src/ValidatorChain.php
+++ b/vendor/ipl/validator/src/ValidatorChain.php
@@ -15,6 +15,7 @@ use UnexpectedValueException;
use function ipl\Stdlib\get_php_type;
+/** @implements IteratorAggregate */
class ValidatorChain implements Countable, IteratorAggregate, Validator
{
use Messages;
@@ -23,10 +24,10 @@ class ValidatorChain implements Countable, IteratorAggregate, Validator
/** Default priority at which validators are added */
const DEFAULT_PRIORITY = 1;
- /** @var PriorityQueue Validator chain */
+ /** @var PriorityQueue Validator chain */
protected $validators;
- /** @var SplObjectStorage Validators that break the chain on failure */
+ /** @var SplObjectStorage Validators that break the chain on failure */
protected $validatorsThatBreakTheChain;
/**
@@ -43,7 +44,7 @@ class ValidatorChain implements Countable, IteratorAggregate, Validator
/**
* Get the validators that break the chain
*
- * @return SplObjectStorage
+ * @return SplObjectStorage
*/
public function getValidatorsThatBreakTheChain()
{
@@ -76,7 +77,7 @@ class ValidatorChain implements Countable, IteratorAggregate, Validator
/**
* Add the validators from the given validator specification to the chain
*
- * @param iterable $validators
+ * @param static|Traversable $validators
*
* @return $this
*
@@ -149,7 +150,7 @@ class ValidatorChain implements Countable, IteratorAggregate, Validator
*
* @return $this
*/
- public function addValidatorLoader($namespace, $postfix = null)
+ public function addValidatorLoader($namespace, $postfix = '')
{
$this->addPluginLoader('validator', $namespace, $postfix);
@@ -221,6 +222,10 @@ class ValidatorChain implements Countable, IteratorAggregate, Validator
{
$validatorsThatBreakTheChain = $validatorChain->getValidatorsThatBreakTheChain();
+ /**
+ * @var int $priority
+ * @var Validator $validator
+ */
foreach ($validatorChain->validators->yieldAll() as $priority => $validator) {
$this->add($validator, $validatorsThatBreakTheChain->contains($validator), $priority);
}
@@ -236,11 +241,14 @@ class ValidatorChain implements Countable, IteratorAggregate, Validator
/**
* Export the chain as array
*
- * @return array
+ * @return Validator[]
*/
public function toArray()
{
- return array_values(iterator_to_array($this));
+ /** @var Validator[] $validators */
+ $validators = iterator_to_array($this);
+
+ return array_values($validators);
}
public function count(): int
@@ -251,7 +259,7 @@ class ValidatorChain implements Countable, IteratorAggregate, Validator
/**
* Get an iterator for traversing the validators
*
- * @return Validator[]|PriorityQueue
+ * @return PriorityQueue
*/
public function getIterator(): Traversable
{
@@ -259,7 +267,7 @@ class ValidatorChain implements Countable, IteratorAggregate, Validator
return clone $this->validators;
}
- public function isValid($value)
+ public function isValid($value): bool
{
$this->clearMessages();
diff --git a/vendor/ipl/validator/src/X509CertValidator.php b/vendor/ipl/validator/src/X509CertValidator.php
index 7dfc4f7..0fc9677 100644
--- a/vendor/ipl/validator/src/X509CertValidator.php
+++ b/vendor/ipl/validator/src/X509CertValidator.php
@@ -11,7 +11,11 @@ class X509CertValidator extends BaseValidator
{
use Translation;
- public function isValid($value)
+ /**
+ * @param String $value
+ * @return bool
+ */
+ public function isValid($value): bool
{
// Multiple isValid() calls must not stack validation messages
$this->clearMessages();
diff --git a/vendor/ipl/web/asset/static/font/icinga-icons/selection.json b/vendor/ipl/web/asset/static/font/icinga-icons/selection.json
index 015faf0..b97abba 100644
--- a/vendor/ipl/web/asset/static/font/icinga-icons/selection.json
+++ b/vendor/ipl/web/asset/static/font/icinga-icons/selection.json
@@ -1 +1 @@
-{"IcoMoonType":"selection","icons":[{"icon":{"paths":["M64 0h896c35.328 0 64 28.672 64 64v640c0 35.328-28.672 64-64 64h-350.72v-64h350.72v-640h-896v640h33.28v64h-33.28c-35.328 0-64-28.672-64-64v-640c0-35.328 28.672-64 64-64z","M576.048 481.122c0 123.698-100.277 223.976-223.976 223.976s-223.976-100.277-223.976-223.976c0-123.698 100.277-223.976 223.976-223.976s223.976 100.277 223.976 223.976z","M511.488 720.896l64 303.104-224.32-128-223.168 128 64-303.488c45.76 30.656 100.8 48.576 160 48.576 58.944 0 113.792-17.728 159.488-48.192z","M896 192c0-16.96-6.784-33.28-18.752-45.248-12.032-12.032-28.288-18.752-45.248-18.752-71.040 0-185.024 0-256 0-17.024 0-33.28 6.72-45.248 18.752-12.032 11.968-18.752 28.288-18.752 45.248s6.72 33.28 18.752 45.248c11.968 12.032 28.224 18.752 45.248 18.752 70.976 0 184.96 0 256 0 16.96 0 33.216-6.72 45.248-18.752 11.968-11.968 18.752-28.288 18.752-45.248z","M896 384c0-16.96-6.784-33.28-18.752-45.248-12.032-12.032-28.288-18.752-45.248-18.752-71.040 0-57.024 0-128 0-17.024 0-33.28 6.72-45.248 18.752-12.032 11.968-18.752 28.288-18.752 45.248s6.72 33.28 18.752 45.248c11.968 12.032 28.224 18.752 45.248 18.752 70.976 0 56.96 0 128 0 16.96 0 33.216-6.72 45.248-18.752 11.968-11.968 18.752-28.288 18.752-45.248z"],"attrs":[],"grid":0,"tags":["certificate"]},"attrs":[],"properties":{"order":18,"id":11,"name":"certificate","prevSize":32,"code":59654},"setIdx":0,"setId":1,"iconIdx":0},{"icon":{"paths":["M7.232 90.496c11.776-24.896 36.672-40.704 64.192-40.704h768c27.584 0 52.48 15.808 64.192 40.704s8.192 54.208-9.216 75.52l-189.376 231.488c-142.592 29.312-249.6 155.392-249.6 306.496 0 48.704 11.2 94.912 31.104 136-2.816-1.408-5.696-3.2-8.32-5.184l-113.792-85.312c-14.4-10.688-22.784-27.52-22.784-45.504v-140.608l-325.312-397.504c-17.216-21.184-20.992-50.688-9.088-75.392z","M1024 705.024c-2.176 72.512-27.456 132.992-75.84 181.504-48.384 48.576-108.672 73.344-180.992 74.496-72.256-1.152-132.288-25.92-180.096-74.496-47.808-48.512-72.832-108.992-75.072-181.504 2.24-72.512 27.264-133.056 75.072-181.568s107.84-73.344 180.096-74.432c72.32 1.088 132.608 25.92 180.992 74.432s73.664 109.056 75.84 181.568zM966.144 581.248c-0.512-0.704-1.088-1.344-1.728-1.92-22.656-22.72-59.52-22.72-82.176 0l-80.448 80.32-33.024 76.608c0 0-25.6-65.728-25.6-65.728l-29.312-29.312c-22.656-22.656-59.52-22.656-82.176 0-22.72 22.72-22.72 59.52 0 82.24l94.272 94.272c11.2 11.2 25.856 16.832 40.512 16.96 0.448 0 0.896 0 1.28 0 14.656-0.192 29.248-5.824 40.384-16.96l156.224-156.224c22.016-22.016 22.656-57.472 1.792-80.256z"],"attrs":[],"grid":0,"tags":["filter-check-circle"]},"attrs":[],"properties":{"order":15,"id":10,"name":"filter-check-circle","prevSize":32,"code":59659},"setIdx":0,"setId":1,"iconIdx":1},{"icon":{"paths":["M177.038 607.479c-5.88 0.539-12.299 0.833-19.306 0.833-22.54 0-43.317-4.018-62.378-12.103-19.061-8.036-35.672-19.453-49.883-34.202-14.259-14.749-25.382-32.34-33.418-52.725s-12.103-43.072-12.103-68.013c0-24.941 4.165-47.727 12.495-68.405s19.6-38.22 33.81-52.725c14.21-14.504 30.968-25.48 50.324-33.026 19.306-7.497 40.23-11.27 62.77-11.27 20.384 0 40.671 3.92 60.761 11.711 20.139 7.742 36.358 19.159 48.707 34.202l-48.266 52.333c-6.468-10.241-15.043-17.591-25.774-22.148s-22.001-6.86-33.81-6.86c-11.809 0-22.932 2.401-33.418 7.252-10.437 4.851-19.453 11.515-26.95 20.139-7.497 8.575-13.279 18.767-17.297 30.576s-6.076 24.696-6.076 38.613c0 13.965 2.058 26.999 6.076 39.054 4.018 12.103 9.8 22.295 17.297 30.576 7.497 8.33 16.219 14.896 26.166 19.747 9.898 4.802 21.070 7.252 33.369 7.252 13.965 0 26.313-2.989 37.044-8.869 8.575-4.851 15.827-11.025 21.756-18.522l-41.896 96.58z","M484.864 594.112l-18.752-49.408h-123.2l-23.296 63.616h-82.944l132.8-321.984h74.88l90.688 222.4c-21.632 25.92-38.336 54.336-50.176 85.376zM405.696 372.48l-40.192 110.272h79.68l-39.488-110.272z","M1024 705.024c-2.176 72.512-27.456 132.992-75.84 181.504-48.384 48.576-108.672 73.344-180.992 74.496-72.256-1.152-132.288-25.92-180.096-74.496-47.808-48.512-72.832-108.992-75.072-181.504 2.24-72.512 27.264-133.056 75.072-181.568s107.84-73.344 180.096-74.432c72.32 1.088 132.608 25.92 180.992 74.432s73.664 109.056 75.84 181.568zM966.144 581.248c-0.512-0.704-1.088-1.344-1.728-1.92-22.656-22.72-59.52-22.72-82.176 0l-80.448 80.32-33.024 76.608c0 0-25.6-65.728-25.6-65.728l-29.312-29.312c-22.656-22.656-59.52-22.656-82.176 0-22.72 22.72-22.72 59.52 0 82.24l94.272 94.272c11.2 11.2 25.856 16.832 40.512 16.96 0.448 0 0.896 0 1.28 0 14.656-0.192 29.248-5.824 40.384-16.96l156.224-156.224c22.016-22.016 22.656-57.472 1.792-80.256z"],"attrs":[],"grid":0,"tags":["filter-circle-check"]},"attrs":[],"properties":{"order":16,"id":9,"name":"ca-circle-check","prevSize":32,"code":59656},"setIdx":0,"setId":1,"iconIdx":2},{"icon":{"paths":["M319.936 448h384v257.088h-384v-257.088z","M383.936 416v-96c0-35.328 28.672-64 64-64h128c35.328 0 64 28.672 64 64v96h-256zM575.936 320h-128v96h128v-96z","M192.448 724.864c68.864 103.168 186.368 171.136 319.552 171.136 141.568 0 265.344-76.8 331.904-190.912h142.4c-76.288 187.008-260.032 318.912-474.304 318.912-180.544 0-339.392-93.632-430.592-235.008l-81.536 47.104 2.112-324.096 281.472 160.384-91.008 52.48zM833.472 302.080c-68.544-104.832-187.008-174.080-321.472-174.080-167.040 0-309.376 106.944-362.112 256h-133.76c56.896-220.736 257.472-384 495.872-384 181.824 0 341.632 94.976 432.448 237.952l79.68-45.952-2.112 324.096-281.472-160.384 92.928-53.632z"],"attrs":[],"grid":0,"tags":["refresh-cert"]},"attrs":[],"properties":{"order":17,"id":8,"name":"refresh-cert","prevSize":32,"code":59657},"setIdx":0,"setId":1,"iconIdx":3},{"icon":{"paths":["M64.491 787.398c0 19.125 6.694 35.381 20.081 48.768s29.644 20.081 48.768 20.081h30.6c19.125 0 35.381-6.694 48.768-20.081s20.081-29.644 20.081-48.768c0-19.125-6.694-35.381-20.081-48.768s-29.644-20.081-48.768-20.081h-30.6c-19.125 0-35.381 6.694-48.768 20.081s-20.081 29.644-20.081 48.768zM64.491 512c0 19.125 6.694 35.381 20.081 48.768s29.644 20.081 48.768 20.081h30.6c19.125 0 35.381-6.694 48.768-20.081s20.081-29.644 20.081-48.768c0-19.125-6.694-35.381-20.081-48.768s-29.644-20.081-48.768-20.081h-30.6c-19.125 0-35.381 6.694-48.768 20.081s-20.081 29.644-20.081 48.768zM64.491 236.602c0 19.125 6.694 35.381 20.081 48.768s29.644 20.081 48.768 20.081h30.6c19.125 0 35.381-6.694 48.768-20.081s20.081-29.644 20.081-48.768c0-19.125-6.694-35.381-20.081-48.768s-29.644-20.081-48.768-20.081h-30.6c-19.125 0-35.381 6.694-48.768 20.081s-20.081 29.644-20.081 48.768zM288.252 787.398c0 19.125 6.694 35.381 20.081 48.768s29.644 20.081 48.768 20.081h534.54c19.125 0 35.381-6.694 48.768-20.081s20.081-29.644 20.081-48.768c0-19.125-6.694-35.381-20.081-48.768s-29.644-20.081-48.768-20.081h-534.54c-19.125 0-35.381 6.694-48.768 20.081s-20.081 29.644-20.081 48.768zM288.252 512c0 19.125 6.694 35.381 20.081 48.768s29.644 20.081 48.768 20.081h534.54c19.125 0 35.381-6.694 48.768-20.081s20.081-29.644 20.081-48.768c0-19.125-6.694-35.381-20.081-48.768s-29.644-20.081-48.768-20.081h-534.54c-19.125 0-35.381 6.694-48.768 20.081s-20.081 29.644-20.081 48.768zM288.252 236.602c0 19.125 6.694 35.381 20.081 48.768s29.644 20.081 48.768 20.081h534.54c19.125 0 35.381-6.694 48.768-20.081s20.081-29.644 20.081-48.768c0-19.125-6.694-35.381-20.081-48.768s-29.644-20.081-48.768-20.081h-534.54c-19.125 0-35.381 6.694-48.768 20.081s-20.081 29.644-20.081 48.768z"],"attrs":[],"grid":0,"tags":["th-list"]},"attrs":[],"properties":{"order":11,"id":7,"name":"th-list","prevSize":32,"code":59658},"setIdx":0,"setId":1,"iconIdx":4},{"icon":{"paths":["M574.496 81.411l45.262 8.286-149.128 422.304-45.261-8.286 149.126-422.304z","M896.001 369.329v29.341l-379.111 128.001-9.78-29.341 388.891-128.001z","M656 768v43.787l-164.906-224.295 41.812-23.571 123.093 204.079z","M205.566 845.588l-27.131-27.175 205.565-242.414 63.999 13.589-242.434 255.999z","M192.001 320.001l-38.798-52.36 308.952 225.624-28.309 38.763-241.845-212.028z","M576.418 0.897c75.061 0 136.002 60.94 136.002 136s-60.941 136-136.002 136c-75.058 0-135.999-60.94-135.999-136s60.941-136 135.999-136z","M911.998 272.897c61.815 0 111.999 50.187 111.999 112 0 61.816-50.185 112-111.999 112s-111.999-50.184-111.999-112c0-61.813 50.185-112 111.999-112z","M656 719.998c44.154 0 80.002 35.85 80.002 80.001 0 44.155-35.848 80.001-80.002 80.001-44.15 0-79.998-35.846-79.998-80.001 0-44.151 35.848-80.001 79.998-80.001z","M143.999 735.999c79.478 0 144.002 64.526 144.002 144.002s-64.524 143.999-144.002 143.999c-79.475 0-143.999-64.524-143.999-143.999s64.524-144.002 143.999-144.002z","M139.048 191.022c52.984 0 96.001 43.016 96.001 96.001 0 52.982-43.018 95.998-96.001 95.998s-95.998-43.016-95.998-95.998c0-52.985 43.014-96.001 95.998-96.001z","M448 319.706c105.968 0 192 86.034 192 192.001s-86.032 191.999-192 191.999c-105.968 0-192-86.032-192-191.999s86.032-192.001 192-192.001z"],"attrs":[],"grid":0,"tags":["icinga"]},"attrs":[],"properties":{"order":10,"id":6,"name":"icinga","prevSize":32,"code":59655},"setIdx":0,"setId":1,"iconIdx":5},{"icon":{"paths":["M192.009 128.005c0 35.361-28.665 64.026-64.026 64.026s-64.026-28.665-64.026-64.026c0-35.361 28.665-64.026 64.026-64.026s64.026 28.665 64.026 64.026z","M192.009 320.329c0 35.361-28.665 64.026-64.026 64.026s-64.026-28.665-64.026-64.026c0-35.361 28.665-64.026 64.026-64.026s64.026 28.665 64.026 64.026z","M192.009 512.329c0 35.361-28.665 64.026-64.026 64.026s-64.026-28.665-64.026-64.026c0-35.361 28.665-64.026 64.026-64.026s64.026 28.665 64.026 64.026z","M320.006 96.003h640.004v64.005h-640.004v-64.005z","M320.006 480.326h640.004v64.005h-640.004v-64.005z","M320.006 288.326h640.004v64.005h-640.004v-64.005z","M320.006 672.326h640.004v64.005h-640.004v-64.005z","M320.006 864.326h640.004v64.005h-640.004v-64.005z","M192.009 704.652c0 35.361-28.665 64.026-64.026 64.026s-64.026-28.665-64.026-64.026c0-35.361 28.665-64.026 64.026-64.026s64.026 28.665 64.026 64.026z","M192.009 896.329c0 35.361-28.665 64.026-64.026 64.026s-64.026-28.665-64.026-64.026c0-35.361 28.665-64.026 64.026-64.026s64.026 28.665 64.026 64.026z"],"attrs":[],"grid":0,"tags":["list-view-minimal"]},"attrs":[],"properties":{"order":4,"id":5,"name":"list-view-minimal","prevSize":32,"code":59648},"setIdx":0,"setId":1,"iconIdx":6},{"icon":{"paths":["M320.007 128.321h639.993v191.358h-639.993v-191.358z","M320.007 384.003h639.993v63.992h-639.993v-63.992z","M256.014 223.683c0 53.041-42.998 96.039-96.039 96.039s-96.039-42.998-96.039-96.039c0-53.041 42.998-96.039 96.039-96.039s96.039 42.998 96.039 96.039z","M256.014 672.008c0 53.041-42.998 96.039-96.039 96.039s-96.039-42.998-96.039-96.039c0-53.041 42.998-96.039 96.039-96.039s96.039 42.998 96.039 96.039z","M320.007 575.996h639.993v192.005h-639.993v-192.005z","M320.007 831.995h639.993v63.992h-639.993v-63.992z"],"attrs":[],"grid":0,"tags":["list-view-detailed"]},"attrs":[],"properties":{"order":5,"id":4,"name":"list-view-detailed","prevSize":32,"code":59649},"setIdx":0,"setId":1,"iconIdx":7},{"icon":{"paths":["M256.015 192.008c0 53.041-42.998 96.039-96.039 96.039s-96.039-42.998-96.039-96.039c0-53.041 42.998-96.039 96.039-96.039s96.039 42.998 96.039 96.039z","M384.001 96h576.002v192.008h-576.002v-192.008z","M384.001 416.002h576.002v192.008h-576.002v-192.008z","M384.001 736.002h576.002v192.008h-576.002v-192.008z","M256.015 512.010c0 53.041-42.998 96.039-96.039 96.039s-96.039-42.998-96.039-96.039c0-53.041 42.998-96.039 96.039-96.039s96.039 42.998 96.039 96.039z","M256.015 832.010c0 53.041-42.998 96.039-96.039 96.039s-96.039-42.998-96.039-96.039c0-53.041 42.998-96.039 96.039-96.039s96.039 42.998 96.039 96.039z"],"attrs":[],"grid":0,"tags":["listr-view-default"]},"attrs":[],"properties":{"order":6,"id":3,"name":"list-view-default","prevSize":32,"code":59650},"setIdx":0,"setId":1,"iconIdx":8},{"icon":{"paths":["M64.059 911.075v-274.364c0-14.39 4.781-25.902 14.342-35.495s21.035-14.39 35.377-15.349h273.451c13.386 0 24.859 4.797 35.377 15.349s15.298 22.064 14.342 35.495v274.364c0 13.43-4.781 24.942-14.342 34.535s-21.035 14.39-35.377 14.39h-273.451c-14.342 0-25.815-4.797-35.377-14.39s-14.342-21.105-14.342-34.535zM64.059 387.289v-274.364c0-13.43 4.781-24.942 14.342-34.535s21.035-14.39 35.377-14.39h273.451c13.386 0 24.859 4.797 35.377 14.39s15.298 21.105 14.342 34.535v274.364c0 14.39-4.781 25.902-14.342 35.495s-21.035 14.39-35.377 15.349h-273.451c-13.386 0-24.859-4.797-35.377-15.349s-15.298-22.064-14.342-35.495zM148.197 876.539h204.61v-205.293h-204.61v205.293zM148.197 352.753h204.61v-204.334h-204.61v204.334zM587.058 911.075v-274.364c0-14.39 4.781-25.902 14.342-35.495s21.035-14.39 35.377-15.349h273.451c13.386 0 24.859 4.797 35.377 15.349s15.298 22.064 14.342 35.495v274.364c0 13.43-4.781 24.942-14.342 34.535s-21.035 14.39-35.377 14.39h-273.451c-13.386 0-24.859-4.797-35.377-14.39s-15.298-21.105-14.342-34.535zM587.058 387.289v-274.364c0-13.43 4.781-24.942 14.342-34.535s21.035-14.39 35.377-14.39h273.451c14.342 0 25.815 4.797 35.377 14.39s14.342 21.105 14.342 34.535v274.364c0 14.39-4.781 25.902-14.342 35.495s-21.035 14.39-35.377 15.349h-273.451c-13.386 0-24.859-4.797-35.377-15.349s-15.298-22.064-14.342-35.495zM671.197 876.539h205.566v-205.293h-205.566v205.293zM671.197 352.753h205.566v-204.334h-205.566v204.334z"],"attrs":[],"grid":0,"tags":["th-thumb-empty"]},"attrs":[],"properties":{"order":7,"id":2,"name":"grid","prevSize":32,"code":59651},"setIdx":0,"setId":1,"iconIdx":9},{"icon":{"paths":["M473.568 780.8c0 59.098 44.467 107.789 101.76 114.432l6.682 0.576 6.758 0.192h-153.6l-6.758-0.192c-58.253-3.379-104.87-49.997-108.25-108.25l-0.192-6.758v-537.6l0.192-6.758c3.226-55.91 46.349-101.107 101.299-107.635l6.95-0.614 6.758-0.192h153.6l-6.758 0.192c-55.91 3.226-101.107 46.349-107.635 101.299l-0.614 6.95-0.192 6.758v537.6z"],"attrs":[],"grid":0,"tags":["bracket-open"]},"attrs":[],"properties":{"order":8,"id":1,"name":"bracket-open","prevSize":32,"code":59652},"setIdx":0,"setId":1,"iconIdx":10},{"icon":{"paths":["M447.136 780.8c0 59.098-44.467 107.789-101.76 114.432l-6.682 0.576-6.758 0.192h153.6l6.758-0.192c58.253-3.379 104.87-49.997 108.25-108.25l0.192-6.758v-537.6l-0.192-6.758c-3.226-55.91-46.349-101.107-101.299-107.635l-6.95-0.614-6.758-0.192h-153.6l6.758 0.192c55.91 3.226 101.107 46.349 107.635 101.299l0.614 6.95 0.192 6.758v537.6z"],"attrs":[],"grid":0,"tags":["bracket-close"]},"attrs":[],"properties":{"order":13,"id":0,"name":"bracket-close","prevSize":32,"code":59653},"setIdx":0,"setId":1,"iconIdx":11}],"height":1024,"metadata":{"name":"Icinga-Icons","url":"https://icinga.com","designer":"Florian Strohmaier (Icinga)","designerURL":"https://icinga.com","license":"Proprietary"},"preferences":{"showGlyphs":true,"showQuickUse":true,"showQuickUse2":true,"showSVGs":true,"fontPref":{"prefix":"iicon-","metadata":{"fontFamily":"Icinga-Icons","majorVersion":1,"minorVersion":0,"fontURL":"https://icinga.com","copyright":"Icinga GmbH","designer":"Florian Strohmaier (Icinga)","designerURL":"https://icinga.com","license":"Proprietary"},"metrics":{"emSize":1024,"baseline":6.25,"whitespace":50},"embed":false,"noie8":true,"ie7":false,"showSelector":true,"showMetrics":false,"showMetadata":false,"showVersion":false},"imagePref":{"prefix":"icon-","png":true,"useClassSelector":true,"color":0,"bgColor":16777215,"classSelector":".icon"},"historySize":50,"showCodes":true,"gridSize":16,"showGrid":false}}
\ No newline at end of file
+{"IcoMoonType":"selection","icons":[{"icon":{"paths":["M561.28 464.64v-160.64h-99.2v160.64h-158.080v99.2h158.080v156.16h99.2v-156.16h158.72v-99.2h-158.72z","M512 138.88c206.080 0 373.12 167.68 373.12 373.12s-167.68 373.12-373.12 373.12-373.12-167.68-373.12-373.12 167.68-373.12 373.12-373.12zM512 64c-247.68 0-448 200.32-448 448s200.32 448 448 448 448-200.32 448-448-200.32-448-448-448v0z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["add-inside"]},"attrs":[{},{}],"properties":{"order":21,"id":14,"name":"add-inside","prevSize":32,"code":59660},"setIdx":0,"setId":1,"iconIdx":0},{"icon":{"paths":["M419.2 499.84h-156.8c-10.88 0-19.2-8.96-19.2-19.2v-288.64h-115.2v307.84c0 74.24 60.16 135.040 135.040 135.040h156.8l-50.56 173.44 231.040-173.44s76.8-57.6 76.8-57.6l-308.48-273.28 51.2 195.84z","M64 64h448v74.88h-448v-74.88z","M853.12 808.32v-464c0-93.44 75.52-149.12 149.12-149.12-45.44 0-99.84-1.28-149.12-1.28-103.040 0-149.12 75.52-149.12 150.4v464c0 74.88 46.080 151.68 149.12 151.68 49.28 0 103.68-0.64 149.12-1.28-73.6 0-149.76-76.16-149.12-150.4z"],"attrs":[{},{},{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["inser-group"]},"attrs":[{},{},{}],"properties":{"order":29,"id":13,"name":"insert-group","prevSize":32,"code":59661},"setIdx":0,"setId":1,"iconIdx":1},{"icon":{"paths":["M802.56 62.72c-49.28 0-110.72 0.64-156.16 1.28 73.6 0 168.32 60.16 167.68 134.4v627.2c0 74.24-94.72 134.4-167.68 134.4 45.44 0 106.88 1.28 156.16 1.28 103.040 0 157.44-60.8 157.44-135.68v-627.2c0-74.88-55.040-135.68-157.44-135.68z","M704 502.4h-152.96v-182.4h-78.080v182.4h-152.96v77.44h152.96v188.16h78.080v-188.16h152.96v-77.44z","M209.92 825.6v-627.2c0-74.24 94.72-134.4 167.68-134.4-45.44 0-106.88-1.28-156.16-1.28-102.4 0-157.44 60.8-157.44 135.68v627.2c0 74.88 55.040 135.68 157.44 135.68 49.28 0 110.72-0.64 156.16-1.28-73.6 0-168.32-60.16-167.68-134.4z"],"attrs":[{},{},{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["wrap"]},"attrs":[{},{},{}],"properties":{"order":27,"id":12,"name":"wrap","prevSize":32,"code":59662},"setIdx":0,"setId":1,"iconIdx":2},{"icon":{"paths":["M64 0h896c35.328 0 64 28.672 64 64v640c0 35.328-28.672 64-64 64h-350.72v-64h350.72v-640h-896v640h33.28v64h-33.28c-35.328 0-64-28.672-64-64v-640c0-35.328 28.672-64 64-64z","M576.048 481.122c0 123.698-100.277 223.976-223.976 223.976s-223.976-100.277-223.976-223.976c0-123.698 100.277-223.976 223.976-223.976s223.976 100.277 223.976 223.976z","M511.488 720.896l64 303.104-224.32-128-223.168 128 64-303.488c45.76 30.656 100.8 48.576 160 48.576 58.944 0 113.792-17.728 159.488-48.192z","M896 192c0-16.96-6.784-33.28-18.752-45.248-12.032-12.032-28.288-18.752-45.248-18.752-71.040 0-185.024 0-256 0-17.024 0-33.28 6.72-45.248 18.752-12.032 11.968-18.752 28.288-18.752 45.248s6.72 33.28 18.752 45.248c11.968 12.032 28.224 18.752 45.248 18.752 70.976 0 184.96 0 256 0 16.96 0 33.216-6.72 45.248-18.752 11.968-11.968 18.752-28.288 18.752-45.248z","M896 384c0-16.96-6.784-33.28-18.752-45.248-12.032-12.032-28.288-18.752-45.248-18.752-71.040 0-57.024 0-128 0-17.024 0-33.28 6.72-45.248 18.752-12.032 11.968-18.752 28.288-18.752 45.248s6.72 33.28 18.752 45.248c11.968 12.032 28.224 18.752 45.248 18.752 70.976 0 56.96 0 128 0 16.96 0 33.216-6.72 45.248-18.752 11.968-11.968 18.752-28.288 18.752-45.248z"],"attrs":[],"grid":0,"tags":["certificate"]},"attrs":[],"properties":{"order":22,"id":11,"name":"certificate","prevSize":32,"code":59654},"setIdx":0,"setId":1,"iconIdx":3},{"icon":{"paths":["M7.232 90.496c11.776-24.896 36.672-40.704 64.192-40.704h768c27.584 0 52.48 15.808 64.192 40.704s8.192 54.208-9.216 75.52l-189.376 231.488c-142.592 29.312-249.6 155.392-249.6 306.496 0 48.704 11.2 94.912 31.104 136-2.816-1.408-5.696-3.2-8.32-5.184l-113.792-85.312c-14.4-10.688-22.784-27.52-22.784-45.504v-140.608l-325.312-397.504c-17.216-21.184-20.992-50.688-9.088-75.392z","M1024 705.024c-2.176 72.512-27.456 132.992-75.84 181.504-48.384 48.576-108.672 73.344-180.992 74.496-72.256-1.152-132.288-25.92-180.096-74.496-47.808-48.512-72.832-108.992-75.072-181.504 2.24-72.512 27.264-133.056 75.072-181.568s107.84-73.344 180.096-74.432c72.32 1.088 132.608 25.92 180.992 74.432s73.664 109.056 75.84 181.568zM966.144 581.248c-0.512-0.704-1.088-1.344-1.728-1.92-22.656-22.72-59.52-22.72-82.176 0l-80.448 80.32-33.024 76.608c0 0-25.6-65.728-25.6-65.728l-29.312-29.312c-22.656-22.656-59.52-22.656-82.176 0-22.72 22.72-22.72 59.52 0 82.24l94.272 94.272c11.2 11.2 25.856 16.832 40.512 16.96 0.448 0 0.896 0 1.28 0 14.656-0.192 29.248-5.824 40.384-16.96l156.224-156.224c22.016-22.016 22.656-57.472 1.792-80.256z"],"attrs":[],"grid":0,"tags":["filter-check-circle"]},"attrs":[],"properties":{"order":23,"id":10,"name":"filter-check-circle","prevSize":32,"code":59659},"setIdx":0,"setId":1,"iconIdx":4},{"icon":{"paths":["M177.038 607.479c-5.88 0.539-12.299 0.833-19.306 0.833-22.54 0-43.317-4.018-62.378-12.103-19.061-8.036-35.672-19.453-49.883-34.202-14.259-14.749-25.382-32.34-33.418-52.725s-12.103-43.072-12.103-68.013c0-24.941 4.165-47.727 12.495-68.405s19.6-38.22 33.81-52.725c14.21-14.504 30.968-25.48 50.324-33.026 19.306-7.497 40.23-11.27 62.77-11.27 20.384 0 40.671 3.92 60.761 11.711 20.139 7.742 36.358 19.159 48.707 34.202l-48.266 52.333c-6.468-10.241-15.043-17.591-25.774-22.148s-22.001-6.86-33.81-6.86c-11.809 0-22.932 2.401-33.418 7.252-10.437 4.851-19.453 11.515-26.95 20.139-7.497 8.575-13.279 18.767-17.297 30.576s-6.076 24.696-6.076 38.613c0 13.965 2.058 26.999 6.076 39.054 4.018 12.103 9.8 22.295 17.297 30.576 7.497 8.33 16.219 14.896 26.166 19.747 9.898 4.802 21.070 7.252 33.369 7.252 13.965 0 26.313-2.989 37.044-8.869 8.575-4.851 15.827-11.025 21.756-18.522l-41.896 96.58z","M484.864 594.112l-18.752-49.408h-123.2l-23.296 63.616h-82.944l132.8-321.984h74.88l90.688 222.4c-21.632 25.92-38.336 54.336-50.176 85.376zM405.696 372.48l-40.192 110.272h79.68l-39.488-110.272z","M1024 705.024c-2.176 72.512-27.456 132.992-75.84 181.504-48.384 48.576-108.672 73.344-180.992 74.496-72.256-1.152-132.288-25.92-180.096-74.496-47.808-48.512-72.832-108.992-75.072-181.504 2.24-72.512 27.264-133.056 75.072-181.568s107.84-73.344 180.096-74.432c72.32 1.088 132.608 25.92 180.992 74.432s73.664 109.056 75.84 181.568zM966.144 581.248c-0.512-0.704-1.088-1.344-1.728-1.92-22.656-22.72-59.52-22.72-82.176 0l-80.448 80.32-33.024 76.608c0 0-25.6-65.728-25.6-65.728l-29.312-29.312c-22.656-22.656-59.52-22.656-82.176 0-22.72 22.72-22.72 59.52 0 82.24l94.272 94.272c11.2 11.2 25.856 16.832 40.512 16.96 0.448 0 0.896 0 1.28 0 14.656-0.192 29.248-5.824 40.384-16.96l156.224-156.224c22.016-22.016 22.656-57.472 1.792-80.256z"],"attrs":[],"grid":0,"tags":["filter-circle-check"]},"attrs":[],"properties":{"order":24,"id":9,"name":"ca-circle-check","prevSize":32,"code":59656},"setIdx":0,"setId":1,"iconIdx":5},{"icon":{"paths":["M319.936 448h384v257.088h-384v-257.088z","M383.936 416v-96c0-35.328 28.672-64 64-64h128c35.328 0 64 28.672 64 64v96h-256zM575.936 320h-128v96h128v-96z","M192.448 724.864c68.864 103.168 186.368 171.136 319.552 171.136 141.568 0 265.344-76.8 331.904-190.912h142.4c-76.288 187.008-260.032 318.912-474.304 318.912-180.544 0-339.392-93.632-430.592-235.008l-81.536 47.104 2.112-324.096 281.472 160.384-91.008 52.48zM833.472 302.080c-68.544-104.832-187.008-174.080-321.472-174.080-167.040 0-309.376 106.944-362.112 256h-133.76c56.896-220.736 257.472-384 495.872-384 181.824 0 341.632 94.976 432.448 237.952l79.68-45.952-2.112 324.096-281.472-160.384 92.928-53.632z"],"attrs":[],"grid":0,"tags":["refresh-cert"]},"attrs":[],"properties":{"order":25,"id":8,"name":"refresh-cert","prevSize":32,"code":59657},"setIdx":0,"setId":1,"iconIdx":6},{"icon":{"paths":["M64.491 787.398c0 19.125 6.694 35.381 20.081 48.768s29.644 20.081 48.768 20.081h30.6c19.125 0 35.381-6.694 48.768-20.081s20.081-29.644 20.081-48.768c0-19.125-6.694-35.381-20.081-48.768s-29.644-20.081-48.768-20.081h-30.6c-19.125 0-35.381 6.694-48.768 20.081s-20.081 29.644-20.081 48.768zM64.491 512c0 19.125 6.694 35.381 20.081 48.768s29.644 20.081 48.768 20.081h30.6c19.125 0 35.381-6.694 48.768-20.081s20.081-29.644 20.081-48.768c0-19.125-6.694-35.381-20.081-48.768s-29.644-20.081-48.768-20.081h-30.6c-19.125 0-35.381 6.694-48.768 20.081s-20.081 29.644-20.081 48.768zM64.491 236.602c0 19.125 6.694 35.381 20.081 48.768s29.644 20.081 48.768 20.081h30.6c19.125 0 35.381-6.694 48.768-20.081s20.081-29.644 20.081-48.768c0-19.125-6.694-35.381-20.081-48.768s-29.644-20.081-48.768-20.081h-30.6c-19.125 0-35.381 6.694-48.768 20.081s-20.081 29.644-20.081 48.768zM288.252 787.398c0 19.125 6.694 35.381 20.081 48.768s29.644 20.081 48.768 20.081h534.54c19.125 0 35.381-6.694 48.768-20.081s20.081-29.644 20.081-48.768c0-19.125-6.694-35.381-20.081-48.768s-29.644-20.081-48.768-20.081h-534.54c-19.125 0-35.381 6.694-48.768 20.081s-20.081 29.644-20.081 48.768zM288.252 512c0 19.125 6.694 35.381 20.081 48.768s29.644 20.081 48.768 20.081h534.54c19.125 0 35.381-6.694 48.768-20.081s20.081-29.644 20.081-48.768c0-19.125-6.694-35.381-20.081-48.768s-29.644-20.081-48.768-20.081h-534.54c-19.125 0-35.381 6.694-48.768 20.081s-20.081 29.644-20.081 48.768zM288.252 236.602c0 19.125 6.694 35.381 20.081 48.768s29.644 20.081 48.768 20.081h534.54c19.125 0 35.381-6.694 48.768-20.081s20.081-29.644 20.081-48.768c0-19.125-6.694-35.381-20.081-48.768s-29.644-20.081-48.768-20.081h-534.54c-19.125 0-35.381 6.694-48.768 20.081s-20.081 29.644-20.081 48.768z"],"attrs":[],"grid":0,"tags":["th-list"]},"attrs":[],"properties":{"order":26,"id":7,"name":"th-list","prevSize":32,"code":59658},"setIdx":0,"setId":1,"iconIdx":7},{"icon":{"paths":["M574.496 81.411l45.262 8.286-149.128 422.304-45.261-8.286 149.126-422.304z","M896.001 369.329v29.341l-379.111 128.001-9.78-29.341 388.891-128.001z","M656 768v43.787l-164.906-224.295 41.812-23.571 123.093 204.079z","M205.566 845.588l-27.131-27.175 205.565-242.414 63.999 13.589-242.434 255.999z","M192.001 320.001l-38.798-52.36 308.952 225.624-28.309 38.763-241.845-212.028z","M576.418 0.897c75.061 0 136.002 60.94 136.002 136s-60.941 136-136.002 136c-75.058 0-135.999-60.94-135.999-136s60.941-136 135.999-136z","M911.998 272.897c61.815 0 111.999 50.187 111.999 112 0 61.816-50.185 112-111.999 112s-111.999-50.184-111.999-112c0-61.813 50.185-112 111.999-112z","M656 719.998c44.154 0 80.002 35.85 80.002 80.001 0 44.155-35.848 80.001-80.002 80.001-44.15 0-79.998-35.846-79.998-80.001 0-44.151 35.848-80.001 79.998-80.001z","M143.999 735.999c79.478 0 144.002 64.526 144.002 144.002s-64.524 143.999-144.002 143.999c-79.475 0-143.999-64.524-143.999-143.999s64.524-144.002 143.999-144.002z","M139.048 191.022c52.984 0 96.001 43.016 96.001 96.001 0 52.982-43.018 95.998-96.001 95.998s-95.998-43.016-95.998-95.998c0-52.985 43.014-96.001 95.998-96.001z","M448 319.706c105.968 0 192 86.034 192 192.001s-86.032 191.999-192 191.999c-105.968 0-192-86.032-192-191.999s86.032-192.001 192-192.001z"],"attrs":[],"grid":0,"tags":["icinga"]},"attrs":[],"properties":{"order":10,"id":6,"name":"icinga","prevSize":32,"code":59655},"setIdx":0,"setId":1,"iconIdx":8},{"icon":{"paths":["M192.009 128.005c0 35.361-28.665 64.026-64.026 64.026s-64.026-28.665-64.026-64.026c0-35.361 28.665-64.026 64.026-64.026s64.026 28.665 64.026 64.026z","M192.009 320.329c0 35.361-28.665 64.026-64.026 64.026s-64.026-28.665-64.026-64.026c0-35.361 28.665-64.026 64.026-64.026s64.026 28.665 64.026 64.026z","M192.009 512.329c0 35.361-28.665 64.026-64.026 64.026s-64.026-28.665-64.026-64.026c0-35.361 28.665-64.026 64.026-64.026s64.026 28.665 64.026 64.026z","M320.006 96.003h640.004v64.005h-640.004v-64.005z","M320.006 480.326h640.004v64.005h-640.004v-64.005z","M320.006 288.326h640.004v64.005h-640.004v-64.005z","M320.006 672.326h640.004v64.005h-640.004v-64.005z","M320.006 864.326h640.004v64.005h-640.004v-64.005z","M192.009 704.652c0 35.361-28.665 64.026-64.026 64.026s-64.026-28.665-64.026-64.026c0-35.361 28.665-64.026 64.026-64.026s64.026 28.665 64.026 64.026z","M192.009 896.329c0 35.361-28.665 64.026-64.026 64.026s-64.026-28.665-64.026-64.026c0-35.361 28.665-64.026 64.026-64.026s64.026 28.665 64.026 64.026z"],"attrs":[],"grid":0,"tags":["list-view-minimal"]},"attrs":[],"properties":{"order":4,"id":5,"name":"list-view-minimal","prevSize":32,"code":59648},"setIdx":0,"setId":1,"iconIdx":9},{"icon":{"paths":["M320.007 128.321h639.993v191.358h-639.993v-191.358z","M320.007 384.003h639.993v63.992h-639.993v-63.992z","M256.014 223.683c0 53.041-42.998 96.039-96.039 96.039s-96.039-42.998-96.039-96.039c0-53.041 42.998-96.039 96.039-96.039s96.039 42.998 96.039 96.039z","M256.014 672.008c0 53.041-42.998 96.039-96.039 96.039s-96.039-42.998-96.039-96.039c0-53.041 42.998-96.039 96.039-96.039s96.039 42.998 96.039 96.039z","M320.007 575.996h639.993v192.005h-639.993v-192.005z","M320.007 831.995h639.993v63.992h-639.993v-63.992z"],"attrs":[],"grid":0,"tags":["list-view-detailed"]},"attrs":[],"properties":{"order":5,"id":4,"name":"list-view-detailed","prevSize":32,"code":59649},"setIdx":0,"setId":1,"iconIdx":10},{"icon":{"paths":["M256.015 192.008c0 53.041-42.998 96.039-96.039 96.039s-96.039-42.998-96.039-96.039c0-53.041 42.998-96.039 96.039-96.039s96.039 42.998 96.039 96.039z","M384.001 96h576.002v192.008h-576.002v-192.008z","M384.001 416.002h576.002v192.008h-576.002v-192.008z","M384.001 736.002h576.002v192.008h-576.002v-192.008z","M256.015 512.010c0 53.041-42.998 96.039-96.039 96.039s-96.039-42.998-96.039-96.039c0-53.041 42.998-96.039 96.039-96.039s96.039 42.998 96.039 96.039z","M256.015 832.010c0 53.041-42.998 96.039-96.039 96.039s-96.039-42.998-96.039-96.039c0-53.041 42.998-96.039 96.039-96.039s96.039 42.998 96.039 96.039z"],"attrs":[],"grid":0,"tags":["listr-view-default"]},"attrs":[],"properties":{"order":6,"id":3,"name":"list-view-default","prevSize":32,"code":59650},"setIdx":0,"setId":1,"iconIdx":11},{"icon":{"paths":["M64.059 911.075v-274.364c0-14.39 4.781-25.902 14.342-35.495s21.035-14.39 35.377-15.349h273.451c13.386 0 24.859 4.797 35.377 15.349s15.298 22.064 14.342 35.495v274.364c0 13.43-4.781 24.942-14.342 34.535s-21.035 14.39-35.377 14.39h-273.451c-14.342 0-25.815-4.797-35.377-14.39s-14.342-21.105-14.342-34.535zM64.059 387.289v-274.364c0-13.43 4.781-24.942 14.342-34.535s21.035-14.39 35.377-14.39h273.451c13.386 0 24.859 4.797 35.377 14.39s15.298 21.105 14.342 34.535v274.364c0 14.39-4.781 25.902-14.342 35.495s-21.035 14.39-35.377 15.349h-273.451c-13.386 0-24.859-4.797-35.377-15.349s-15.298-22.064-14.342-35.495zM148.197 876.539h204.61v-205.293h-204.61v205.293zM148.197 352.753h204.61v-204.334h-204.61v204.334zM587.058 911.075v-274.364c0-14.39 4.781-25.902 14.342-35.495s21.035-14.39 35.377-15.349h273.451c13.386 0 24.859 4.797 35.377 15.349s15.298 22.064 14.342 35.495v274.364c0 13.43-4.781 24.942-14.342 34.535s-21.035 14.39-35.377 14.39h-273.451c-13.386 0-24.859-4.797-35.377-14.39s-15.298-21.105-14.342-34.535zM587.058 387.289v-274.364c0-13.43 4.781-24.942 14.342-34.535s21.035-14.39 35.377-14.39h273.451c14.342 0 25.815 4.797 35.377 14.39s14.342 21.105 14.342 34.535v274.364c0 14.39-4.781 25.902-14.342 35.495s-21.035 14.39-35.377 15.349h-273.451c-13.386 0-24.859-4.797-35.377-15.349s-15.298-22.064-14.342-35.495zM671.197 876.539h205.566v-205.293h-205.566v205.293zM671.197 352.753h205.566v-204.334h-205.566v204.334z"],"attrs":[],"grid":0,"tags":["th-thumb-empty"]},"attrs":[],"properties":{"order":7,"id":2,"name":"grid","prevSize":32,"code":59651},"setIdx":0,"setId":1,"iconIdx":12},{"icon":{"paths":["M473.568 780.8c0 59.098 44.467 107.789 101.76 114.432l6.682 0.576 6.758 0.192h-153.6l-6.758-0.192c-58.253-3.379-104.87-49.997-108.25-108.25l-0.192-6.758v-537.6l0.192-6.758c3.226-55.91 46.349-101.107 101.299-107.635l6.95-0.614 6.758-0.192h153.6l-6.758 0.192c-55.91 3.226-101.107 46.349-107.635 101.299l-0.614 6.95-0.192 6.758v537.6z"],"attrs":[],"grid":0,"tags":["bracket-open"]},"attrs":[],"properties":{"order":8,"id":1,"name":"bracket-open","prevSize":32,"code":59652},"setIdx":0,"setId":1,"iconIdx":13},{"icon":{"paths":["M447.136 780.8c0 59.098-44.467 107.789-101.76 114.432l-6.682 0.576-6.758 0.192h153.6l6.758-0.192c58.253-3.379 104.87-49.997 108.25-108.25l0.192-6.758v-537.6l-0.192-6.758c-3.226-55.91-46.349-101.107-101.299-107.635l-6.95-0.614-6.758-0.192h-153.6l6.758 0.192c55.91 3.226 101.107 46.349 107.635 101.299l0.614 6.95 0.192 6.758v537.6z"],"attrs":[],"grid":0,"tags":["bracket-close"]},"attrs":[],"properties":{"order":13,"id":0,"name":"bracket-close","prevSize":32,"code":59653},"setIdx":0,"setId":1,"iconIdx":14}],"height":1024,"metadata":{"name":"Icinga-Icons","url":"https://icinga.com","designer":"Florian Strohmaier (Icinga)","designerURL":"https://icinga.com","license":"Proprietary"},"preferences":{"showGlyphs":true,"showQuickUse":true,"showQuickUse2":true,"showSVGs":true,"fontPref":{"prefix":"iicon-","metadata":{"fontFamily":"Icinga-Icons","majorVersion":1,"minorVersion":0,"fontURL":"https://icinga.com","copyright":"Icinga GmbH","designer":"Florian Strohmaier (Icinga)","designerURL":"https://icinga.com","license":"Proprietary"},"metrics":{"emSize":1024,"baseline":6.25,"whitespace":50},"embed":false,"noie8":true,"ie7":false,"showSelector":true,"showMetrics":true,"showMetadata":true,"showVersion":true},"imagePref":{"prefix":"icon-","png":true,"useClassSelector":true,"color":0,"bgColor":16777215,"classSelector":".icon"},"historySize":50,"showCodes":true,"gridSize":16,"showGrid":false}}
\ No newline at end of file
diff --git a/vendor/ipl/web/composer.json b/vendor/ipl/web/composer.json
index 642039e..1534baa 100644
--- a/vendor/ipl/web/composer.json
+++ b/vendor/ipl/web/composer.json
@@ -17,10 +17,10 @@
}
},
"require": {
- "php": ">=7.2",
+ "php": ">=8.2",
"ext-json": "*",
"psr/http-message": "^1.1",
- "ipl/html": ">=0.8.0",
+ "ipl/html": ">=0.9.0",
"ipl/i18n": ">=0.2.0",
"ipl/orm": ">=0.5.2",
"ipl/scheduler": ">=0.1.0",
diff --git a/vendor/ipl/web/src/Common/BaseItemList.php b/vendor/ipl/web/src/Common/BaseItemList.php
index 8320d1c..dc7091d 100644
--- a/vendor/ipl/web/src/Common/BaseItemList.php
+++ b/vendor/ipl/web/src/Common/BaseItemList.php
@@ -7,9 +7,12 @@ use ipl\Html\BaseHtmlElement;
use ipl\Orm\ResultSet;
use ipl\Stdlib\BaseFilter;
use ipl\Web\Widget\EmptyStateBar;
+use ipl\Web\Widget\ItemList;
/**
* Base class for item lists
+ *
+ * @deprecated Use {@see ItemList} instead
*/
abstract class BaseItemList extends BaseHtmlElement
{
@@ -33,6 +36,9 @@ abstract class BaseItemList extends BaseHtmlElement
protected $tag = 'ul';
+ /** @var ?string Message to show if the list is empty */
+ protected $emptyStateMessage;
+
/**
* Create a new item list
*
@@ -62,12 +68,52 @@ abstract class BaseItemList extends BaseHtmlElement
{
}
+ /**
+ * Create a list item for the given data
+ *
+ * @param object $data
+ *
+ * @return BaseListItem|BaseTableRowItem
+ */
+ protected function createListItem(object $data)
+ {
+ $className = $this->getItemClass();
+
+ return new $className($data, $this);
+ }
+
+ /**
+ * Get message to show if the list is empty
+ *
+ * @return string
+ */
+ public function getEmptyStateMessage(): string
+ {
+ if ($this->emptyStateMessage === null) {
+ return t('No items found.');
+ }
+
+ return $this->emptyStateMessage;
+ }
+
+ /**
+ * Set message to show if the list is empty
+ *
+ * @param string $message
+ *
+ * @return $this
+ */
+ public function setEmptyStateMessage(string $message): self
+ {
+ $this->emptyStateMessage = $message;
+
+ return $this;
+ }
+
protected function assemble(): void
{
- $itemClass = $this->getItemClass();
foreach ($this->data as $data) {
- /** @var BaseListItem|BaseTableRowItem $item */
- $item = new $itemClass($data, $this);
+ $item = $this->createListItem($data);
$this->emit(self::BEFORE_ITEM_ADD, [$item, $data]);
$this->addHtml($item);
$this->emit(self::ON_ITEM_ADD, [$item, $data]);
@@ -75,7 +121,7 @@ abstract class BaseItemList extends BaseHtmlElement
if ($this->isEmpty()) {
$this->setTag('div');
- $this->addHtml(new EmptyStateBar(t('No items found.')));
+ $this->addHtml(new EmptyStateBar($this->getEmptyStateMessage()));
}
}
}
diff --git a/vendor/ipl/web/src/Common/BaseItemTable.php b/vendor/ipl/web/src/Common/BaseItemTable.php
index f6ca212..6fd7541 100644
--- a/vendor/ipl/web/src/Common/BaseItemTable.php
+++ b/vendor/ipl/web/src/Common/BaseItemTable.php
@@ -7,9 +7,12 @@ use ipl\Html\BaseHtmlElement;
use ipl\Orm\ResultSet;
use ipl\Stdlib\BaseFilter;
use ipl\Web\Widget\EmptyStateBar;
+use ipl\Web\Widget\ItemTable;
/**
* Base class for item tables
+ *
+ * @deprecated Use {@see ItemTable} instead
*/
abstract class BaseItemTable extends BaseHtmlElement
{
diff --git a/vendor/ipl/web/src/Common/BaseListItem.php b/vendor/ipl/web/src/Common/BaseListItem.php
index cf143ee..787391e 100644
--- a/vendor/ipl/web/src/Common/BaseListItem.php
+++ b/vendor/ipl/web/src/Common/BaseListItem.php
@@ -5,14 +5,17 @@ namespace ipl\Web\Common;
use ipl\Html\Attributes;
use ipl\Html\BaseHtmlElement;
use ipl\Html\HtmlElement;
+use ipl\Web\Widget\ItemList;
/**
* Base class for list items
+ *
+ * @deprecated Use a {@see ItemList} with a dedicated {@see ItemRenderer} instead.
*/
abstract class BaseListItem extends BaseHtmlElement
{
/** @var array */
- protected $baseAttributes = ['class' => 'list-item'];
+ protected $baseAttributes = ['class' => ['list-item', 'item-layout', 'default-item-layout']];
/** @var object The associated list item */
protected $item;
diff --git a/vendor/ipl/web/src/Common/BaseOrderedItemList.php b/vendor/ipl/web/src/Common/BaseOrderedItemList.php
index c141fc5..cef5450 100644
--- a/vendor/ipl/web/src/Common/BaseOrderedItemList.php
+++ b/vendor/ipl/web/src/Common/BaseOrderedItemList.php
@@ -6,6 +6,7 @@ use ipl\Web\Widget\EmptyStateBar;
/**
* @method BaseOrderedListItem getItemClass()
+ * @deprecated Use your own implementation instead
*/
abstract class BaseOrderedItemList extends BaseItemList
{
diff --git a/vendor/ipl/web/src/Common/BaseOrderedListItem.php b/vendor/ipl/web/src/Common/BaseOrderedListItem.php
index 03b387d..e43c076 100644
--- a/vendor/ipl/web/src/Common/BaseOrderedListItem.php
+++ b/vendor/ipl/web/src/Common/BaseOrderedListItem.php
@@ -4,6 +4,7 @@ namespace ipl\Web\Common;
use LogicException;
+/** @deprecated Use your own implementation instead */
abstract class BaseOrderedListItem extends BaseListItem
{
/** @var ?int This element's position */
diff --git a/vendor/ipl/web/src/Common/BaseTableRowItem.php b/vendor/ipl/web/src/Common/BaseTableRowItem.php
index c24578f..9149a77 100644
--- a/vendor/ipl/web/src/Common/BaseTableRowItem.php
+++ b/vendor/ipl/web/src/Common/BaseTableRowItem.php
@@ -7,11 +7,13 @@ use ipl\Html\BaseHtmlElement;
use ipl\Html\Html;
use ipl\Html\HtmlDocument;
use ipl\Html\HtmlElement;
+use ipl\Web\Widget\ItemTable;
+/** @deprecated Use a {@see ItemTable} with a dedicated {@see ItemRenderer} instead. */
abstract class BaseTableRowItem extends BaseHtmlElement
{
/** @var array */
- protected $baseAttributes = ['class' => 'table-row'];
+ protected $baseAttributes = ['class' => ['table-row', 'item-layout', 'default-item-layout']];
/** @var object The associated list item */
protected $item;
diff --git a/vendor/ipl/web/src/Common/CsrfCounterMeasure.php b/vendor/ipl/web/src/Common/CsrfCounterMeasure.php
index ae2dace..5ad58df 100644
--- a/vendor/ipl/web/src/Common/CsrfCounterMeasure.php
+++ b/vendor/ipl/web/src/Common/CsrfCounterMeasure.php
@@ -8,12 +8,44 @@ use ipl\Html\FormElement\HiddenElement;
trait CsrfCounterMeasure
{
+ /** @var ?string The ID of the CSRF form element */
+ private ?string $csrfCounterMeasureId = null;
+
+ /** @var bool Whether to actually add the CSRF element to the form */
+ private bool $csrfCounterMeasureEnabled = true;
+
+ /**
+ * Set the ID for the CSRF form element
+ *
+ * @param string $id A unique ID that persists through different requests
+ *
+ * @return $this
+ */
+ public function setCsrfCounterMeasureId(string $id): static
+ {
+ $this->csrfCounterMeasureId = $id;
+
+ return $this;
+ }
+
+ /**
+ * Disable the CSRF form element
+ *
+ * @return void
+ */
+ public function disableCsrfCounterMeasure(): void
+ {
+ $this->csrfCounterMeasureEnabled = false;
+ }
+
/**
* Create a form element to countermeasure CSRF attacks
*
* @param string $uniqueId A unique ID that persists through different requests
*
* @return FormElement
+ *
+ * @deprecated Use {@see addCsrfCounterMeasure()} instead
*/
protected function createCsrfCounterMeasure($uniqueId)
{
@@ -53,4 +85,27 @@ trait CsrfCounterMeasure
return $element;
}
+
+ /**
+ * Add the CSRF form element to this form
+ *
+ * Does nothing if disabled via {@see disableCsrfCounterMeasure()}.
+ * Unless passed as argument, requires a unique ID to be set via {@see setCsrfCounterMeasureId()}.
+ *
+ * @param ?string $uniqueId A unique ID that persists through different requests
+ *
+ * @return void
+ */
+ protected function addCsrfCounterMeasure(?string $uniqueId = null): void
+ {
+ if (! $this->csrfCounterMeasureEnabled) {
+ return;
+ }
+
+ if ($uniqueId === null && $this->csrfCounterMeasureId === null) {
+ throw new Error('No CSRF counter measure ID set');
+ }
+
+ $this->addElement($this->createCsrfCounterMeasure($uniqueId ?? $this->csrfCounterMeasureId));
+ }
}
diff --git a/vendor/ipl/web/src/Common/ItemRenderer.php b/vendor/ipl/web/src/Common/ItemRenderer.php
new file mode 100644
index 0000000..015d61f
--- /dev/null
+++ b/vendor/ipl/web/src/Common/ItemRenderer.php
@@ -0,0 +1,92 @@
+ 'icinga-form icinga-controls'];
+ /** @var bool Whether to disable the legacy form decorator */
+ private bool $disableLegacyDecorator = false;
+
+ /**
+ * Apply default element decorators
+ *
+ * This method must be called before adding any elements to the form.
+ *
+ * Calling this method disables the legacy decorator.
+ *
+ * @return $this
+ */
+ public function applyDefaultElementDecorators(): static
+ {
+ $this->disableLegacyDecorator = true;
+
+ $this->addElementDecoratorLoaderPaths([
+ ['ipl\\Web\\Compat\\FormDecorator', 'Decorator']
+ ]);
+
+ $labelDecorator = new LabelDecorator();
+ $this->setDefaultElementDecorators([
+ 'Label' => $labelDecorator,
+ 'LabelGroup' => [
+ 'name' => 'HtmlTag',
+ 'options' => [
+ 'tag' => 'div',
+ 'class' => 'control-label-group',
+ 'condition' => function (FormElement $element): bool {
+ return ! $element instanceof FormSubmitElement
+ && (! $element instanceof HtmlElementInterface || $element->getTag() !== 'fieldset');
+ }
+ ]
+ ],
+ 'Fieldset',
+ 'Checkbox',
+ 'RenderElement',
+ 'Description',
+ 'Errors' => ['name' => 'Errors', 'options' => ['class' => 'errors']],
+ 'ControlGroup' => [
+ 'name' => 'HtmlTag',
+ 'options' => [
+ 'tag' => 'div',
+ 'class' => 'control-group',
+ 'condition' => fn(FormElement $element): bool => ! $element instanceof FormSubmitElement
+ ]
+ ],
+ 'FormControls' => [
+ 'name' => 'HtmlTag',
+ 'options' => [
+ 'tag' => 'div',
+ 'class' => 'control-group form-controls',
+ 'condition' => fn(FormElement $element): bool => $element instanceof FormSubmitElement
+ ]
+ ],
+ ]);
+
+ $this->getDecorators()->addDecorator('Required', $labelDecorator);
+
+ return $this;
+ }
+
/**
* Render the content of the element to HTML
*
@@ -41,6 +106,10 @@ class CompatForm extends Form
public function hasDefaultElementDecorator()
{
+ if ($this->disableLegacyDecorator) {
+ return false;
+ }
+
if (parent::hasDefaultElementDecorator()) {
return true;
}
diff --git a/vendor/ipl/web/src/Compat/FormDecorator/CheckboxDecorator.php b/vendor/ipl/web/src/Compat/FormDecorator/CheckboxDecorator.php
new file mode 100644
index 0000000..0dfe64b
--- /dev/null
+++ b/vendor/ipl/web/src/Compat/FormDecorator/CheckboxDecorator.php
@@ -0,0 +1,52 @@
+getAttributes();
+ $elementAttrs->add('class', 'sr-only');
+
+ if (! $elementAttrs->has('id')) {
+ $elementAttrs->set('id', uniqid('checkbox_'));
+ }
+
+ $attributes = new Attributes([
+ 'class' => 'toggle-switch',
+ 'aria-hidden' => 'true',
+ 'for' => $elementAttrs->get('id')->getValue()
+ ]);
+
+ if ($elementAttrs->get('disabled')->getValue()) {
+ $attributes->add('class', 'disabled');
+ }
+
+ $formElement->prependWrapper(
+ (new HtmlDocument())->addHtml(
+ $formElement,
+ new HtmlElement(
+ 'label',
+ $attributes,
+ new HtmlElement('span', Attributes::create(['class' => 'toggle-slider']))
+ )
+ )
+ );
+ }
+}
diff --git a/vendor/ipl/web/src/Compat/FormDecorator/DescriptionDecorator.php b/vendor/ipl/web/src/Compat/FormDecorator/DescriptionDecorator.php
new file mode 100644
index 0000000..fe6b75e
--- /dev/null
+++ b/vendor/ipl/web/src/Compat/FormDecorator/DescriptionDecorator.php
@@ -0,0 +1,34 @@
+getDescription();
+ $icon = new Icon('info-circle', [
+ 'aria-hidden' => 'true',
+ 'class' => 'control-info',
+ 'role' => 'img',
+ 'title' => $description
+ ]);
+
+ return (new HtmlElement('span', content: new Text($description)))
+ ->addWrapper((new HtmlDocument())->addHtml($icon));
+ }
+}
diff --git a/vendor/ipl/web/src/Compat/FormDecorator/LabelDecorator.php b/vendor/ipl/web/src/Compat/FormDecorator/LabelDecorator.php
new file mode 100755
index 0000000..72e8d12
--- /dev/null
+++ b/vendor/ipl/web/src/Compat/FormDecorator/LabelDecorator.php
@@ -0,0 +1,74 @@
+isRequired()) {
+ $formElement->setAttribute('aria-required', 'true');
+ $requiredHint = new HtmlElement(
+ 'span',
+ Attributes::create([
+ 'class' => 'required-hint',
+ 'aria-hidden' => 'true',
+ 'title' => $this->translate('Required')
+ ]),
+ Text::create(" *")
+ );
+ $this->requiredExplanationNeeded = true;
+ $result->addHtml($requiredHint);
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Appends an explanation of the asterisk for required fields if at least one such field exists
+ */
+ public function decorateForm(DecorationResult $result, Form $form): void
+ {
+ if ($this->requiredExplanationNeeded) {
+ $requiredExplanation = new HtmlElement(
+ 'ul',
+ Attributes::create(['class' => 'form-info',]),
+ new HtmlElement(
+ 'li',
+ null,
+ Text::create(sprintf($this->translate('%s Required field'), '*'))
+ )
+ );
+ $result->append($requiredExplanation);
+ }
+ }
+}
diff --git a/vendor/ipl/web/src/Compat/SearchControls.php b/vendor/ipl/web/src/Compat/SearchControls.php
index f6e74ab..f554473 100644
--- a/vendor/ipl/web/src/Compat/SearchControls.php
+++ b/vendor/ipl/web/src/Compat/SearchControls.php
@@ -57,9 +57,10 @@ trait SearchControls
$requestUrl = Url::fromRequest();
$preserveParams = array_pop($params) ?? [];
$redirectUrl = array_pop($params);
+ $paramsToAdd = $this->decodedParamValues($preserveParams, $requestUrl);
if ($redirectUrl !== null) {
- $redirectUrl->addParams($requestUrl->onlyWith($preserveParams)->getParams()->toArray(false));
+ $redirectUrl->addParams($paramsToAdd);
} else {
$redirectUrl = $requestUrl->onlyWith($preserveParams);
}
@@ -83,14 +84,14 @@ trait SearchControls
if (method_exists($this, 'completeAction')) {
$searchBar->setSuggestionUrl(Url::fromPath(
"$moduleName/$controllerName/complete",
- ['_disableLayout' => true, 'showCompact' => true]
+ $paramsToAdd + ['_disableLayout' => true, 'showCompact' => true]
));
}
if (method_exists($this, 'searchEditorAction')) {
$searchBar->setEditorUrl(Url::fromPath(
"$moduleName/$controllerName/search-editor"
- )->setParams($redirectUrl->getParams()));
+ )->setParams(clone $redirectUrl->getParams()));
}
$filterColumns = $this->fetchFilterColumns($query);
@@ -127,7 +128,15 @@ trait SearchControls
->on(SearchBar::ON_SENT, function (SearchBar $form) {
/** @var Url $redirectUrl */
$redirectUrl = $form->getRedirectUrl();
- $redirectUrl->setFilter($form->getFilter());
+
+ $baseFilter = $redirectUrl->getFilter();
+ if ($baseFilter && ((! $baseFilter instanceof Filter\Chain) || ! $baseFilter->isEmpty())) {
+ $filter = Filter::all($baseFilter, $form->getFilter());
+ } else {
+ $filter = $form->getFilter();
+ }
+
+ $redirectUrl->setFilter($filter);
$form->setRedirectUrl($redirectUrl);
})->on(SearchBar::ON_SUCCESS, function (SearchBar $form) {
$this->getResponse()->redirectAndExit($form->getRedirectUrl());
@@ -156,14 +165,13 @@ trait SearchControls
$redirectUrl = array_pop($params);
$moduleName = $this->getRequest()->getModuleName();
$controllerName = $this->getRequest()->getControllerName();
+ $paramsToAdd = $this->decodedParamValues($preserveParams, $requestUrl);
if ($redirectUrl !== null) {
- $redirectUrl->addParams($requestUrl->onlyWith($preserveParams)->getParams()->toArray(false));
+ $redirectUrl->addParams($paramsToAdd);
} else {
- $redirectUrl = Url::fromPath("$moduleName/$controllerName");
- if (! empty($preserveParams)) {
- $redirectUrl->setParams($requestUrl->onlyWith($preserveParams)->getParams());
- }
+ $redirectUrl = Url::fromPath("$moduleName/$controllerName")
+ ->setParams($paramsToAdd);
}
$editor = new SearchEditor();
@@ -174,7 +182,7 @@ trait SearchControls
if (method_exists($this, 'completeAction')) {
$editor->setSuggestionUrl(Url::fromPath(
"$moduleName/$controllerName/complete",
- ['_disableLayout' => true, 'showCompact' => true]
+ $paramsToAdd + ['_disableLayout' => true, 'showCompact' => true]
));
}
@@ -217,7 +225,15 @@ trait SearchControls
})->on(SearchEditor::ON_SUCCESS, function (SearchEditor $form) {
/** @var Url $redirectUrl */
$redirectUrl = $form->getRedirectUrl();
- $redirectUrl->setFilter($form->getFilter());
+
+ $baseFilter = $redirectUrl->getFilter();
+ if ($baseFilter && ((! $baseFilter instanceof Filter\Chain) || ! $baseFilter->isEmpty())) {
+ $filter = Filter::all($baseFilter, $form->getFilter());
+ } else {
+ $filter = $form->getFilter();
+ }
+
+ $redirectUrl->setFilter($filter);
$this->getResponse()
->setHeader('X-Icinga-Container', '_self')
@@ -257,4 +273,27 @@ trait SearchControls
$condition->metaData()->set('columnLabel', $label);
}
}
+
+ /**
+ * Decode the given param names from the given Url
+ *
+ * @internal This is only a helping method to prevent params being encoded multiple times in
+ * {@see SearchControls::createSearchBar()} and {@see SearchControls::createSearchEditor()}
+ * and therefore should not be used anywhere else.
+ *
+ * @return array decoded key => value pairs
+ */
+ private function decodedParamValues(array $paramNames, Url $url): array
+ {
+ $params = [];
+ foreach ($paramNames as $param) {
+ $val = $url->getParam($param);
+
+ if ($val !== null) {
+ $params[$param] = $val;
+ }
+ }
+
+ return $params;
+ }
}
diff --git a/vendor/ipl/web/src/Control/PaginationControl.php b/vendor/ipl/web/src/Control/PaginationControl.php
index e704829..85019a5 100644
--- a/vendor/ipl/web/src/Control/PaginationControl.php
+++ b/vendor/ipl/web/src/Control/PaginationControl.php
@@ -4,9 +4,13 @@ namespace ipl\Web\Control;
use ipl\Html\BaseHtmlElement;
use ipl\Html\Html;
+use ipl\Html\TemplateString;
+use ipl\Html\ValidHtml;
+use ipl\I18n\Translation;
use ipl\Stdlib\Contract\Paginatable;
use ipl\Web\Compat\CompatForm;
use ipl\Web\Url;
+use ipl\Web\Widget\ButtonLink;
use ipl\Web\Widget\Icon;
/**
@@ -17,6 +21,8 @@ use ipl\Web\Widget\Icon;
*/
class PaginationControl extends BaseHtmlElement
{
+ use Translation;
+
/** @var string Default page parameter */
public const DEFAULT_PAGE_PARAM = 'page';
@@ -29,9 +35,6 @@ class PaginationControl extends BaseHtmlElement
/** @var string Name of the URL parameter which holds the page size. If given, overrides {@link $defaultPageSize} */
protected $pageSizeParam = 'limit';
- /** @var string */
- protected $pageSpacer = '…';
-
/** @var Paginatable The pagination adapter which handles the underlying data source */
protected $paginatable;
@@ -122,6 +125,26 @@ class PaginationControl extends BaseHtmlElement
return $this;
}
+ /**
+ * Get message content to show when the list is empty
+ *
+ * @return ?ValidHtml Content is returned when given page is out of range, null otherwise
+ */
+ public function getEmptyStateMessage(): ?ValidHtml
+ {
+ $currentPage = $this->getCurrentPageNumber();
+ $pageCount = $this->getPageCount();
+ if ($pageCount && $pageCount < $currentPage) {
+ return TemplateString::create(
+ $this->translate('Page %d is out of range. {{#button}}Navigate to first page{{/button}}'),
+ $currentPage,
+ ['button' => new ButtonLink(null, $this->url->without('page'))]
+ );
+ }
+
+ return null;
+ }
+
/**
* Get the name of the URL parameter which stores the page size
*
@@ -378,12 +401,6 @@ class PaginationControl extends BaseHtmlElement
return $nextItem;
}
- /** @TODO(el): Use ipl-translation when it's ready instead */
- private function translate($message)
- {
- return $message;
- }
-
/**
* Create and return the first page item
*
@@ -460,30 +477,42 @@ class PaginationControl extends BaseHtmlElement
{
$currentPageNumber = $this->getCurrentPageNumber();
- $form = new CompatForm($this->url);
+ $form = new CompatForm();
$form->addAttributes(['class' => 'inline']);
$form->setMethod('GET');
$select = Html::tag('select', [
'name' => $this->getPageParam(),
'class' => 'autosubmit',
- 'title' => t('Go to page …')
+ 'title' => $this->translate('Go to page …')
]);
- if ($currentPageNumber === 1 || $currentPageNumber === $this->getPageCount()) {
+ $pageCount = $this->getPageCount();
+
+ if ($currentPageNumber === 1 || $currentPageNumber === $pageCount) {
$select->add(Html::tag('option', ['disabled' => '', 'selected' => ''], '…'));
}
- foreach (range(2, $this->getPageCount() - 1) as $page) {
- $option = Html::tag('option', [
- 'value' => $page
- ], $page);
+ if (2 <= $pageCount - 1) {
+ foreach (range(2, $pageCount - 1) as $page) {
+ $option = Html::tag('option', [
+ 'value' => $page
+ ], $page);
- if ($page == $currentPageNumber) {
- $option->addAttributes(['selected' => '']);
+ if ($page == $currentPageNumber) {
+ $option->addAttributes(['selected' => '']);
+ }
+
+ $select->add($option);
}
+ }
- $select->add($option);
+ if ($currentPageNumber > $pageCount) {
+ $select->add(Html::tag('option', [
+ 'value' => $currentPageNumber,
+ 'selected' => '',
+ 'disabled' => ''
+ ], $currentPageNumber));
}
$form->add($select);
diff --git a/vendor/ipl/web/src/Control/SearchBar/Suggestions.php b/vendor/ipl/web/src/Control/SearchBar/Suggestions.php
index fe4a2db..4dba21a 100644
--- a/vendor/ipl/web/src/Control/SearchBar/Suggestions.php
+++ b/vendor/ipl/web/src/Control/SearchBar/Suggestions.php
@@ -8,7 +8,6 @@ use ipl\Html\Attributes;
use ipl\Html\BaseHtmlElement;
use ipl\Html\FormattedString;
use ipl\Html\FormElement\ButtonElement;
-use ipl\Html\FormElement\InputElement;
use ipl\Html\HtmlElement;
use ipl\Html\Text;
use ipl\Stdlib\Contract\Paginatable;
@@ -126,7 +125,7 @@ abstract class Suggestions extends BaseHtmlElement
$logicalSep = [
'label' => QueryString::getRuleSymbol($filter),
'search' => QueryString::getRuleSymbol($filter),
- 'class' => 'logical_operator',
+ 'class' => 'logical-operator',
'type' => 'logical_operator'
];
@@ -137,14 +136,14 @@ abstract class Suggestions extends BaseHtmlElement
'search' => '(',
'label' => '(',
'type' => 'grouping_operator',
- 'class' => 'grouping_operator_open'
+ 'class' => 'grouping-operator-open'
];
$terms = array_merge($terms, $this->filterToTerms($child));
$terms[] = [
'search' => ')',
'label' => ')',
'type' => 'grouping_operator',
- 'class' => 'grouping_operator_close'
+ 'class' => 'grouping-operator-close'
];
} else {
/** @var Filter\Condition $child */
@@ -191,7 +190,7 @@ abstract class Suggestions extends BaseHtmlElement
$attributes['data-type'] = $this->type;
}
- $button = new ButtonElement(null, $attributes);
+ $button = new ButtonElement('', $attributes);
if (isset($this->default['type']) && $this->default['type'] === 'terms') {
$terms = $this->filterToTerms($this->default['terms']);
$list = new HtmlElement('ul', Attributes::create(['class' => 'comma-separated']));
@@ -242,11 +241,17 @@ abstract class Suggestions extends BaseHtmlElement
$data = new LimitIterator(new IteratorIterator($this->data), 0, self::DEFAULT_LIMIT);
}
+ $noDefault = null;
foreach ($data as $term => $meta) {
if (is_int($term)) {
$term = $meta;
}
+ if ($this->searchTerm) {
+ // Only the first exact match will set this to true, any other to false
+ $noDefault = $noDefault === null && $term === $this->searchTerm;
+ }
+
$attributes = [
'type' => 'button',
'tabindex' => -1,
@@ -270,7 +275,7 @@ abstract class Suggestions extends BaseHtmlElement
$attributes['data-label'] = $meta;
}
- $button = (new ButtonElement(null, $attributes))
+ $button = (new ButtonElement('', $attributes))
->setAttribute('value', $label)
->addHtml(Text::create($label));
if ($this->type === 'column' && $this->shouldShowRelationFor($term)) {
@@ -290,14 +295,6 @@ abstract class Suggestions extends BaseHtmlElement
$this->getAttributes()->add('class', 'has-more');
}
- $showDefault = true;
- if ($this->searchTerm && $this->count() === 1) {
- // The default option is only shown if the user's input does not result in an exact match
- $input = $this->getFirst('li')->getFirst('button');
- $showDefault = $input->getContent() != $this->searchTerm
- && $input->getAttributes()->get('data-search')->getValue() != $this->searchTerm;
- }
-
if ($this->type === 'column' && ! $this->isEmpty() && ! $this->getFirst('li')->getAttributes()->has('class')) {
// The column title is only added if there are any suggestions and the first item is not a title already
$this->prependHtml(new HtmlElement(
@@ -307,7 +304,7 @@ abstract class Suggestions extends BaseHtmlElement
));
}
- if ($showDefault) {
+ if (! $noDefault) {
$this->assembleDefault();
}
diff --git a/vendor/ipl/web/src/Control/SearchBar/Terms.php b/vendor/ipl/web/src/Control/SearchBar/Terms.php
index c81e336..c7a9ce8 100644
--- a/vendor/ipl/web/src/Control/SearchBar/Terms.php
+++ b/vendor/ipl/web/src/Control/SearchBar/Terms.php
@@ -81,7 +81,7 @@ class Terms extends BaseHtmlElement
if ($i > 0) {
$logicalOperator = QueryString::getRuleSymbol($filters);
$this->assembleTerm([
- 'class' => 'logical_operator',
+ 'class' => 'logical-operator',
'type' => 'logical_operator',
'search' => $logicalOperator,
'label' => $logicalOperator
@@ -110,7 +110,7 @@ class Terms extends BaseHtmlElement
if ($chain instanceof Filter\None) {
$this->assembleTerm([
- 'class' => 'logical_operator',
+ 'class' => 'logical-operator',
'type' => 'negation_operator',
'search' => '!',
'label' => '!'
@@ -119,7 +119,7 @@ class Terms extends BaseHtmlElement
if ($wrap) {
$opening = $this->assembleTerm([
- 'class' => 'grouping_operator_open',
+ 'class' => 'grouping-operator-open',
'type' => 'grouping_operator',
'search' => '(',
'label' => '('
@@ -130,7 +130,7 @@ class Terms extends BaseHtmlElement
if ($wrap) {
$closing = $this->assembleTerm([
- 'class' => 'grouping_operator_close',
+ 'class' => 'grouping-operator-close',
'type' => 'grouping_operator',
'search' => ')',
'label' => ')'
diff --git a/vendor/ipl/web/src/Control/SearchEditor.php b/vendor/ipl/web/src/Control/SearchEditor.php
index f975471..19bdd14 100644
--- a/vendor/ipl/web/src/Control/SearchEditor.php
+++ b/vendor/ipl/web/src/Control/SearchEditor.php
@@ -8,18 +8,23 @@ use ipl\Html\FormDecorator\CallbackDecorator;
use ipl\Html\HtmlDocument;
use ipl\Html\HtmlElement;
use ipl\Html\Text;
+use ipl\I18n\Translation;
use ipl\Stdlib\Events;
use ipl\Stdlib\Filter;
+use ipl\Web\Compat\StyleWithNonce;
use ipl\Web\Control\SearchBar\SearchException;
use ipl\Web\Filter\Parser;
use ipl\Web\Filter\QueryString;
use ipl\Web\Filter\Renderer;
+use ipl\Web\Style;
use ipl\Web\Url;
+use ipl\Web\Widget\IcingaIcon;
use ipl\Web\Widget\Icon;
class SearchEditor extends Form
{
use Events;
+ use Translation;
/** @var string Emitted for every validated column */
const ON_VALIDATE_COLUMN = 'validate-column';
@@ -44,6 +49,9 @@ class SearchEditor extends Form
/** @var Filter\Rule */
protected $filter;
+ /** @var ?Style */
+ protected ?Style $style = null;
+
/** @var bool */
protected $cleared = false;
@@ -117,6 +125,20 @@ class SearchEditor extends Form
return $this->filter;
}
+ /**
+ * Get inline stylesheet
+ *
+ * @return Style
+ */
+ protected function getStyle(): Style
+ {
+ if ($this->style === null) {
+ $this->style = new StyleWithNonce();
+ }
+
+ return $this->style;
+ }
+
public function populate($values)
{
// applyChanges() is basically this form's own populate implementation, hence
@@ -124,6 +146,10 @@ class SearchEditor extends Form
$filter = (new Parser(isset($values['filter']) ? $values['filter'] : $this->queryString))
->setStrict()
->parse();
+ if (! $filter instanceof Filter\Chain) {
+ $filter = Filter::all($filter);
+ }
+
$filter = $this->applyChanges($filter, $values);
parent::populate($values);
@@ -339,51 +365,48 @@ class SearchEditor extends Form
return $rule;
}
- protected function createTree(Filter\Rule $rule, array $path = [0])
+ protected function createTree(Filter\Rule $rule, array $path = [0], bool $draggable = false)
{
$identifier = 'rule-' . join('-', $path);
if ($rule instanceof Filter\Condition) {
$parts = [$this->createCondition($rule, $identifier), $this->createButtons($rule, $identifier)];
- if (count($path) === 1) {
- $item = new HtmlElement('ol', null, new HtmlElement(
- 'li',
- Attributes::create(['id' => $identifier]),
- ...$parts
- ));
- } else {
- array_splice($parts, 1, 0, [
- new Icon('bars', ['class' => 'drag-initiator'])
- ]);
-
- $item = (new HtmlDocument())->addHtml(...$parts);
+ if ($draggable) {
+ array_unshift($parts, new Icon('bars', ['class' => 'drag-initiator']));
}
+
+ $item = (new HtmlDocument())->addHtml(...$parts);
} else {
/** @var Filter\Chain $rule */
$item = new HtmlElement('ul');
$groupOperatorInput = $this->createElement('select', $identifier, [
'options' => [
- '&' => 'ALL',
- '|' => 'ANY',
- '!' => 'NONE'
+ '&' => $this->translate('AND'),
+ '|' => $this->translate('OR'),
+ '!' => $this->translate('NOT')
],
'value' => $rule instanceof Filter\None ? '!' : QueryString::getRuleSymbol($rule)
]);
$this->registerElement($groupOperatorInput);
$item->addHtml(HtmlElement::create('li', ['id' => $identifier], [
- $groupOperatorInput,
- count($path) > 1
+ $draggable
? new Icon('bars', ['class' => 'drag-initiator'])
: null,
+ $groupOperatorInput,
$this->createButtons($rule, $identifier)
]));
$children = new HtmlElement('ol');
$item->addHtml(new HtmlElement('li', null, $children));
+ $this->getStyle()->addFor($children, [
+ '--depth' => sprintf('%dem', count($path))
+ ]);
+
$i = 0;
+ $draggableChildren = count($path) > 1 || $rule->count() > 1;
foreach ($rule as $child) {
$childPath = $path;
$childPath[] = $i++;
@@ -395,7 +418,7 @@ class SearchEditor extends Form
? 'filter-condition'
: 'filter-chain'
]),
- $this->createTree($child, $childPath)
+ $this->createTree($child, $childPath, $draggableChildren)
));
}
}
@@ -410,38 +433,47 @@ class SearchEditor extends Form
if ($for instanceof Filter\Chain) {
$buttons[] = $this->createElement('submitButton', 'structural-change', [
'value' => 'add-condition:' . $identifier,
- 'label' => t('Add Condition', 'to a group of filter conditions'),
+ 'title' => $this->translate('Append Condition', 'to a group of filter conditions'),
+ 'label' => new IcingaIcon('add-inside'),
+ 'class' => 'control-button',
'formnovalidate' => true
]);
$buttons[] = $this->createElement('submitButton', 'structural-change', [
'value' => 'add-group:' . $identifier,
- 'label' => t('Add Group', 'of filter conditions'),
+ 'title' => $this->translate('Append Group', 'of filter conditions'),
+ 'label' => new IcingaIcon('insert-group'),
+ 'class' => 'control-button',
'formnovalidate' => true
]);
+
+ $wrapTitle = $this->translate('Wrap Group in Group', 'of filter conditions');
+ $removeTitle = $this->translate('Remove Group', 'of filter conditions');
+ } else {
+ $wrapTitle = $this->translate('Wrap Condition in Group', 'a filter rule');
+ $removeTitle = $this->translate('Remove Condition', 'a filter rule');
}
$buttons[] = $this->createElement('submitButton', 'structural-change', [
'value' => 'wrap-rule:' . $identifier,
- 'label' => t('Wrap in Group', 'a filter rule'),
+ 'label' => new IcingaIcon('wrap'),
+ 'class' => 'control-button',
+ 'title' => $wrapTitle,
'formnovalidate' => true
]);
$buttons[] = $this->createElement('submitButton', 'structural-change', [
'value' => 'drop-rule:' . $identifier,
- 'label' => t('Delete', 'a filter rule'),
+ 'label' => new Icon('trash'),
+ 'class' => ['control-button', 'remove-button'],
+ 'title' => $removeTitle,
'formnovalidate' => true
]);
- $ul = new HtmlElement('ul');
+ $ul = new HtmlElement('ul', Attributes::create(['class' => 'buttons']));
foreach ($buttons as $button) {
$ul->addHtml(new HtmlElement('li', null, $button));
}
- return new HtmlElement(
- 'div',
- Attributes::create(['class' => 'buttons']),
- $ul,
- new Icon('ellipsis-h')
- );
+ return $ul;
}
protected function createCondition(Filter\Condition $condition, $identifier)
@@ -460,7 +492,8 @@ class SearchEditor extends Form
'autocomplete' => 'off',
'data-type' => 'column',
'data-enrichment-type' => 'completion',
- 'data-term-suggestions' => '#search-editor-suggestions'
+ 'data-term-suggestions' => '#search-editor-suggestions',
+ 'placeholder' => $this->translate('Start typing to search for a column')
]);
$columnInput->getAttributes()->registerAttributeCallback('data-suggest-url', function () {
return (string) $this->getSuggestionUrl();
@@ -537,7 +570,8 @@ class SearchEditor extends Form
'autocomplete' => 'off',
'data-type' => 'value',
'data-enrichment-type' => 'completion',
- 'data-term-suggestions' => '#search-editor-suggestions'
+ 'data-term-suggestions' => '#search-editor-suggestions',
+ 'placeholder' => $this->translate('Start typing to search for a value')
]);
$valueInput->getAttributes()->registerAttributeCallback('data-suggest-url', function () {
return (string) $this->getSuggestionUrl();
@@ -561,6 +595,8 @@ class SearchEditor extends Form
protected function assemble()
{
+ $this->addHtml($this->getStyle());
+
$filterInput = $this->createElement('hidden', 'filter');
$filterInput->getAttributes()->registerAttributeCallback(
'value',
@@ -572,8 +608,12 @@ class SearchEditor extends Form
$this->addElement($filterInput);
$filter = $this->getFilter();
- if ($filter instanceof Filter\Chain && $filter->isEmpty()) {
- $filter = Filter::equal('', '');
+ if ($filter instanceof Filter\Chain) {
+ if ($filter->isEmpty()) {
+ $filter->add(Filter::equal('', ''));
+ }
+ } else {
+ $filter = Filter::all($filter);
}
$this->addHtml($this->createTree($filter));
@@ -586,13 +626,13 @@ class SearchEditor extends Form
$this->addHtml($this->createElement('submitButton', 'structural-change', [
'value' => 'clear:rule-0',
'class' => 'cancel-button',
- 'label' => t('Clear Filter'),
+ 'label' => $this->translate('Clear Filter'),
'formnovalidate' => true
]));
}
$this->addElement('submit', 'btn_submit', [
- 'label' => t('Apply')
+ 'label' => $this->translate('Apply')
]);
// Add submit button also as first element to make Web 2 submit
diff --git a/vendor/ipl/web/src/Control/SortControl.php b/vendor/ipl/web/src/Control/SortControl.php
index 65c2c3d..b5cabd8 100644
--- a/vendor/ipl/web/src/Control/SortControl.php
+++ b/vendor/ipl/web/src/Control/SortControl.php
@@ -7,11 +7,11 @@ use ipl\Html\Form;
use ipl\Html\FormDecorator\DivDecorator;
use ipl\Html\FormElement\ButtonElement;
use ipl\Html\HtmlElement;
+use ipl\I18n\Translation;
use ipl\Orm\Common\SortUtil;
use ipl\Orm\Query;
use ipl\Stdlib\Str;
use ipl\Web\Common\FormUid;
-use ipl\Web\Url;
use ipl\Web\Widget\Icon;
use Psr\Http\Message\ServerRequestInterface;
@@ -21,6 +21,7 @@ use Psr\Http\Message\ServerRequestInterface;
class SortControl extends Form
{
use FormUid;
+ use Translation;
/** @var string Default sort param */
public const DEFAULT_SORT_PARAM = 'sort';
@@ -30,13 +31,6 @@ class SortControl extends Form
/** @var string Name of the URL parameter which stores the sort column */
protected $sortParam = self::DEFAULT_SORT_PARAM;
- /**
- * @var Url Request URL
- * @deprecated Access {@see self::getRequest()} instead.
- * @todo Remove once cube calls {@see self::handleRequest()}.
- */
- protected $url;
-
/** @var array Possible sort columns as sort string-value pairs */
private $columns;
@@ -49,14 +43,12 @@ class SortControl extends Form
* Create a new sort control
*
* @param array $columns Possible sort columns
- * @param Url $url Request URL
*
* @internal Use {@see self::create()} instead.
*/
- private function __construct(array $columns, Url $url)
+ private function __construct(array $columns)
{
$this->setColumns($columns);
- $this->url = $url;
}
/**
@@ -73,14 +65,12 @@ class SortControl extends Form
$normalized[SortUtil::normalizeSortSpec($spec)] = $label;
}
- $self = new static($normalized, Url::fromRequest());
+ $self = new static($normalized);
$self->on(self::ON_REQUEST, function (ServerRequestInterface $request) use ($self) {
- if (! $self->hasBeenSent()) {
- // If the form is submitted by POST, handleRequest() won't access the URL, so we have to
- if (($sort = $request->getQueryParams()[$self->getSortParam()] ?? null)) {
- $self->populate([$self->getSortParam() => $sort]);
- }
+ // If the form is submitted by POST, handleRequest() won't access the URL, so we have to
+ if (($sort = $request->getQueryParams()[$self->getSortParam()] ?? null)) {
+ $self->populate([$self->getSortParam() => $sort]);
}
});
@@ -168,12 +158,7 @@ class SortControl extends Form
*/
public function getSort(): ?string
{
- if ($this->getRequest() === null) {
- $sort = $this->url->getParam($this->getSortParam(), $this->getDefault());
- } else {
- $sort = $this->getPopulatedValue($this->getSortParam(), $this->getDefault());
- }
-
+ $sort = $this->getPopulatedValue($this->getSortParam(), $this->getDefault());
if (! empty($sort)) {
$columns = $this->getColumns();
@@ -203,12 +188,6 @@ class SortControl extends Form
*/
public function apply(Query $query, $defaultSort = null): self
{
- if ($this->getRequest() === null) {
- // handleRequest() has not been called yet
- // TODO: Remove this once everything using this requires ipl v0.12.0
- $this->handleRequest(ServerRequest::fromGlobals());
- }
-
$default = $defaultSort ?? (array) $query->getModel()->getDefaultSort();
if (! empty($default)) {
$this->setDefault(SortUtil::normalizeSortSpec($default));
@@ -222,7 +201,16 @@ class SortControl extends Form
return $this;
}
- protected function assemble()
+ /**
+ * Prepare the visual representation of the sort control
+ *
+ * This is called just before rendering happens. What is being done here, doesn't influence validity in any way.
+ * So there is no need to have the result already at hand during validation. Instead, delaying it allows
+ * to influence the visual result as long as possible.
+ *
+ * @return void
+ */
+ protected function prepareContent(): void
{
$columns = $this->getColumns();
$sort = $this->getSort();
@@ -266,7 +254,7 @@ class SortControl extends Form
$this->addElement('select', $this->getSortParam(), [
'class' => 'autosubmit',
- 'label' => 'Sort By',
+ 'label' => $this->translate('Sort By'),
'options' => $columns,
'value' => $value
]);
@@ -278,16 +266,26 @@ class SortControl extends Form
$toggleButton = new ButtonElement($this->getSortParam(), [
'class' => 'control-button spinner',
- 'title' => t('Change sort direction'),
+ 'title' => $this->translate('Change sort direction'),
'type' => 'submit',
'value' => implode(',', array_merge(["{$column} {$toggleDirection}"], $sort))
]);
$toggleButton->add(new Icon($toggleIcon));
$this->addHtml($toggleButton);
+ }
+ protected function assemble()
+ {
if ($this->getMethod() === 'POST' && $this->hasAttribute('name')) {
$this->addElement($this->createUidElement());
}
}
+
+ public function renderUnwrapped()
+ {
+ $this->prepareContent();
+
+ return parent::renderUnwrapped();
+ }
}
diff --git a/vendor/ipl/web/src/FormDecorator/IcingaFormDecorator.php b/vendor/ipl/web/src/FormDecorator/IcingaFormDecorator.php
index f038931..397640d 100644
--- a/vendor/ipl/web/src/FormDecorator/IcingaFormDecorator.php
+++ b/vendor/ipl/web/src/FormDecorator/IcingaFormDecorator.php
@@ -4,6 +4,7 @@ namespace ipl\Web\FormDecorator;
use Icinga\Web\Window;
use ipl\Html\Attributes;
+use ipl\Html\Contract\FormElementDecoration;
use ipl\Html\Contract\FormSubmitElement;
use ipl\Html\FormDecorator\DivDecorator;
use ipl\Html\FormElement\CheckboxElement;
@@ -12,8 +13,13 @@ use ipl\Html\HtmlDocument;
use ipl\Html\HtmlElement;
use ipl\Html\HtmlString;
use ipl\Html\Text;
+use ipl\Web\Compat\CompatForm;
use ipl\Web\Widget\Icon;
+/**
+ * @deprecated Use {@see FormElementDecoration} decorators by calling {@see CompatForm::applyDefaultElementDecorators()}
+ * instead.
+ */
class IcingaFormDecorator extends DivDecorator
{
const SUBMIT_ELEMENT_CLASS = 'form-controls';
diff --git a/vendor/ipl/web/src/FormElement/ScheduleElement.php b/vendor/ipl/web/src/FormElement/ScheduleElement.php
index f872f49..8ef8ee7 100644
--- a/vendor/ipl/web/src/FormElement/ScheduleElement.php
+++ b/vendor/ipl/web/src/FormElement/ScheduleElement.php
@@ -16,7 +16,6 @@ use ipl\Validator\CallbackValidator;
use ipl\Web\FormElement\ScheduleElement\AnnuallyFields;
use ipl\Web\FormElement\ScheduleElement\Common\FieldsProtector;
use ipl\Web\FormElement\ScheduleElement\MonthlyFields;
-use ipl\Web\FormElement\ScheduleElement\Recurrence;
use ipl\Web\FormElement\ScheduleElement\WeeklyFields;
use LogicException;
use Psr\Http\Message\RequestInterface;
@@ -65,29 +64,9 @@ class ScheduleElement extends FieldsetElement
protected function init(): void
{
+ $this->addDefaultPluginLoader('element', 'ipl\\Web\\FormElement\\ScheduleElement', '');
+
$this->start = new DateTime();
- $this->weeklyField = new WeeklyFields('weekly-fields', [
- 'default' => $this->start->format('D'),
- 'protector' => function (string $day) {
- return $this->protectId($day);
- },
- ]);
-
- $this->monthlyFields = new MonthlyFields('monthly-fields', [
- 'default' => $this->start->format('j'),
- 'availableFields' => (int) $this->start->format('t'),
- 'protector' => function ($day) {
- return $this->protectId($day);
- }
- ]);
-
- $this->annuallyFields = new AnnuallyFields('annually-fields', [
- 'default' => $this->start->format('M'),
- 'protector' => function ($month) {
- return $this->protectId($month);
- }
- ]);
-
$this->regulars = [
RRule::MINUTELY => $this->translate('Minutely'),
@@ -108,6 +87,64 @@ class ScheduleElement extends FieldsetElement
];
}
+ /**
+ * Create and return the weekly fields element
+ *
+ * @return WeeklyFields
+ */
+ protected function weeklyField(): WeeklyFields
+ {
+ if ($this->weeklyField === null) {
+ $this->weeklyField = $this->createElement('weeklyFields', 'weekly-fields', [
+ 'default' => $this->start->format('D'),
+ 'protector' => function (string $day) {
+ return $this->protectId($day);
+ },
+ ]);
+ }
+
+ return $this->weeklyField;
+ }
+
+ /**
+ * Create and return the monthly fields element
+ *
+ * @return MonthlyFields
+ */
+ protected function monthlyFields(): MonthlyFields
+ {
+ if ($this->monthlyFields === null) {
+ $this->monthlyFields = $this->createElement('monthlyFields', 'monthly-fields', [
+ 'default' => $this->start->format('j'),
+ 'availableFields' => (int) $this->start->format('t'),
+ 'protector' => function ($day) {
+ return $this->protectId($day);
+ }
+ ]);
+ }
+
+ return $this->monthlyFields;
+ }
+
+ /**
+ * Create and return the annually fields element
+ *
+ * @return AnnuallyFields
+ */
+ protected function annuallyFields(): AnnuallyFields
+ {
+ if ($this->annuallyFields === null) {
+ $this->annuallyFields = $this->createElement('annuallyFields', 'annually-fields', [
+ 'default' => $this->start->format('M'),
+ 'protector' => function ($month) {
+ return $this->protectId($month);
+ }
+ ]);
+ }
+
+ return $this->annuallyFields;
+ }
+
/**
* Get whether this element is rendering a cron expression
*
@@ -190,9 +227,9 @@ class ScheduleElement extends FieldsetElement
$this->start = $start;
// Forward the start time update to the sub elements as well!
- $this->weeklyField->setDefault($start->format('D'));
- $this->annuallyFields->setDefault($start->format('M'));
- $this->monthlyFields
+ $this->weeklyField()->setDefault($start->format('D'));
+ $this->annuallyFields()->setDefault($start->format('M'));
+ $this->monthlyFields()
->setDefault((int) $start->format('j'))
->setAvailableFields((int) $start->format('t'));
@@ -237,16 +274,16 @@ class ScheduleElement extends FieldsetElement
break;
case RRule::WEEKLY:
- $byDay = implode(',', $this->weeklyField->getSelectedWeekDays());
+ $byDay = implode(',', $this->weeklyField()->getSelectedWeekDays());
$rule = new RRule("FREQ=WEEKLY;INTERVAL=$interval;BYDAY=$byDay");
break;
/** @noinspection PhpMissingBreakStatementInspection */
case RRule::MONTHLY:
- $runsOn = $this->monthlyFields->getValue('runsOn', MonthlyFields::RUNS_EACH);
+ $runsOn = $this->monthlyFields()->getValue('runsOn', MonthlyFields::RUNS_EACH);
if ($runsOn === MonthlyFields::RUNS_EACH) {
- $byMonth = implode(',', $this->monthlyFields->getSelectedDays());
+ $byMonth = implode(',', $this->monthlyFields()->getSelectedDays());
$rule = new RRule("FREQ=MONTHLY;INTERVAL=$interval;BYMONTHDAY=$byMonth");
@@ -256,8 +293,8 @@ class ScheduleElement extends FieldsetElement
case RRule::YEARLY:
$rule = "FREQ=MONTHLY;INTERVAL=$interval;";
if ($customFrequency === RRule::YEARLY) {
- $runsOn = $this->annuallyFields->getValue('runsOnThe', 'n');
- $month = $this->annuallyFields->getValue('month', (int) $this->start->format('m'));
+ $runsOn = $this->annuallyFields()->getValue('runsOnThe', 'n');
+ $month = $this->annuallyFields()->getValue('month', (int) $this->start->format('m'));
if (is_string($month)) {
$datetime = DateTime::createFromFormat('!M', $month);
if (! $datetime) {
@@ -275,9 +312,9 @@ class ScheduleElement extends FieldsetElement
}
}
- $element = $this->monthlyFields;
+ $element = $this->monthlyFields();
if ($customFrequency === RRule::YEARLY) {
- $element = $this->annuallyFields;
+ $element = $this->annuallyFields();
}
$runDay = $element->getValue('day', $element::$everyDay);
@@ -355,7 +392,7 @@ class ScheduleElement extends FieldsetElement
if (! $rule->getByDay() || empty($rule->getByDay())) {
$this->setFrequency(RRule::WEEKLY);
} else {
- $values['weekly-fields'] = $this->weeklyField->loadWeekDays($rule->getByDay());
+ $values['weekly-fields'] = $this->weeklyField()->loadWeekDays($rule->getByDay());
$this
->setFrequency(static::CUSTOM_EXPR)
->setCustomFrequency(RRule::WEEKLY);
@@ -369,10 +406,10 @@ class ScheduleElement extends FieldsetElement
$this->setFrequency(static::CUSTOM_EXPR);
if ($isMonthly) {
- $values['monthly-fields'] = $this->monthlyFields->loadRRule($rule);
+ $values['monthly-fields'] = $this->monthlyFields()->loadRRule($rule);
$this->setCustomFrequency(RRule::MONTHLY);
} else {
- $values['annually-fields'] = $this->annuallyFields->loadRRule($rule);
+ $values['annually-fields'] = $this->annuallyFields()->loadRRule($rule);
$this->setCustomFrequency(RRule::YEARLY);
}
} elseif ($isMonthly && $rule->getInterval() === 3) {
@@ -463,16 +500,16 @@ class ScheduleElement extends FieldsetElement
break;
case RRule::WEEKLY:
$this->assembleCommonElements();
- $this->addElement($this->weeklyField);
+ $this->addElement($this->weeklyField());
break;
case RRule::MONTHLY:
$this->assembleCommonElements();
- $this->addElement($this->monthlyFields);
+ $this->addElement($this->monthlyFields());
break;
case RRule::YEARLY:
- $this->addElement($this->annuallyFields);
+ $this->addElement($this->annuallyFields());
}
} elseif ($this->hasCronExpression()) {
$this->addElement('text', 'cron_expression', [
@@ -495,7 +532,9 @@ class ScheduleElement extends FieldsetElement
if ($this->getFrequency() !== static::NO_REPEAT && ! $this->hasCronExpression()) {
$this->addElement(
- new Recurrence('schedule-recurrences', [
+ 'recurrence',
+ 'schedule-recurrences',
+ [
'id' => $this->protectId('schedule-recurrences'),
'label' => $this->translate('Next occurrences'),
'validate' => function (): array {
@@ -511,15 +550,15 @@ class ScheduleElement extends FieldsetElement
$frequency = $this->getCustomFrequency();
switch ($frequency) {
case RRule::WEEKLY:
- $reason = current($this->weeklyField->getMessages());
+ $reason = current($this->weeklyField()->getMessages());
break;
case RRule::MONTHLY:
- $reason = current($this->monthlyFields->getMessages());
+ $reason = current($this->monthlyFields()->getMessages());
break;
default: // annually
- $reason = current($this->annuallyFields->getMessages());
+ $reason = current($this->annuallyFields()->getMessages());
break;
}
@@ -549,7 +588,7 @@ class ScheduleElement extends FieldsetElement
return $rule;
}
- ])
+ ]
);
}
}
@@ -620,7 +659,7 @@ class ScheduleElement extends FieldsetElement
&& $matches[1] === 'start'
) {
// To update the available fields/days based on the provided start time
- $partUpdates[] = $this->monthlyFields;
+ $partUpdates[] = $this->monthlyFields();
}
}
diff --git a/vendor/ipl/web/src/FormElement/ScheduleElement/AnnuallyFields.php b/vendor/ipl/web/src/FormElement/ScheduleElement/AnnuallyFields.php
index 857711a..ae0be84 100644
--- a/vendor/ipl/web/src/FormElement/ScheduleElement/AnnuallyFields.php
+++ b/vendor/ipl/web/src/FormElement/ScheduleElement/AnnuallyFields.php
@@ -46,6 +46,8 @@ class AnnuallyFields extends FieldsetElement
{
parent::init();
$this->initUtils();
+
+ $this->addDefaultPluginLoader('element', 'ipl\\Web\\FormElement\\ScheduleElement', '');
}
/**
@@ -70,7 +72,7 @@ class AnnuallyFields extends FieldsetElement
{
$this->getAttributes()->set('id', $this->protectId('annually-fields'));
- $fieldsSelector = new FieldsRadio('month', [
+ $fieldsSelector = $this->createElement('fieldsRadio', 'month', [
'class' => ['autosubmit', 'sr-only'],
'value' => $this->default,
'options' => $this->months,
@@ -79,22 +81,20 @@ class AnnuallyFields extends FieldsetElement
}
]);
$this->registerElement($fieldsSelector);
+ $this->decorate($fieldsSelector);
$runsOnThe = $this->getPopulatedValue('runsOnThe', 'n');
- $this->addElement('checkbox', 'runsOnThe', [
+ $checkbox = $this->createElement('checkbox', 'runsOnThe', [
'class' => 'autosubmit',
'value' => $runsOnThe
]);
+ $this->registerElement($checkbox);
+ $this->decorate($checkbox);
$checkboxControls = HtmlElement::create('div', ['class' => 'toggle-slider-controls']);
- $checkbox = $this->getElement('runsOnThe');
$checkbox->prependWrapper($checkboxControls);
$checkboxControls->addHtml($checkbox, HtmlElement::create('span', null, $this->translate('On the')));
- $annuallyWrapper = HtmlElement::create('div', ['class' => 'annually']);
- $checkboxControls->prependWrapper($annuallyWrapper);
- $annuallyWrapper->addHtml($fieldsSelector);
-
$notes = HtmlElement::create('div', ['class' => 'note']);
$notes->addHtml(
FormattedString::create(
@@ -103,23 +103,26 @@ class AnnuallyFields extends FieldsetElement
new Icon('arrow-right')
)
);
- $annuallyWrapper->addHtml($notes);
+ $annuallyWrapper = HtmlElement::create('div', ['class' => 'annually']);
+ $fieldsSelector->prependWrapper($annuallyWrapper);
+ $annuallyWrapper->addHtml($fieldsSelector, $notes);
+
+ $this->addHtml($fieldsSelector, $checkbox);
$enumerations = $this->createOrdinalElement();
$enumerations->getAttributes()->set('disabled', $runsOnThe === 'n');
$this->registerElement($enumerations);
+ $this->decorate($enumerations);
$selectableDays = $this->createOrdinalSelectableDays();
$selectableDays->getAttributes()->set('disabled', $runsOnThe === 'n');
$this->registerElement($selectableDays);
$ordinalWrapper = HtmlElement::create('div', ['class' => ['ordinal', 'annually']]);
- $this
- ->decorate($enumerations)
- ->addHtml($enumerations);
-
$enumerations->prependWrapper($ordinalWrapper);
$ordinalWrapper->addHtml($enumerations, $selectableDays);
+
+ $this->addHtml($enumerations);
}
protected function registerAttributeCallbacks(Attributes $attributes)
diff --git a/vendor/ipl/web/src/FormElement/ScheduleElement/MonthlyFields.php b/vendor/ipl/web/src/FormElement/ScheduleElement/MonthlyFields.php
index 26329fc..c85c460 100644
--- a/vendor/ipl/web/src/FormElement/ScheduleElement/MonthlyFields.php
+++ b/vendor/ipl/web/src/FormElement/ScheduleElement/MonthlyFields.php
@@ -108,7 +108,8 @@ class MonthlyFields extends FieldsetElement
foreach (range(1, $this->availableFields) as $day) {
$checkbox = $this->createElement('checkbox', "day$day", [
'class' => ['autosubmit', 'sr-only'],
- 'value' => $day === $this->default && $runsOn === static::RUNS_EACH
+ 'value' => $day === $this->default && $runsOn === static::RUNS_EACH,
+ 'decorators' => []
]);
$this->registerElement($checkbox);
diff --git a/vendor/ipl/web/src/FormElement/ScheduleElement/WeeklyFields.php b/vendor/ipl/web/src/FormElement/ScheduleElement/WeeklyFields.php
index 01933ca..47ddd41 100644
--- a/vendor/ipl/web/src/FormElement/ScheduleElement/WeeklyFields.php
+++ b/vendor/ipl/web/src/FormElement/ScheduleElement/WeeklyFields.php
@@ -102,7 +102,8 @@ class WeeklyFields extends FieldsetElement
foreach ($this->weekdays as $day => $value) {
$checkbox = $this->createElement('checkbox', $day, [
'class' => ['autosubmit', 'sr-only'],
- 'value' => $day === $this->default
+ 'value' => $day === $this->default,
+ 'decorators' => []
]);
$this->registerElement($checkbox);
diff --git a/vendor/ipl/web/src/FormElement/SearchSuggestions.php b/vendor/ipl/web/src/FormElement/SearchSuggestions.php
new file mode 100644
index 0000000..0218d43
--- /dev/null
+++ b/vendor/ipl/web/src/FormElement/SearchSuggestions.php
@@ -0,0 +1,279 @@
+provider = $provider;
+ }
+
+ /**
+ * Set a callback to identify groups for terms delivered by the provider
+ *
+ * The callback must return a string which is used as label for the group.
+ * Its interface is: `function (array $data): string`
+ *
+ * @param callable $callback
+ *
+ * @return $this
+ */
+ public function setGroupingCallback(callable $callback): self
+ {
+ $this->groupingCallback = $callback;
+
+ return $this;
+ }
+
+ /**
+ * Get the callback used to identify groups for terms delivered by the provider
+ *
+ * @return ?callable
+ */
+ public function getGroupingCallback(): ?callable
+ {
+ return $this->groupingCallback;
+ }
+
+ /**
+ * Set the search term (can contain `*` wildcards)
+ *
+ * @param string $term
+ *
+ * @return $this
+ */
+ public function setSearchTerm(string $term): self
+ {
+ $this->searchTerm = $term;
+ $this->setSearchPattern(
+ '/' . str_replace(
+ '\\000',
+ '.*',
+ preg_quote(
+ str_replace(
+ '*',
+ "\0",
+ $term
+ ),
+ '/'
+ )
+ ) . '/i'
+ );
+
+ return $this;
+ }
+
+ /**
+ * Get the search term
+ *
+ * @return ?string
+ */
+ public function getSearchTerm(): ?string
+ {
+ return $this->searchTerm;
+ }
+
+ /**
+ * Set the search pattern used by {@see matchSearch}
+ *
+ * @param string $pattern
+ *
+ * @return $this
+ */
+ protected function setSearchPattern(string $pattern): self
+ {
+ $this->searchPattern = $pattern;
+
+ return $this;
+ }
+
+ /**
+ * Set the original search value
+ *
+ * The one without automatically added wildcards.
+ *
+ * @param string $term
+ *
+ * @return $this
+ */
+ public function setOriginalSearchValue(string $term): self
+ {
+ $this->originalValue = $term;
+
+ return $this;
+ }
+
+ /**
+ * Get the original search value
+ *
+ * @return ?string
+ */
+ public function getOriginalSearchValue(): ?string
+ {
+ return $this->originalValue;
+ }
+
+ /**
+ * Set the terms to exclude in the suggestion list
+ *
+ * @param string[] $terms
+ *
+ * @return $this
+ */
+ public function setExcludeTerms(array $terms): self
+ {
+ $this->excludeTerms = $terms;
+
+ return $this;
+ }
+
+ /**
+ * Get the terms to exclude in the suggestion list
+ *
+ * @return string[]
+ */
+ public function getExcludeTerms(): array
+ {
+ return $this->excludeTerms;
+ }
+
+ /**
+ * Match the given search term against the users search
+ *
+ * @param string $term
+ *
+ * @return bool Whether the search matches or not
+ */
+ public function matchSearch(string $term): bool
+ {
+ if (! $this->searchPattern || $this->searchPattern === '.*') {
+ return true;
+ }
+
+ return (bool) preg_match($this->searchPattern, $term);
+ }
+
+ /**
+ * Load suggestions as requested by the client
+ *
+ * @param ServerRequestInterface $request
+ *
+ * @return $this
+ */
+ public function forRequest(ServerRequestInterface $request): self
+ {
+ if ($request->getMethod() !== 'POST') {
+ return $this;
+ }
+
+ /** @var array> $requestData */
+ $requestData = json_decode($request->getBody()->read(8192), true);
+ if (empty($requestData)) {
+ return $this;
+ }
+
+ $this->setSearchTerm($requestData['term']['label']);
+ $this->setOriginalSearchValue($requestData['term']['search']);
+ $this->setExcludeTerms($requestData['exclude'] ?? []);
+
+ return $this;
+ }
+
+ protected function assemble(): void
+ {
+ $groupingCallback = $this->getGroupingCallback();
+ if ($groupingCallback) {
+ $provider = yield_groups($this->provider, $groupingCallback);
+ } else {
+ $provider = [null => $this->provider];
+ }
+
+ /** @var iterable>> $provider */
+ foreach ($provider as $group => $suggestions) {
+ if ($group) {
+ $this->addHtml(
+ new HtmlElement(
+ 'li',
+ Attributes::create(['class' => 'suggestion-title']),
+ Text::create($group)
+ )
+ );
+ }
+
+ foreach ($suggestions as $data) {
+ $attributes = [
+ 'type' => 'button',
+ 'value' => $data['label'] ?? $data['search']
+ ];
+ foreach ($data as $name => $value) {
+ $attributes["data-$name"] = $value;
+ }
+
+ $this->addHtml(
+ new HtmlElement(
+ 'li',
+ null,
+ new HtmlElement(
+ 'input',
+ Attributes::create($attributes)
+ )
+ )
+ );
+ }
+ }
+
+ if ($this->isEmpty()) {
+ $this->addHtml(new HtmlElement(
+ 'li',
+ Attributes::create(['class' => 'nothing-to-suggest']),
+ new HtmlElement('em', null, Text::create($this->translate('Nothing to suggest')))
+ ));
+ }
+ }
+}
diff --git a/vendor/ipl/web/src/FormElement/SuggestionElement.php b/vendor/ipl/web/src/FormElement/SuggestionElement.php
new file mode 100644
index 0000000..30323a3
--- /dev/null
+++ b/vendor/ipl/web/src/FormElement/SuggestionElement.php
@@ -0,0 +1,86 @@
+ 'off',
+ 'class' => 'suggestion-element',
+ 'data-enrichment-type' => 'completion'
+ ];
+
+ /** @var ?Url URL to fetch suggestions from */
+ protected ?Url $suggestionsUrl = null;
+
+ /**
+ * Get the URL to fetch suggestions from
+ *
+ * @return Url
+ *
+ * @throws RuntimeException if the suggestionsUrl is not set
+ */
+ public function getSuggestionsUrl(): Url
+ {
+ if ($this->suggestionsUrl === null) {
+ throw new RuntimeException('SuggestionsUrl is not set');
+ }
+
+ return $this->suggestionsUrl;
+ }
+
+ /**
+ * Set the URL to fetch suggestions from
+ *
+ * @param Url $suggestionsUrl
+ *
+ * @return $this
+ */
+ public function setSuggestionsUrl(Url $suggestionsUrl): static
+ {
+ $this->suggestionsUrl = $suggestionsUrl;
+
+ return $this;
+ }
+
+ /**
+ * @return string If not set, returns a default placeholder
+ */
+ public function getPlaceholder(): string
+ {
+ return $this->placeholder ?? $this->translate('Start typing to see suggestions…');
+ }
+
+ protected function assemble(): void
+ {
+ $suggestionsId = uniqid('search-suggestions-');
+
+ $this->prependWrapper(
+ new HtmlElement(
+ 'div',
+ new Attributes(['class' => 'suggestion-element-group']),
+ new HtmlElement('div', new Attributes(['id' => $suggestionsId, 'class' => 'search-suggestions'])),
+ new HtmlElement('span', new Attributes(['class' => 'suggestion-element-icon']), new Icon('search'))
+ )
+ );
+
+ $this->getAttributes()->add([
+ 'data-term-suggestions' => '#' . $suggestionsId,
+ 'data-suggest-url' => $this->getSuggestionsUrl()
+ ]);
+ }
+
+ protected function registerAttributeCallbacks(Attributes $attributes): void
+ {
+ parent::registerAttributeCallbacks($attributes);
+
+ $attributes->registerAttributeCallback('suggestionsUrl', null, $this->setSuggestionsUrl(...));
+ }
+}
diff --git a/vendor/ipl/web/src/FormElement/TermInput.php b/vendor/ipl/web/src/FormElement/TermInput.php
index f1485c7..c1c4b87 100644
--- a/vendor/ipl/web/src/FormElement/TermInput.php
+++ b/vendor/ipl/web/src/FormElement/TermInput.php
@@ -2,6 +2,7 @@
namespace ipl\Web\FormElement;
+use ipl\Html\Attribute;
use ipl\Html\Attributes;
use ipl\Html\Form;
use ipl\Html\FormElement\FieldsetElement;
@@ -268,19 +269,25 @@ class TermInput extends FieldsetElement
if ($this->valueHasBeenPasted()) {
$updates[] = $this->termContainer();
$updates[] = [
- HtmlString::create(json_encode(['#' . $this->getName() . '-search-input', []])),
+ HtmlString::create(json_encode(
+ ['#' . Attribute::sanitizeId($this->getValueOfNameAttribute()) . '-search-input', []]
+ )),
'Behavior:InputEnrichment'
];
} elseif (! empty($this->changes)) {
$updates[] = [
- HtmlString::create(json_encode(['#' . $this->getName() . '-search-input', $this->changes])),
+ HtmlString::create(json_encode(
+ ['#' . Attribute::sanitizeId($this->getValueOfNameAttribute()) . '-search-input', $this->changes]
+ )),
'Behavior:InputEnrichment'
];
}
if (empty($updates) && $this->hasBeenAutoSubmitted()) {
$updates[] = $updates[] = [
- HtmlString::create(json_encode(['#' . $this->getName() . '-search-input', 'bogus'])),
+ HtmlString::create(json_encode(
+ ['#' . Attribute::sanitizeId($this->getValueOfNameAttribute()) . '-search-input', 'bogus']
+ )),
'Behavior:InputEnrichment'
];
}
@@ -314,8 +321,8 @@ class TermInput extends FieldsetElement
public function onRegistered(Form $form)
{
- $termContainerId = $this->getName() . '-terms';
- $mainInputId = $this->getName() . '-search-input';
+ $termContainerId = Attribute::sanitizeId($this->getValueOfNameAttribute()) . '-terms';
+ $mainInputId = Attribute::sanitizeId($this->getValueOfNameAttribute()) . '-search-input';
$autoSubmittedBy = $form->getRequest()->getHeader('X-Icinga-Autosubmittedby');
$this->hasBeenAutoSubmitted = in_array($mainInputId, $autoSubmittedBy, true)
@@ -384,7 +391,7 @@ class TermInput extends FieldsetElement
{
if ($this->termContainer === null) {
$this->termContainer = (new TermContainer($this))
- ->setAttribute('id', $this->getName() . '-terms');
+ ->setAttribute('id', Attribute::sanitizeId($this->getValueOfNameAttribute()) . '-terms');
}
return $this->termContainer;
@@ -392,7 +399,7 @@ class TermInput extends FieldsetElement
protected function assemble()
{
- $myName = $this->getName();
+ $myName = Attribute::sanitizeId($this->getValueOfNameAttribute());
$termInputId = $myName . '-term-input';
$dataInputId = $myName . '-data-input';
diff --git a/vendor/ipl/web/src/FormElement/TermInput/TermContainer.php b/vendor/ipl/web/src/FormElement/TermInput/TermContainer.php
index 0e0bb0e..8eabf0e 100644
--- a/vendor/ipl/web/src/FormElement/TermInput/TermContainer.php
+++ b/vendor/ipl/web/src/FormElement/TermInput/TermContainer.php
@@ -5,11 +5,15 @@ namespace ipl\Web\FormElement\TermInput;
use ipl\Html\Attributes;
use ipl\Html\BaseHtmlElement;
use ipl\Html\HtmlElement;
+use ipl\Html\Text;
+use ipl\I18n\Translation;
use ipl\Web\FormElement\TermInput;
use ipl\Web\Widget\Icon;
class TermContainer extends BaseHtmlElement
{
+ use Translation;
+
protected $tag = 'div';
protected $defaultAttributes = ['class' => 'terms'];
@@ -33,6 +37,12 @@ class TermContainer extends BaseHtmlElement
protected function assemble()
{
+ if ($this->input->getReadOnly()) {
+ $removeLabel = $this->translate('Remove');
+ // bind remove translation to DOM, this allows the JS part to make use of it
+ $this->setAttribute('data-remove-action-label', $removeLabel);
+ }
+
foreach ($this->input->getTerms() as $i => $term) {
$value = $term->getLabel() ?: $term->getSearchValue();
@@ -57,7 +67,16 @@ class TermContainer extends BaseHtmlElement
);
if ($this->input->getReadOnly()) {
$label->addHtml(
- new Icon('trash'),
+ new HtmlElement(
+ 'div',
+ Attributes::create(['class' => 'remove-action', 'title' => $removeLabel]),
+ new Icon('trash'),
+ new HtmlElement(
+ 'span',
+ Attributes::create(['class' => 'remove-action-label']),
+ new Text($removeLabel)
+ )
+ ),
new HtmlElement('span', Attributes::create(['class' => 'invalid-reason']))
);
}
diff --git a/vendor/ipl/web/src/FormElement/TermInput/TermSuggestions.php b/vendor/ipl/web/src/FormElement/TermInput/TermSuggestions.php
index 26b00ea..9a94b1c 100644
--- a/vendor/ipl/web/src/FormElement/TermInput/TermSuggestions.php
+++ b/vendor/ipl/web/src/FormElement/TermInput/TermSuggestions.php
@@ -2,280 +2,11 @@
namespace ipl\Web\FormElement\TermInput;
-use ipl\Html\Attributes;
-use ipl\Html\BaseHtmlElement;
-use ipl\Html\HtmlElement;
-use ipl\Html\Text;
-use ipl\I18n\Translation;
-use Psr\Http\Message\ServerRequestInterface;
-use Traversable;
+use ipl\Web\FormElement\SearchSuggestions;
-use function ipl\Stdlib\yield_groups;
-
-class TermSuggestions extends BaseHtmlElement
+/**
+ * @deprecated Use {@see SearchSuggestions} instead
+ */
+class TermSuggestions extends SearchSuggestions
{
- use Translation;
-
- protected $tag = 'ul';
-
- /** @var Traversable */
- protected $provider;
-
- /** @var ?callable */
- protected $groupingCallback;
-
- /** @var ?string */
- protected $searchTerm;
-
- /** @var ?string */
- protected $searchPattern;
-
- /** @var ?string */
- protected $originalValue;
-
- /** @var string[] */
- protected $excludeTerms = [];
-
- /**
- * Create new TermSuggestions
- *
- * The provider must deliver terms in form of arrays with the following keys:
- * * (required) search: The search value
- * * label: A human-readable label
- * * class: A CSS class
- * * title: A message shown upon hover on the term
- *
- * Any excess key is also transferred to the client, but currently unused.
- *
- * @param Traversable $provider
- */
- public function __construct(Traversable $provider)
- {
- $this->provider = $provider;
- }
-
- /**
- * Set a callback to identify groups for terms delivered by the provider
- *
- * The callback must return a string which is used as label for the group.
- * Its interface is: `function (array $data): string`
- *
- * @param callable $callback
- *
- * @return $this
- */
- public function setGroupingCallback(callable $callback): self
- {
- $this->groupingCallback = $callback;
-
- return $this;
- }
-
- /**
- * Get the callback used to identify groups for terms delivered by the provider
- *
- * @return ?callable
- */
- public function getGroupingCallback(): ?callable
- {
- return $this->groupingCallback;
- }
-
- /**
- * Set the search term (can contain `*` wildcards)
- *
- * @param string $term
- *
- * @return $this
- */
- public function setSearchTerm(string $term): self
- {
- $this->searchTerm = $term;
- $this->setSearchPattern(
- '/' . str_replace(
- '\\000',
- '.*',
- preg_quote(
- str_replace(
- '*',
- "\0",
- $term
- ),
- '/'
- )
- ) . '/i'
- );
-
- return $this;
- }
-
- /**
- * Get the search term
- *
- * @return ?string
- */
- public function getSearchTerm(): ?string
- {
- return $this->searchTerm;
- }
-
- /**
- * Set the search pattern used by {@see matchSearch}
- *
- * @param string $pattern
- *
- * @return $this
- */
- protected function setSearchPattern(string $pattern): self
- {
- $this->searchPattern = $pattern;
-
- return $this;
- }
-
- /**
- * Set the original search value
- *
- * The one without automatically added wildcards.
- *
- * @param string $term
- *
- * @return $this
- */
- public function setOriginalSearchValue(string $term): self
- {
- $this->originalValue = $term;
-
- return $this;
- }
-
- /**
- * Get the original search value
- *
- * @return ?string
- */
- public function getOriginalSearchValue(): ?string
- {
- return $this->originalValue;
- }
-
- /**
- * Set the terms to exclude in the suggestion list
- *
- * @param string[] $terms
- *
- * @return $this
- */
- public function setExcludeTerms(array $terms): self
- {
- $this->excludeTerms = $terms;
-
- return $this;
- }
-
- /**
- * Get the terms to exclude in the suggestion list
- *
- * @return string[]
- */
- public function getExcludeTerms(): array
- {
- return $this->excludeTerms;
- }
-
- /**
- * Match the given search term against the users search
- *
- * @param string $term
- *
- * @return bool Whether the search matches or not
- */
- public function matchSearch(string $term): bool
- {
- if (! $this->searchPattern || $this->searchPattern === '.*') {
- return true;
- }
-
- return (bool) preg_match($this->searchPattern, $term);
- }
-
- /**
- * Load suggestions as requested by the client
- *
- * @param ServerRequestInterface $request
- *
- * @return $this
- */
- public function forRequest(ServerRequestInterface $request): self
- {
- if ($request->getMethod() !== 'POST') {
- return $this;
- }
-
- /** @var array> $requestData */
- $requestData = json_decode($request->getBody()->read(8192), true);
- if (empty($requestData)) {
- return $this;
- }
-
- $this->setSearchTerm($requestData['term']['label']);
- $this->setOriginalSearchValue($requestData['term']['search']);
- $this->setExcludeTerms($requestData['exclude'] ?? []);
-
- return $this;
- }
-
- protected function assemble()
- {
- $groupingCallback = $this->getGroupingCallback();
- if ($groupingCallback) {
- $provider = yield_groups($this->provider, $groupingCallback);
- } else {
- $provider = [null => $this->provider];
- }
-
- /** @var iterable>> $provider */
- foreach ($provider as $group => $suggestions) {
- if ($group) {
- $this->addHtml(
- new HtmlElement(
- 'li',
- Attributes::create([
- 'class' => 'suggestion-title'
- ]),
- Text::create($group)
- )
- );
- }
-
- foreach ($suggestions as $data) {
- $attributes = [
- 'type' => 'button',
- 'value' => $data['label'] ?? $data['search']
- ];
- foreach ($data as $name => $value) {
- $attributes["data-$name"] = $value;
- }
-
- $this->addHtml(
- new HtmlElement(
- 'li',
- null,
- new HtmlElement(
- 'input',
- Attributes::create($attributes)
- )
- )
- );
- }
- }
-
- if ($this->isEmpty()) {
- $this->addHtml(new HtmlElement(
- 'li',
- Attributes::create(['class' => 'nothing-to-suggest']),
- new HtmlElement('em', null, Text::create($this->translate('Nothing to suggest')))
- ));
- }
- }
}
diff --git a/vendor/ipl/web/src/Layout/Controls.php b/vendor/ipl/web/src/Layout/Controls.php
index 8763775..9b52613 100644
--- a/vendor/ipl/web/src/Layout/Controls.php
+++ b/vendor/ipl/web/src/Layout/Controls.php
@@ -43,7 +43,7 @@ class Controls extends BaseHtmlElement
return $this;
}
- public function isEmpty()
+ public function isEmpty(): bool
{
if (! parent::isEmpty()) {
return false;
diff --git a/vendor/ipl/web/src/Layout/DetailedItemLayout.php b/vendor/ipl/web/src/Layout/DetailedItemLayout.php
new file mode 100644
index 0000000..a0c19c2
--- /dev/null
+++ b/vendor/ipl/web/src/Layout/DetailedItemLayout.php
@@ -0,0 +1,27 @@
+get('class')
+ ->removeValue('default-item-layout')
+ ->addValue('detailed-item-layout');
+ }
+
+ protected function assembleMain(HtmlDocument $container): void
+ {
+ $this->registerHeader($container);
+ $this->registerCaption($container);
+ $this->registerFooter($container);
+ }
+}
diff --git a/vendor/ipl/web/src/Layout/DetailedItemTableLayout.php b/vendor/ipl/web/src/Layout/DetailedItemTableLayout.php
new file mode 100644
index 0000000..bcedebc
--- /dev/null
+++ b/vendor/ipl/web/src/Layout/DetailedItemTableLayout.php
@@ -0,0 +1,19 @@
+get('class')
+ ->removeValue('default-item-layout')
+ ->addValue('detailed-item-layout');
+ }
+}
diff --git a/vendor/ipl/web/src/Layout/HeaderItemLayout.php b/vendor/ipl/web/src/Layout/HeaderItemLayout.php
new file mode 100644
index 0000000..7245174
--- /dev/null
+++ b/vendor/ipl/web/src/Layout/HeaderItemLayout.php
@@ -0,0 +1,17 @@
+get('class')->addValue('header-item-layout');
+ }
+}
diff --git a/vendor/ipl/web/src/Layout/ItemLayout.php b/vendor/ipl/web/src/Layout/ItemLayout.php
new file mode 100644
index 0000000..49f760f
--- /dev/null
+++ b/vendor/ipl/web/src/Layout/ItemLayout.php
@@ -0,0 +1,478 @@
+ */
+ protected $before = [];
+
+ /** @var array */
+ protected $after = [];
+
+ /**
+ * Create a new layout for items
+ *
+ * @param Item $item The item to render
+ * @param ItemRenderer- $renderer The renderer used to assemble the layout's content
+ */
+ public function __construct($item, ItemRenderer $renderer)
+ {
+ $this->item = $item;
+ $this->renderer = $renderer;
+ }
+
+ /**
+ * Get the name of this layout
+ *
+ * @return string
+ */
+ public function getName(): string
+ {
+ return static::NAME;
+ }
+
+ /**
+ * Create attributes for this layout
+ *
+ * @param Attributes $attributes
+ *
+ * @return void
+ */
+ protected function createAttributes(Attributes $attributes): void
+ {
+ $attributes->get('class')->addValue(['item-layout', 'default-item-layout']);
+ }
+
+ /**
+ * Get attributes to apply to the container the layout is added to
+ *
+ * @return Attributes
+ */
+ public function getAttributes(): Attributes
+ {
+ $attributes = new Attributes();
+ $this->createAttributes($attributes);
+ $this->renderer->assembleAttributes($this->item, $attributes, $this->getName());
+
+ return $attributes;
+ }
+
+ /**
+ * Create a container for the visual representation of the item
+ *
+ * @return HtmlDocument
+ */
+ protected function createVisual(): HtmlDocument
+ {
+ return new HtmlElement('div', Attributes::create(['class' => static::VISUAL]));
+ }
+
+ /**
+ * Assemble the visual representation of the item in the given container
+ *
+ * @return void
+ */
+ protected function assembleVisual(HtmlDocument $container)
+ {
+ $this->renderer->assembleVisual($this->item, $container, $this->getName());
+ }
+
+ /**
+ * Create, assemble and register the visual representation of the item
+ *
+ * @param HtmlDocument $container
+ *
+ * @return void
+ */
+ protected function registerVisual(HtmlDocument $container): void
+ {
+ $visual = $this->createVisual();
+
+ $this->createBefore(static::VISUAL, $container);
+
+ $this->assembleVisual($visual);
+ if ($visual->isEmpty()) {
+ return;
+ }
+
+ $container->addHtml($visual);
+
+ $this->createAfter(static::VISUAL, $container);
+ }
+
+ /**
+ * Create a container for the main content of the item
+ *
+ * @return HtmlDocument
+ */
+ protected function createMain(): HtmlDocument
+ {
+ return new HtmlElement('div', Attributes::create(['class' => static::MAIN]));
+ }
+
+ /**
+ * Assemble the main content of the item in the given container
+ *
+ * @param HtmlDocument $container
+ *
+ * @return void
+ */
+ protected function assembleMain(HtmlDocument $container): void
+ {
+ $this->registerHeader($container);
+ $this->registerCaption($container);
+ }
+
+ /**
+ * Create, assemble and register the main content of the item
+ *
+ * @param HtmlDocument $container
+ *
+ * @return void
+ */
+ protected function registerMain(HtmlDocument $container): void
+ {
+ $main = $this->createMain();
+
+ $this->createBefore(static::MAIN, $container);
+
+ $this->assembleMain($main);
+
+ $container->addHtml($main);
+
+ $this->createAfter(static::MAIN, $container);
+ }
+
+ /**
+ * Create a container for the header of the item
+ *
+ * @return HtmlDocument
+ */
+ protected function createHeader(): HtmlDocument
+ {
+ return new HtmlElement('header');
+ }
+
+ /**
+ * Assemble the header of the item in the given container
+ *
+ * @param HtmlDocument $container
+ *
+ * @return void
+ */
+ protected function assembleHeader(HtmlDocument $container): void
+ {
+ $this->registerTitle($container);
+ $this->registerExtendedInfo($container);
+ }
+
+ /**
+ * Create, assemble and register the header of the item
+ *
+ * @param HtmlDocument $container
+ *
+ * @return void
+ */
+ protected function registerHeader(HtmlDocument $container): void
+ {
+ $header = $this->createHeader();
+
+ $this->createBefore(static::HEADER, $container);
+
+ $this->assembleHeader($header);
+
+ $container->addHtml($header);
+
+ $this->createAfter(static::HEADER, $container);
+ }
+
+ /**
+ * Create a container for the footer of the item
+ *
+ * @return HtmlDocument
+ */
+ protected function createFooter(): HtmlDocument
+ {
+ return new HtmlElement('footer');
+ }
+
+ /**
+ * Assemble the footer of the item in the given container
+ *
+ * @param HtmlDocument $container
+ *
+ * @return void
+ */
+ protected function assembleFooter(HtmlDocument $container): void
+ {
+ $this->renderer->assembleFooter($this->item, $container, $this->getName());
+ }
+
+ /**
+ * Create, assemble and register the footer of the item
+ *
+ * @param HtmlDocument $container
+ *
+ * @return void
+ */
+ protected function registerFooter(HtmlDocument $container): void
+ {
+ $footer = $this->createFooter();
+
+ $this->createBefore(static::FOOTER, $container);
+
+ $this->assembleFooter($footer);
+ if ($footer->isEmpty()) {
+ return;
+ }
+
+ $container->addHtml($footer);
+
+ $this->createAfter(static::FOOTER, $container);
+ }
+
+ /**
+ * Create a container for the caption of the item
+ *
+ * @return HtmlDocument
+ */
+ protected function createCaption(): HtmlDocument
+ {
+ return new HtmlElement('section', Attributes::create(['class' => static::CAPTION]));
+ }
+
+ /**
+ * Assemble the caption of the item in the given container
+ *
+ * @param HtmlDocument $container
+ *
+ * @return void
+ */
+ protected function assembleCaption(HtmlDocument $container): void
+ {
+ $this->renderer->assembleCaption($this->item, $container, $this->getName());
+ }
+
+ /**
+ * Create, assemble and register the caption of the item
+ *
+ * @param HtmlDocument $container
+ *
+ * @return void
+ */
+ protected function registerCaption(HtmlDocument $container): void
+ {
+ $caption = $this->createCaption();
+
+ $this->createBefore(static::CAPTION, $container);
+
+ $this->assembleCaption($caption);
+
+ $container->addHtml($caption);
+
+ $this->createAfter(static::CAPTION, $container);
+ }
+
+ /**
+ * Create a container for the title of the item
+ *
+ * @return HtmlDocument
+ */
+ protected function createTitle(): HtmlDocument
+ {
+ return new HtmlElement('div', Attributes::create(['class' => static::TITLE]));
+ }
+
+ /**
+ * Assemble the title of the item in the given container
+ *
+ * @param HtmlDocument $container
+ *
+ * @return void
+ */
+ protected function assembleTitle(HtmlDocument $container): void
+ {
+ $this->renderer->assembleTitle($this->item, $container, $this->getName());
+ }
+
+ /**
+ * Create, assemble and register the title of the item
+ *
+ * @param HtmlDocument $container
+ *
+ * @return void
+ */
+ protected function registerTitle(HtmlDocument $container): void
+ {
+ $title = $this->createTitle();
+
+ $this->createBefore(static::TITLE, $container);
+
+ $this->assembleTitle($title);
+
+ $container->addHtml($title);
+
+ $this->createAfter(static::TITLE, $container);
+ }
+
+ /**
+ * Create a container for the extended information of the item
+ *
+ * @return HtmlDocument
+ */
+ protected function createExtendedInfo(): HtmlDocument
+ {
+ return new HtmlElement('div', Attributes::create(['class' => static::EXTENDED_INFO]));
+ }
+
+ /**
+ * Assemble the extended information of the item in the given container
+ *
+ * @param HtmlDocument $container
+ *
+ * @return void
+ */
+ protected function assembleExtendedInfo(HtmlDocument $container): void
+ {
+ $this->renderer->assembleExtendedInfo($this->item, $container, $this->getName());
+ }
+
+ /**
+ * Create, assemble and register the extended information of the item
+ *
+ * @param HtmlDocument $container
+ *
+ * @return void
+ */
+ protected function registerExtendedInfo(HtmlDocument $container): void
+ {
+ $info = $this->createExtendedInfo();
+
+ $this->createBefore(static::EXTENDED_INFO, $container);
+
+ $this->assembleExtendedInfo($info);
+ if ($info->isEmpty()) {
+ return;
+ }
+
+ $container->addHtml($info);
+
+ $this->createAfter(static::EXTENDED_INFO, $container);
+ }
+
+ /**
+ * Render a custom section before the given one
+ *
+ * @param SECTION $section Identifier of the target section
+ * @param string $customSection Identifier for the custom section
+ *
+ * @return void
+ */
+ public function before(string $section, string $customSection): void
+ {
+ $this->before[$section] = $customSection;
+ }
+
+ /**
+ * Add a custom section before the given one
+ *
+ * @param SECTION $section Identifier of the target section
+ * @param HtmlDocument $container The container to add the custom section to
+ *
+ * @return void
+ */
+ protected function createBefore(string $section, HtmlDocument $container): void
+ {
+ if (isset($this->before[$section])) {
+ $customSection = new HtmlElement('div', Attributes::create(['class' => $this->before[$section]]));
+ if ($this->renderer->assemble($this->item, $this->before[$section], $customSection, $this->getName())) {
+ $container->addHtml($customSection);
+ }
+ }
+ }
+
+ /**
+ * Render a custom section after the given one
+ *
+ * @param SECTION $section Identifier of the target section
+ * @param string $customSection Identifier for the custom section
+ *
+ * @return void
+ */
+ public function after(string $section, string $customSection): void
+ {
+ $this->after[$section] = $customSection;
+ }
+
+ /**
+ * Add a custom section after the given one
+ *
+ * @param SECTION $section Identifier of the target section
+ * @param HtmlDocument $container The container to add the custom section to
+ *
+ * @return void
+ */
+ protected function createAfter(string $section, HtmlDocument $container): void
+ {
+ if (isset($this->after[$section])) {
+ $customSection = new HtmlElement('div', Attributes::create(['class' => $this->after[$section]]));
+ if ($this->renderer->assemble($this->item, $this->after[$section], $customSection, $this->getName())) {
+ $container->addHtml($customSection);
+ }
+ }
+ }
+
+ /**
+ * Assemble the layout
+ *
+ * @return void
+ */
+ protected function assemble(): void
+ {
+ $this->registerVisual($this);
+ $this->registerMain($this);
+ }
+}
diff --git a/vendor/ipl/web/src/Layout/ItemTableLayout.php b/vendor/ipl/web/src/Layout/ItemTableLayout.php
new file mode 100644
index 0000000..ede658c
--- /dev/null
+++ b/vendor/ipl/web/src/Layout/ItemTableLayout.php
@@ -0,0 +1,125 @@
+
+ */
+class ItemTableLayout extends ItemLayout
+{
+ /** @var ItemTableRenderer */
+ protected $renderer;
+
+ /** @var int Number of caption columns */
+ protected $columnCount = 0;
+
+ /**
+ * Create a new item table layout
+ *
+ * @param Item $item
+ * @param ItemTableRenderer $renderer
+ */
+ public function __construct($item, ItemTableRenderer $renderer)
+ {
+ parent::__construct($item, $renderer);
+ }
+
+ /**
+ * Get the number of caption columns
+ *
+ * @return int
+ */
+ public function getColumnCount(): int
+ {
+ return $this->columnCount;
+ }
+
+ /**
+ * Create column
+ *
+ * @param string $class CSS class to apply
+ *
+ * @return HtmlElement
+ */
+ protected function createColumn(string $class): HtmlElement
+ {
+ return new HtmlElement('div', Attributes::create(['class' => ['col', $class]]));
+ }
+
+ protected function createVisual(): HtmlDocument
+ {
+ return $this->createColumn(ItemLayout::VISUAL);
+ }
+
+ protected function createMain(): HtmlDocument
+ {
+ return $this->createColumn(ItemLayout::MAIN);
+ }
+
+ protected function assembleHeader(HtmlDocument $container): void
+ {
+ $this->registerTitle($container);
+ }
+
+ /**
+ * Create a container for the item's columns
+ *
+ * @return HtmlDocument
+ */
+ protected function createColumns(): HtmlDocument
+ {
+ return new HtmlDocument();
+ }
+
+ /**
+ * Assemble columns for the item
+ *
+ * @param HtmlDocument $container
+ *
+ * @return void
+ */
+ protected function assembleColumns(HtmlDocument $container): void
+ {
+ $this->renderer->assembleColumns($this->item, $container, $this->getName());
+ }
+
+ /**
+ * Create, assemble and register columns for the item
+ *
+ * @param HtmlDocument $container
+ *
+ * @return void
+ */
+ protected function registerColumns(HtmlDocument $container): void
+ {
+ $columns = $this->createColumns();
+
+ $this->createBefore('columns', $container);
+
+ $this->assembleColumns($columns);
+
+ $this->columnCount = $columns->count();
+
+ $container->addFrom($columns, function (ValidHtml $content) {
+ return $this->createColumn('')->addHtml($content);
+ });
+
+ $this->createAfter('columns', $container);
+ }
+
+ protected function assemble(): void
+ {
+ $this->registerVisual($this);
+ $this->registerMain($this);
+ $this->registerColumns($this);
+ }
+}
diff --git a/vendor/ipl/web/src/Layout/MinimalItemLayout.php b/vendor/ipl/web/src/Layout/MinimalItemLayout.php
new file mode 100644
index 0000000..c70521e
--- /dev/null
+++ b/vendor/ipl/web/src/Layout/MinimalItemLayout.php
@@ -0,0 +1,30 @@
+get('class')->addValue('minimal-item-layout');
+ }
+
+ protected function assembleMain(HtmlDocument $container): void
+ {
+ $this->registerHeader($container);
+ }
+
+ protected function assembleHeader(HtmlDocument $container): void
+ {
+ $this->registerTitle($container);
+ $this->registerCaption($container);
+ $this->registerExtendedInfo($container);
+ }
+}
diff --git a/vendor/ipl/web/src/Layout/MinimalItemTableLayout.php b/vendor/ipl/web/src/Layout/MinimalItemTableLayout.php
new file mode 100644
index 0000000..6330220
--- /dev/null
+++ b/vendor/ipl/web/src/Layout/MinimalItemTableLayout.php
@@ -0,0 +1,29 @@
+get('class')->addValue('minimal-item-layout');
+ }
+
+ protected function assembleHeader(HtmlDocument $container): void
+ {
+ $this->registerTitle($container);
+ $this->registerCaption($container);
+ }
+
+ protected function assembleMain(HtmlDocument $container): void
+ {
+ $this->registerHeader($container);
+ }
+}
diff --git a/vendor/ipl/web/src/Widget/Ball.php b/vendor/ipl/web/src/Widget/Ball.php
new file mode 100644
index 0000000..61b7284
--- /dev/null
+++ b/vendor/ipl/web/src/Widget/Ball.php
@@ -0,0 +1,102 @@
+ ['ball']];
+
+ /** @var SIZE */
+ protected $size = self::SIZE_LARGE;
+
+ /**
+ * Create a new ball element
+ *
+ * @param SIZE $size
+ */
+ public function __construct(string $size = self::SIZE_LARGE)
+ {
+ $size = trim($size);
+ if (empty($size)) {
+ $size = self::SIZE_MEDIUM;
+ }
+
+ $this->size = $size;
+ }
+
+ /**
+ * Register the attribute callbacks
+ *
+ * @param Attributes $attributes
+ */
+ protected function registerAttributeCallbacks(Attributes $attributes): void
+ {
+ $attributes->registerAttributeCallback('class', function () {
+ return new Attribute('class', $this->assembleCssClasses());
+ });
+ }
+
+ /**
+ * Assemble the CSS classes for the ball
+ *
+ * @return array
+ */
+ protected function assembleCssClasses(): array
+ {
+ return ['ball-size-' . $this->size];
+ }
+
+ /**
+ * Add content to the ball
+ *
+ * Automatically wraps text content in a span element.
+ *
+ * @param ValidHtml ...$content
+ *
+ * @return $this
+ */
+ public function addHtml(ValidHtml ...$content): static
+ {
+ if (count($content) === 1 && $content[0] instanceof Text) {
+ $content[0] = new HtmlElement('span', null, $content[0]);
+ }
+
+ return parent::addHtml(...$content);
+ }
+}
diff --git a/vendor/ipl/web/src/Widget/ButtonLink.php b/vendor/ipl/web/src/Widget/ButtonLink.php
index 2da5dfd..b9cd1fa 100644
--- a/vendor/ipl/web/src/Widget/ButtonLink.php
+++ b/vendor/ipl/web/src/Widget/ButtonLink.php
@@ -2,13 +2,54 @@
namespace ipl\Web\Widget;
+use ipl\Html\Attribute;
+
/**
* Button like link generally pointing to CRUD actions
*/
class ButtonLink extends ActionLink
{
protected $defaultAttributes = [
- 'class' => 'button-link',
- 'data-base-target' => '_main'
+ 'role' => 'button',
+ 'class' => 'button-link',
+ 'data-base-target' => '_main'
];
+
+ /** @var ?string The explanation why the button is disabled */
+ protected ?string $disabledExplanation = null;
+
+ /**
+ * Disable the button with explanation
+ *
+ * @param string $explanation Why the button is disabled
+ *
+ * @return $this
+ */
+ public function disable(string $explanation): self
+ {
+ $this->disabledExplanation = $explanation;
+
+ return $this;
+ }
+
+ public function createHrefAttribute(): ?Attribute
+ {
+ if ($this->disabledExplanation) {
+ return null;
+ }
+
+ return parent::createHrefAttribute();
+ }
+
+ public function assemble(): void
+ {
+ parent::assemble();
+
+ if ($this->disabledExplanation) {
+ $this->addAttributes([
+ 'aria-disabled' => 'true',
+ 'title' => $this->disabledExplanation,
+ ]);
+ }
+ }
}
diff --git a/vendor/ipl/web/src/Widget/ContinueWith.php b/vendor/ipl/web/src/Widget/ContinueWith.php
index 1479e9a..6c3fd69 100644
--- a/vendor/ipl/web/src/Widget/ContinueWith.php
+++ b/vendor/ipl/web/src/Widget/ContinueWith.php
@@ -54,6 +54,11 @@ class ContinueWith extends BaseHtmlElement
$filter = $filter(); /** @var Filter\Rule $filter */
}
+ $baseFilter = $this->url->getFilter();
+ if ($baseFilter && ((! $baseFilter instanceof Filter\Chain) || ! $baseFilter->isEmpty())) {
+ $filter = Filter::all($baseFilter, $filter);
+ }
+
if ($filter instanceof Filter\Chain && $filter->isEmpty()) {
$this->addHtml(new HtmlElement(
'span',
diff --git a/vendor/ipl/web/src/Widget/ItemList.php b/vendor/ipl/web/src/Widget/ItemList.php
new file mode 100644
index 0000000..f8da067
--- /dev/null
+++ b/vendor/ipl/web/src/Widget/ItemList.php
@@ -0,0 +1,191 @@
+ */
+ protected $data;
+
+ /** @var ItemRenderer|callable */
+ protected $itemRenderer;
+
+ /** @var string */
+ private $itemLayoutClass = ItemLayout::class;
+
+ /** @var ?ValidHtml Message to show if the list is empty */
+ protected $emptyStateMessage;
+
+ /** @var array */
+ protected $baseAttributes = [
+ 'class' => 'item-list',
+ 'data-base-target' => '_next',
+ 'data-pdfexport-page-breaks-at' => '.list-item'
+ ];
+
+ protected $tag = 'ul';
+
+ /**
+ * Create a new item list
+ *
+ * @param ResultSet|iterable $data
+ * @param ItemRenderer
- |callable $itemRenderer If a callable is passed,
+ * it must accept an item as first argument
+ */
+ public function __construct($data, $itemRenderer)
+ {
+ if (! is_iterable($data)) {
+ throw new InvalidArgumentException('Data must be an array or an instance of Traversable');
+ }
+
+ $this->data = $data;
+ $this->itemRenderer = $itemRenderer;
+
+ $this->addAttributes($this->baseAttributes);
+
+ $this->init();
+ }
+
+ /**
+ * Initialize the item list
+ *
+ * If you want to adjust the item list after construction, override this method.
+ */
+ protected function init(): void
+ {
+ }
+
+ /**
+ * Set the layout class for the items
+ *
+ * @param string $class Must be an instance of the previously set item layout class
+ *
+ * @return $this
+ *
+ * @throws InvalidArgumentException If the class is not a subclass of {@see ItemLayout}
+ */
+ public function setItemLayoutClass(string $class): self
+ {
+ if ($class !== $this->itemLayoutClass && ! is_subclass_of($class, $this->itemLayoutClass)) {
+ throw new InvalidArgumentException("Class $class must be a subclass of " . $this->itemLayoutClass);
+ }
+
+ $this->itemLayoutClass = $class;
+
+ return $this;
+ }
+
+ /**
+ * Get the layout for the given item
+ *
+ * @param Item $item
+ *
+ * @return ItemLayout
+ */
+ public function getItemLayout($item): ItemLayout
+ {
+ return new $this->itemLayoutClass($item, $this->getItemRenderer($item));
+ }
+
+ /**
+ * Get message to show if the list is empty
+ *
+ * @return ValidHtml
+ */
+ public function getEmptyStateMessage(): ValidHtml
+ {
+ if ($this->emptyStateMessage === null) {
+ return new Text($this->translate('No items found.'));
+ }
+
+ return $this->emptyStateMessage;
+ }
+
+ /**
+ * Set message to show if the list is empty
+ *
+ * @param mixed $message If empty, the default message is used
+ *
+ * @return $this
+ */
+ public function setEmptyStateMessage(mixed $message): self
+ {
+ if (empty($message)) {
+ $this->emptyStateMessage = null;
+ } else {
+ $this->emptyStateMessage = Html::wantHtml($message);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get renderer for the given item
+ *
+ * @param Item $item
+ *
+ * @return ItemRenderer
-
+ */
+ protected function getItemRenderer($item): ItemRenderer
+ {
+ if (is_callable($this->itemRenderer)) {
+ return call_user_func($this->itemRenderer, $item);
+ } elseif (is_string($this->itemRenderer)) {
+ $this->itemRenderer = new $this->itemRenderer();
+ }
+
+ return $this->itemRenderer;
+ }
+
+ /**
+ * Create a list item for the given data
+ *
+ * @param Result $data
+ *
+ * @return ListItem
-
+ */
+ protected function createListItem(object $data)
+ {
+ return new ListItem($data, $this);
+ }
+
+ protected function assemble(): void
+ {
+ /** @var Result $data */
+ foreach ($this->data as $data) {
+ $item = $this->createListItem($data);
+ $this->emit(self::BEFORE_ITEM_ADD, [$item, $data]);
+ $this->addHtml($item);
+ $this->emit(self::ON_ITEM_ADD, [$item, $data]);
+ }
+
+ if ($this->isEmpty()) {
+ $this->setTag('div');
+ $this->addHtml(new EmptyState($this->getEmptyStateMessage()));
+ }
+ }
+}
diff --git a/vendor/ipl/web/src/Widget/ItemTable.php b/vendor/ipl/web/src/Widget/ItemTable.php
new file mode 100644
index 0000000..d791fbc
--- /dev/null
+++ b/vendor/ipl/web/src/Widget/ItemTable.php
@@ -0,0 +1,76 @@
+
+ */
+class ItemTable extends ItemList
+{
+ /** @var array */
+ protected $baseAttributes = [
+ 'class' => 'item-table',
+ 'data-base-target' => '_next'
+ ];
+
+ /** @var bool Whether the list already listens for an item's assembly to determine the number of caption columns */
+ protected $listeningForColumnCount = false;
+
+ /** @var StyleWithNonce */
+ protected $style;
+
+ protected function init(): void
+ {
+ parent::init();
+
+ $this->setItemLayoutClass(ItemTableLayout::class);
+ }
+
+ /**
+ * Create a list item for the given data
+ *
+ * @param object $data
+ *
+ * @return ItemTableRow
-
+ */
+ protected function createListItem(object $data): ValidHtml
+ {
+ return new ItemTableRow($data, $this);
+ }
+
+ public function getItemLayout($item): ItemLayout
+ {
+ $layout = parent::getItemLayout($item);
+ if (! $this->listeningForColumnCount) {
+ $this->listeningForColumnCount = true;
+ $layout->on(HtmlDocument::ON_ASSEMBLED, function (ItemTableLayout $layout) {
+ $columns = $layout->getColumnCount();
+ if ($columns === 0) {
+ throw new LogicException('An item table requires at least a single column.');
+ }
+
+ $this->style->addFor($this, ['--columns' => $columns]);
+ });
+ }
+
+ return $layout;
+ }
+
+ protected function assemble(): void
+ {
+ parent::assemble();
+
+ $this->style = new StyleWithNonce();
+ $this->addHtml($this->style);
+ }
+}
diff --git a/vendor/ipl/web/src/Widget/ItemTable/ItemTableRenderer.php b/vendor/ipl/web/src/Widget/ItemTable/ItemTableRenderer.php
new file mode 100644
index 0000000..d1faf69
--- /dev/null
+++ b/vendor/ipl/web/src/Widget/ItemTable/ItemTableRenderer.php
@@ -0,0 +1,26 @@
+
+ */
+interface ItemTableRenderer extends ItemRenderer
+{
+ /**
+ * Assemble columns for an item
+ *
+ * @param Item $item The item to render
+ * @param HtmlDocument $columns The container to add the result to
+ * @param string $layout The name of the layout
+ *
+ * @return void
+ */
+ public function assembleColumns($item, HtmlDocument $columns, string $layout): void;
+}
diff --git a/vendor/ipl/web/src/Widget/ItemTableRow.php b/vendor/ipl/web/src/Widget/ItemTableRow.php
new file mode 100644
index 0000000..9b7804b
--- /dev/null
+++ b/vendor/ipl/web/src/Widget/ItemTableRow.php
@@ -0,0 +1,46 @@
+ The list where the item is part of */
+ protected $list;
+
+ protected $tag = 'li';
+
+ protected $defaultAttributes = ['class' => 'table-row'];
+
+ /**
+ * Create a new table row item
+ *
+ * @param Item $item
+ * @param ItemTable $table
+ */
+ public function __construct($item, ItemTable $table)
+ {
+ $this->item = $item;
+ $this->list = $table;
+ }
+
+ protected function assemble()
+ {
+ $layout = $this->list->getItemLayout($this->item);
+
+ $this->addAttributes($layout->getAttributes());
+ $this->addHtml($layout);
+ }
+}
diff --git a/vendor/ipl/web/src/Widget/ListItem.php b/vendor/ipl/web/src/Widget/ListItem.php
new file mode 100644
index 0000000..7187379
--- /dev/null
+++ b/vendor/ipl/web/src/Widget/ListItem.php
@@ -0,0 +1,46 @@
+ The list where the item is part of */
+ protected $list;
+
+ protected $tag = 'li';
+
+ protected $defaultAttributes = ['class' => 'list-item'];
+
+ /**
+ * Create a new list item
+ *
+ * @param Item $item
+ * @param ItemList
- $list
+ */
+ public function __construct($item, ItemList $list)
+ {
+ $this->item = $item;
+ $this->list = $list;
+ }
+
+ protected function assemble()
+ {
+ $layout = $this->list->getItemLayout($this->item);
+
+ $this->addAttributes($layout->getAttributes());
+ $this->addHtml($layout);
+ }
+}
diff --git a/vendor/ipl/web/src/Widget/StateBall.php b/vendor/ipl/web/src/Widget/StateBall.php
index 5a1216d..cc47e13 100644
--- a/vendor/ipl/web/src/Widget/StateBall.php
+++ b/vendor/ipl/web/src/Widget/StateBall.php
@@ -2,42 +2,62 @@
namespace ipl\Web\Widget;
-use ipl\Html\BaseHtmlElement;
-
/**
* State ball element that supports different sizes and colors
+ *
+ * @phpstan-import-type SIZE from Ball
+ * @phpstan-type STATE 'none'|'pending'|'up'|'down'|'ok'|'critical'|'warning'|'unknown'|'unreachable'
*/
-class StateBall extends BaseHtmlElement
+class StateBall extends Ball
{
- const SIZE_TINY = 'xs';
- const SIZE_SMALL = 's';
- const SIZE_MEDIUM = 'm';
- const SIZE_MEDIUM_LARGE = 'ml';
- const SIZE_BIG = 'l';
- const SIZE_LARGE = 'xl';
+ protected $defaultAttributes = ['class' => 'state-ball'];
- protected $tag = 'span';
+ /** @var STATE */
+ protected $state = 'none';
+
+ /** @var bool */
+ protected $handled = false;
/**
* Create a new state ball element
*
- * @param string $state
- * @param string $size
+ * @param STATE $state
+ * @param SIZE $size
*/
- public function __construct($state = 'none', $size = self::SIZE_SMALL)
+ public function __construct(string $state = 'none', string $size = self::SIZE_SMALL)
{
$state = trim($state);
-
if (empty($state)) {
$state = 'none';
}
- $size = trim($size);
+ $this->state = $state;
- if (empty($size)) {
- $size = self::SIZE_MEDIUM;
+ parent::__construct($size);
+ }
+
+ /**
+ * Show the handled state instead
+ *
+ * @param bool $handled
+ *
+ * @return $this
+ */
+ public function setHandled(bool $handled): self
+ {
+ $this->handled = $handled;
+
+ return $this;
+ }
+
+ protected function assembleCssClasses(): array
+ {
+ $classes = parent::assembleCssClasses();
+ $classes[] = 'state-' . $this->state;
+ if ($this->handled) {
+ $classes[] = 'handled';
}
- $this->defaultAttributes = ['class' => "state-ball state-$state ball-size-$size"];
+ return $classes;
}
}
diff --git a/vendor/ramsey/collection/LICENSE b/vendor/ramsey/collection/LICENSE
index ae15f59..a7fcf12 100644
--- a/vendor/ramsey/collection/LICENSE
+++ b/vendor/ramsey/collection/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2015-2021 Ben Ramsey
+Copyright (c) 2015-2022 Ben Ramsey
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/vendor/ramsey/collection/composer.json b/vendor/ramsey/collection/composer.json
index 0c5d095..42fc22b 100644
--- a/vendor/ramsey/collection/composer.json
+++ b/vendor/ramsey/collection/composer.json
@@ -1,7 +1,8 @@
{
"name": "ramsey/collection",
+ "description": "A PHP library for representing and manipulating collections.",
+ "license": "MIT",
"type": "library",
- "description": "A PHP 7.2+ library for representing and manipulating collections.",
"keywords": [
"array",
"collection",
@@ -10,7 +11,6 @@
"queue",
"set"
],
- "license": "MIT",
"authors": [
{
"name": "Ben Ramsey",
@@ -19,29 +19,28 @@
}
],
"require": {
- "php": "^7.2 || ^8"
+ "php": "^8.1"
},
"require-dev": {
- "captainhook/captainhook": "^5.3",
- "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
- "ergebnis/composer-normalize": "^2.6",
- "fakerphp/faker": "^1.5",
- "hamcrest/hamcrest-php": "^2",
- "jangregor/phpstan-prophecy": "^0.8",
- "mockery/mockery": "^1.3",
- "phpstan/extension-installer": "^1",
- "phpstan/phpstan": "^0.12.32",
- "phpstan/phpstan-mockery": "^0.12.5",
- "phpstan/phpstan-phpunit": "^0.12.11",
- "phpunit/phpunit": "^8.5 || ^9",
- "psy/psysh": "^0.10.4",
- "slevomat/coding-standard": "^6.3",
- "squizlabs/php_codesniffer": "^3.5",
- "vimeo/psalm": "^4.4"
- },
- "config": {
- "sort-packages": true
+ "captainhook/plugin-composer": "^5.3",
+ "ergebnis/composer-normalize": "^2.45",
+ "fakerphp/faker": "^1.24",
+ "hamcrest/hamcrest-php": "^2.0",
+ "jangregor/phpstan-prophecy": "^2.1",
+ "mockery/mockery": "^1.6",
+ "php-parallel-lint/php-console-highlighter": "^1.0",
+ "php-parallel-lint/php-parallel-lint": "^1.4",
+ "phpspec/prophecy-phpunit": "^2.3",
+ "phpstan/extension-installer": "^1.4",
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-mockery": "^2.0",
+ "phpstan/phpstan-phpunit": "^2.0",
+ "phpunit/phpunit": "^10.5",
+ "ramsey/coding-standard": "^2.3",
+ "ramsey/conventional-commits": "^1.6",
+ "roave/security-advisories": "dev-latest"
},
+ "prefer-stable": true,
"autoload": {
"psr-4": {
"Ramsey\\Collection\\": "src/"
@@ -49,57 +48,61 @@
},
"autoload-dev": {
"psr-4": {
- "Ramsey\\Console\\": "resources/console/",
"Ramsey\\Collection\\Test\\": "tests/"
+ }
+ },
+ "config": {
+ "allow-plugins": {
+ "captainhook/plugin-composer": true,
+ "dealerdirect/phpcodesniffer-composer-installer": true,
+ "ergebnis/composer-normalize": true,
+ "phpstan/extension-installer": true
},
- "files": [
- "vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest.php"
- ]
+ "sort-packages": true
+ },
+ "extra": {
+ "captainhook": {
+ "force-install": true
+ },
+ "ramsey/conventional-commits": {
+ "configFile": "conventional-commits.json"
+ }
},
"scripts": {
- "post-autoload-dump": "captainhook install --ansi -f -s",
- "br:analyze": [
- "@br:analyze:phpstan",
- "@br:analyze:psalm"
+ "dev:analyze": [
+ "@dev:analyze:phpstan"
],
- "br:analyze:phpstan": "phpstan --memory-limit=1G analyse",
- "br:analyze:psalm": "psalm --diff --config=psalm.xml",
- "br:build:clean": "git clean -fX build/.",
- "br:build:clear-cache": "git clean -fX build/cache/.",
- "br:lint": "phpcs --cache=build/cache/phpcs.cache",
- "br:lint:fix": "./bin/lint-fix.sh",
- "br:repl": [
- "echo ; echo 'Type ./bin/repl to start the REPL.'"
+ "dev:analyze:phpstan": "phpstan analyse --ansi --memory-limit=1G",
+ "dev:build:clean": "git clean -fX build/",
+ "dev:lint": [
+ "@dev:lint:syntax",
+ "@dev:lint:style"
],
- "br:test": "phpunit",
- "br:test:all": [
- "@br:lint",
- "@br:analyze",
- "@br:test"
+ "dev:lint:fix": "phpcbf",
+ "dev:lint:style": "phpcs --colors",
+ "dev:lint:syntax": "parallel-lint --colors src/ tests/",
+ "dev:test": [
+ "@dev:lint",
+ "@dev:analyze",
+ "@dev:test:unit"
],
- "br:test:coverage:ci": "phpunit --coverage-clover build/logs/clover.xml",
- "br:test:coverage:html": "phpunit --coverage-html build/coverage",
- "pre-commit": [
- "@br:lint:fix",
- "@br:lint",
- "@br:analyze"
- ],
- "test": "@br:test:all"
+ "dev:test:coverage:ci": "phpunit --colors=always --coverage-text --coverage-clover build/coverage/clover.xml --coverage-cobertura build/coverage/cobertura.xml --coverage-crap4j build/coverage/crap4j.xml --coverage-xml build/coverage/coverage-xml --log-junit build/junit.xml",
+ "dev:test:coverage:html": "phpunit --colors=always --coverage-html build/coverage/coverage-html/",
+ "dev:test:unit": "phpunit --colors=always",
+ "test": "@dev:test"
},
"scripts-descriptions": {
- "br:analyze": "Performs static analysis on the code base.",
- "br:analyze:phpstan": "Runs the PHPStan static analyzer.",
- "br:analyze:psalm": "Runs the Psalm static analyzer.",
- "br:build:clean": "Removes everything not under version control from the build directory.",
- "br:build:clear-cache": "Removes everything not under version control from build/cache/.",
- "br:lint": "Checks all source code for coding standards issues.",
- "br:lint:fix": "Checks source code for coding standards issues and fixes them, if possible.",
- "br:repl": "Note: Use ./bin/repl to run the REPL.",
- "br:test": "Runs the full unit test suite.",
- "br:test:all": "Runs linting, static analysis, and unit tests.",
- "br:test:coverage:ci": "Runs the unit test suite and generates a Clover coverage report.",
- "br:test:coverage:html": "Runs the unit tests suite and generates an HTML coverage report.",
- "pre-commit": "These commands are run as part of a Git pre-commit hook installed using captainhook/captainhook. Each command should be prepared to accept a list of space-separated staged files.",
- "test": "Shortcut to run the full test suite."
+ "dev:analyze": "Runs all static analysis checks.",
+ "dev:analyze:phpstan": "Runs the PHPStan static analyzer.",
+ "dev:build:clean": "Cleans the build/ directory.",
+ "dev:lint": "Runs all linting checks.",
+ "dev:lint:fix": "Auto-fixes coding standards issues, if possible.",
+ "dev:lint:style": "Checks for coding standards issues.",
+ "dev:lint:syntax": "Checks for syntax errors.",
+ "dev:test": "Runs linting, static analysis, and unit tests.",
+ "dev:test:coverage:ci": "Runs unit tests and generates CI coverage reports.",
+ "dev:test:coverage:html": "Runs unit tests and generates HTML coverage report.",
+ "dev:test:unit": "Runs unit tests.",
+ "test": "Runs linting, static analysis, and unit tests."
}
}
diff --git a/vendor/ramsey/collection/src/AbstractArray.php b/vendor/ramsey/collection/src/AbstractArray.php
index a8a164c..6d6b6d6 100644
--- a/vendor/ramsey/collection/src/AbstractArray.php
+++ b/vendor/ramsey/collection/src/AbstractArray.php
@@ -17,15 +17,14 @@ namespace Ramsey\Collection;
use ArrayIterator;
use Traversable;
-use function serialize;
-use function unserialize;
+use function count;
/**
* This class provides a basic implementation of `ArrayInterface`, to minimize
* the effort required to implement this interface.
*
* @template T
- * @template-implements ArrayInterface
+ * @implements ArrayInterface
*/
abstract class AbstractArray implements ArrayInterface
{
@@ -34,7 +33,7 @@ abstract class AbstractArray implements ArrayInterface
*
* @var array
*/
- protected $data = [];
+ protected array $data = [];
/**
* Constructs a new array object.
@@ -43,7 +42,7 @@ abstract class AbstractArray implements ArrayInterface
*/
public function __construct(array $data = [])
{
- // Invoke offsetSet() for each value added; in this way, sub-classes
+ // Invoke offsetSet() for each value added; in this way, subclasses
// may provide additional logic about values added to the array object.
foreach ($data as $key => $value) {
$this[$key] = $value;
@@ -55,7 +54,7 @@ abstract class AbstractArray implements ArrayInterface
*
* @link http://php.net/manual/en/iteratoraggregate.getiterator.php IteratorAggregate::getIterator()
*
- * @return Traversable
+ * @return Traversable
*/
public function getIterator(): Traversable
{
@@ -69,7 +68,7 @@ abstract class AbstractArray implements ArrayInterface
*
* @param array-key $offset The offset to check.
*/
- public function offsetExists($offset): bool
+ public function offsetExists(mixed $offset): bool
{
return isset($this->data[$offset]);
}
@@ -81,13 +80,12 @@ abstract class AbstractArray implements ArrayInterface
*
* @param array-key $offset The offset for which a value should be returned.
*
- * @return T|null the value stored at the offset, or null if the offset
+ * @return T the value stored at the offset, or null if the offset
* does not exist.
*/
- #[\ReturnTypeWillChange]
- public function offsetGet($offset)
+ public function offsetGet(mixed $offset): mixed
{
- return $this->data[$offset] ?? null;
+ return $this->data[$offset];
}
/**
@@ -95,12 +93,11 @@ abstract class AbstractArray implements ArrayInterface
*
* @link http://php.net/manual/en/arrayaccess.offsetset.php ArrayAccess::offsetSet()
*
- * @param array-key|null $offset The offset to set. If `null`, the value may be
- * set at a numerically-indexed offset.
+ * @param array-key | null $offset The offset to set. If `null`, the value
+ * may be set at a numerically-indexed offset.
* @param T $value The value to set at the given offset.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function offsetSet($offset, $value): void
+ public function offsetSet(mixed $offset, mixed $value): void
{
if ($offset === null) {
$this->data[] = $value;
@@ -116,50 +113,34 @@ abstract class AbstractArray implements ArrayInterface
*
* @param array-key $offset The offset to remove from the array.
*/
- public function offsetUnset($offset): void
+ public function offsetUnset(mixed $offset): void
{
unset($this->data[$offset]);
}
/**
- * Returns a serialized string representation of this array object.
+ * Returns data suitable for PHP serialization.
*
- * @link http://php.net/manual/en/serializable.serialize.php Serializable::serialize()
+ * @link https://www.php.net/manual/en/language.oop5.magic.php#language.oop5.magic.serialize
+ * @link https://www.php.net/serialize
*
- * @return string a PHP serialized string.
+ * @return array
*/
- public function serialize(): string
+ public function __serialize(): array
{
- return serialize($this->data);
- }
-
- public function __serialize()
- {
- return $this->serialize();
+ return $this->data;
}
/**
- * Converts a serialized string representation into an instance object.
+ * Adds unserialized data to the object.
*
- * @link http://php.net/manual/en/serializable.unserialize.php Serializable::unserialize()
- *
- * @param string $serialized A PHP serialized string to unserialize.
- *
- * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
+ * @param array $data
*/
- public function unserialize($serialized): void
+ public function __unserialize(array $data): void
{
- /** @var array $data */
- $data = unserialize($serialized, ['allowed_classes' => false]);
-
$this->data = $data;
}
- public function __unserialize(array $data)
- {
- $this->unserialize($data);
- }
-
/**
* Returns the number of items in this array.
*
@@ -185,6 +166,6 @@ abstract class AbstractArray implements ArrayInterface
public function isEmpty(): bool
{
- return count($this->data) === 0;
+ return $this->data === [];
}
}
diff --git a/vendor/ramsey/collection/src/AbstractCollection.php b/vendor/ramsey/collection/src/AbstractCollection.php
index f803f42..2f006b9 100644
--- a/vendor/ramsey/collection/src/AbstractCollection.php
+++ b/vendor/ramsey/collection/src/AbstractCollection.php
@@ -17,24 +17,27 @@ namespace Ramsey\Collection;
use Closure;
use Ramsey\Collection\Exception\CollectionMismatchException;
use Ramsey\Collection\Exception\InvalidArgumentException;
-use Ramsey\Collection\Exception\InvalidSortOrderException;
-use Ramsey\Collection\Exception\OutOfBoundsException;
+use Ramsey\Collection\Exception\InvalidPropertyOrMethod;
+use Ramsey\Collection\Exception\NoSuchElementException;
+use Ramsey\Collection\Exception\UnsupportedOperationException;
use Ramsey\Collection\Tool\TypeTrait;
use Ramsey\Collection\Tool\ValueExtractorTrait;
use Ramsey\Collection\Tool\ValueToStringTrait;
use function array_filter;
+use function array_key_first;
+use function array_key_last;
use function array_map;
use function array_merge;
+use function array_reduce;
use function array_search;
use function array_udiff;
use function array_uintersect;
-use function current;
-use function end;
use function in_array;
-use function reset;
+use function is_int;
+use function is_object;
+use function spl_object_id;
use function sprintf;
-use function unserialize;
use function usort;
/**
@@ -42,8 +45,8 @@ use function usort;
* minimize the effort required to implement this interface
*
* @template T
- * @template-extends AbstractArray
- * @template-implements CollectionInterface
+ * @extends AbstractArray
+ * @implements CollectionInterface
*/
abstract class AbstractCollection extends AbstractArray implements CollectionInterface
{
@@ -52,32 +55,29 @@ abstract class AbstractCollection extends AbstractArray implements CollectionInt
use ValueExtractorTrait;
/**
- * @inheritDoc
+ * @throws InvalidArgumentException if $element is of the wrong type.
*/
- public function add($element): bool
+ public function add(mixed $element): bool
{
$this[] = $element;
return true;
}
- /**
- * @inheritDoc
- */
- public function contains($element, bool $strict = true): bool
+ public function contains(mixed $element, bool $strict = true): bool
{
return in_array($element, $this->data, $strict);
}
/**
- * @inheritDoc
+ * @throws InvalidArgumentException if $element is of the wrong type.
*/
- public function offsetSet($offset, $value): void
+ public function offsetSet(mixed $offset, mixed $value): void
{
if ($this->checkType($this->getType(), $value) === false) {
throw new InvalidArgumentException(
'Value must be of type ' . $this->getType() . '; value is '
- . $this->toolValueToString($value)
+ . $this->toolValueToString($value),
);
}
@@ -88,13 +88,10 @@ abstract class AbstractCollection extends AbstractArray implements CollectionInt
}
}
- /**
- * @inheritDoc
- */
- public function remove($element): bool
+ public function remove(mixed $element): bool
{
if (($position = array_search($element, $this->data, true)) !== false) {
- unset($this->data[$position]);
+ unset($this[$position]);
return true;
}
@@ -103,6 +100,11 @@ abstract class AbstractCollection extends AbstractArray implements CollectionInt
}
/**
+ * @throws InvalidPropertyOrMethod if the $propertyOrMethod does not exist
+ * on the elements in this collection.
+ * @throws UnsupportedOperationException if unable to call column() on this
+ * collection.
+ *
* @inheritDoc
*/
public function column(string $propertyOrMethod): array
@@ -110,77 +112,74 @@ abstract class AbstractCollection extends AbstractArray implements CollectionInt
$temp = [];
foreach ($this->data as $item) {
- /** @var mixed $value */
- $value = $this->extractValue($item, $propertyOrMethod);
-
- /** @psalm-suppress MixedAssignment */
- $temp[] = $value;
+ $temp[] = $this->extractValue($item, $propertyOrMethod);
}
return $temp;
}
/**
- * @inheritDoc
+ * @return T
+ *
+ * @throws NoSuchElementException if this collection is empty.
*/
- public function first()
+ public function first(): mixed
{
- if ($this->isEmpty()) {
- throw new OutOfBoundsException('Can\'t determine first item. Collection is empty');
+ $firstIndex = array_key_first($this->data);
+
+ if ($firstIndex === null) {
+ throw new NoSuchElementException('Can\'t determine first item. Collection is empty');
}
- reset($this->data);
-
- /** @var T $first */
- $first = current($this->data);
-
- return $first;
+ return $this->data[$firstIndex];
}
/**
- * @inheritDoc
+ * @return T
+ *
+ * @throws NoSuchElementException if this collection is empty.
*/
- public function last()
+ public function last(): mixed
{
- if ($this->isEmpty()) {
- throw new OutOfBoundsException('Can\'t determine last item. Collection is empty');
+ $lastIndex = array_key_last($this->data);
+
+ if ($lastIndex === null) {
+ throw new NoSuchElementException('Can\'t determine last item. Collection is empty');
}
- /** @var T $item */
- $item = end($this->data);
- reset($this->data);
-
- return $item;
+ return $this->data[$lastIndex];
}
- public function sort(string $propertyOrMethod, string $order = self::SORT_ASC): CollectionInterface
+ /**
+ * @return CollectionInterface
+ *
+ * @throws InvalidPropertyOrMethod if the $propertyOrMethod does not exist
+ * on the elements in this collection.
+ * @throws UnsupportedOperationException if unable to call sort() on this
+ * collection.
+ */
+ public function sort(?string $propertyOrMethod = null, Sort $order = Sort::Ascending): CollectionInterface
{
- if (!in_array($order, [self::SORT_ASC, self::SORT_DESC], true)) {
- throw new InvalidSortOrderException('Invalid sort order given: ' . $order);
- }
-
$collection = clone $this;
usort(
$collection->data,
- /**
- * @param T $a
- * @param T $b
- */
- function ($a, $b) use ($propertyOrMethod, $order): int {
- /** @var mixed $aValue */
+ function (mixed $a, mixed $b) use ($propertyOrMethod, $order): int {
$aValue = $this->extractValue($a, $propertyOrMethod);
-
- /** @var mixed $bValue */
$bValue = $this->extractValue($b, $propertyOrMethod);
- return ($aValue <=> $bValue) * ($order === self::SORT_DESC ? -1 : 1);
- }
+ return ($aValue <=> $bValue) * ($order === Sort::Descending ? -1 : 1);
+ },
);
return $collection;
}
+ /**
+ * @param callable(T): bool $callback A callable to use for filtering elements.
+ *
+ * @return CollectionInterface
+ */
public function filter(callable $callback): CollectionInterface
{
$collection = clone $this;
@@ -190,23 +189,56 @@ abstract class AbstractCollection extends AbstractArray implements CollectionInt
}
/**
- * {@inheritdoc}
+ * @return CollectionInterface
+ *
+ * @throws InvalidPropertyOrMethod if the $propertyOrMethod does not exist
+ * on the elements in this collection.
+ * @throws UnsupportedOperationException if unable to call where() on this
+ * collection.
*/
- public function where(string $propertyOrMethod, $value): CollectionInterface
+ public function where(?string $propertyOrMethod, mixed $value): CollectionInterface
{
- return $this->filter(function ($item) use ($propertyOrMethod, $value) {
- /** @var mixed $accessorValue */
- $accessorValue = $this->extractValue($item, $propertyOrMethod);
-
- return $accessorValue === $value;
- });
+ return $this->filter(
+ fn (mixed $item): bool => $this->extractValue($item, $propertyOrMethod) === $value,
+ );
}
+ /**
+ * @param callable(T): TCallbackReturn $callback A callable to apply to each
+ * item of the collection.
+ *
+ * @return CollectionInterface
+ *
+ * @template TCallbackReturn
+ */
public function map(callable $callback): CollectionInterface
{
return new Collection('mixed', array_map($callback, $this->data));
}
+ /**
+ * @param callable(TCarry, T): TCarry $callback A callable to apply to each
+ * item of the collection to reduce it to a single value.
+ * @param TCarry $initial This is the initial value provided to the callback.
+ *
+ * @return TCarry
+ *
+ * @template TCarry
+ */
+ public function reduce(callable $callback, mixed $initial): mixed
+ {
+ return array_reduce($this->data, $callback, $initial);
+ }
+
+ /**
+ * @param CollectionInterface $other The collection to check for divergent
+ * items.
+ *
+ * @return CollectionInterface
+ *
+ * @throws CollectionMismatchException if the compared collections are of
+ * differing types.
+ */
public function diff(CollectionInterface $other): CollectionInterface
{
$this->compareCollectionTypes($other);
@@ -214,71 +246,79 @@ abstract class AbstractCollection extends AbstractArray implements CollectionInt
$diffAtoB = array_udiff($this->data, $other->toArray(), $this->getComparator());
$diffBtoA = array_udiff($other->toArray(), $this->data, $this->getComparator());
- /** @var array $diff */
- $diff = array_merge($diffAtoB, $diffBtoA);
-
$collection = clone $this;
- $collection->data = $diff;
+ $collection->data = array_merge($diffAtoB, $diffBtoA);
return $collection;
}
+ /**
+ * @param CollectionInterface $other The collection to check for
+ * intersecting items.
+ *
+ * @return CollectionInterface
+ *
+ * @throws CollectionMismatchException if the compared collections are of
+ * differing types.
+ */
public function intersect(CollectionInterface $other): CollectionInterface
{
$this->compareCollectionTypes($other);
- /** @var array $intersect */
- $intersect = array_uintersect($this->data, $other->toArray(), $this->getComparator());
-
$collection = clone $this;
- $collection->data = $intersect;
+ $collection->data = array_uintersect($this->data, $other->toArray(), $this->getComparator());
return $collection;
}
+ /**
+ * @param CollectionInterface ...$collections The collections to merge.
+ *
+ * @return CollectionInterface
+ *
+ * @throws CollectionMismatchException if unable to merge any of the given
+ * collections or items within the given collections due to type
+ * mismatch errors.
+ */
public function merge(CollectionInterface ...$collections): CollectionInterface
{
- $temp = [$this->data];
+ $mergedCollection = clone $this;
foreach ($collections as $index => $collection) {
if (!$collection instanceof static) {
throw new CollectionMismatchException(
- sprintf('Collection with index %d must be of type %s', $index, static::class)
+ sprintf('Collection with index %d must be of type %s', $index, static::class),
);
}
// When using generics (Collection.php, Set.php, etc),
// we also need to make sure that the internal types match each other
- if ($collection->getType() !== $this->getType()) {
+ if ($this->getUniformType($collection) !== $this->getUniformType($this)) {
throw new CollectionMismatchException(
- sprintf('Collection items in collection with index %d must be of type %s', $index, $this->getType())
+ sprintf(
+ 'Collection items in collection with index %d must be of type %s',
+ $index,
+ $this->getType(),
+ ),
);
}
- $temp[] = $collection->toArray();
+ foreach ($collection as $key => $value) {
+ if (is_int($key)) {
+ $mergedCollection[] = $value;
+ } else {
+ $mergedCollection[$key] = $value;
+ }
+ }
}
- $merge = array_merge(...$temp);
-
- $collection = clone $this;
- $collection->data = $merge;
-
- return $collection;
- }
-
- /**
- * @inheritDoc
- */
- public function unserialize($serialized): void
- {
- /** @var array $data */
- $data = unserialize($serialized, ['allowed_classes' => [$this->getType()]]);
-
- $this->data = $data;
+ return $mergedCollection;
}
/**
* @param CollectionInterface $other
+ *
+ * @throws CollectionMismatchException
*/
private function compareCollectionTypes(CollectionInterface $other): void
{
@@ -288,29 +328,38 @@ abstract class AbstractCollection extends AbstractArray implements CollectionInt
// When using generics (Collection.php, Set.php, etc),
// we also need to make sure that the internal types match each other
- if ($other->getType() !== $this->getType()) {
+ if ($this->getUniformType($other) !== $this->getUniformType($this)) {
throw new CollectionMismatchException('Collection items must be of type ' . $this->getType());
}
}
private function getComparator(): Closure
{
- return /**
- * @param T $a
- * @param T $b
- */
- function ($a, $b): int {
- // If the two values are object, we convert them to unique scalars.
- // If the collection contains mixed values (unlikely) where some are objects
- // and some are not, we leave them as they are.
- // The comparator should still work and the result of $a < $b should
- // be consistent but unpredictable since not documented.
- if (is_object($a) && is_object($b)) {
- $a = spl_object_id($a);
- $b = spl_object_id($b);
- }
+ return function (mixed $a, mixed $b): int {
+ // If the two values are object, we convert them to unique scalars.
+ // If the collection contains mixed values (unlikely) where some are objects
+ // and some are not, we leave them as they are.
+ // The comparator should still work and the result of $a < $b should
+ // be consistent but unpredictable since not documented.
+ if (is_object($a) && is_object($b)) {
+ $a = spl_object_id($a);
+ $b = spl_object_id($b);
+ }
- return $a === $b ? 0 : ($a < $b ? 1 : -1);
- };
+ return $a === $b ? 0 : ($a < $b ? 1 : -1);
+ };
+ }
+
+ /**
+ * @param CollectionInterface $collection
+ */
+ private function getUniformType(CollectionInterface $collection): string
+ {
+ return match ($collection->getType()) {
+ 'integer' => 'int',
+ 'boolean' => 'bool',
+ 'double' => 'float',
+ default => $collection->getType(),
+ };
}
}
diff --git a/vendor/ramsey/collection/src/AbstractSet.php b/vendor/ramsey/collection/src/AbstractSet.php
index 3bd2296..63f8331 100644
--- a/vendor/ramsey/collection/src/AbstractSet.php
+++ b/vendor/ramsey/collection/src/AbstractSet.php
@@ -20,26 +20,27 @@ namespace Ramsey\Collection;
* this specific type of collection.
*
* @template T
- * @template-extends AbstractCollection
+ * @extends AbstractCollection
*/
abstract class AbstractSet extends AbstractCollection
{
- /**
- * @inheritDoc
- */
- public function add($element): bool
+ public function add(mixed $element): bool
{
if ($this->contains($element)) {
return false;
}
- return parent::add($element);
+ // Call offsetSet() on the parent instead of add(), since calling
+ // parent::add() will invoke $this->offsetSet(), which will call
+ // $this->contains() a second time. This can cause performance issues
+ // with extremely large collections. For more information, see
+ // https://github.com/ramsey/collection/issues/68.
+ parent::offsetSet(null, $element);
+
+ return true;
}
- /**
- * @inheritDoc
- */
- public function offsetSet($offset, $value): void
+ public function offsetSet(mixed $offset, mixed $value): void
{
if ($this->contains($value)) {
return;
diff --git a/vendor/ramsey/collection/src/ArrayInterface.php b/vendor/ramsey/collection/src/ArrayInterface.php
index 19fbff3..bc7f6f4 100644
--- a/vendor/ramsey/collection/src/ArrayInterface.php
+++ b/vendor/ramsey/collection/src/ArrayInterface.php
@@ -17,18 +17,18 @@ namespace Ramsey\Collection;
use ArrayAccess;
use Countable;
use IteratorAggregate;
-use Serializable;
/**
* `ArrayInterface` provides traversable array functionality to data types.
*
* @template T
+ * @extends ArrayAccess
+ * @extends IteratorAggregate
*/
interface ArrayInterface extends
ArrayAccess,
Countable,
- IteratorAggregate,
- Serializable
+ IteratorAggregate
{
/**
* Removes all items from this array.
diff --git a/vendor/ramsey/collection/src/Collection.php b/vendor/ramsey/collection/src/Collection.php
index 2f8dedd..3b0f768 100644
--- a/vendor/ramsey/collection/src/Collection.php
+++ b/vendor/ramsey/collection/src/Collection.php
@@ -24,7 +24,7 @@ namespace Ramsey\Collection;
*
* Example usage:
*
- * ``` php
+ * ```
* $collection = new \Ramsey\Collection\Collection('My\\Foo');
* $collection->add(new \My\Foo());
* $collection->add(new \My\Foo());
@@ -37,7 +37,7 @@ namespace Ramsey\Collection;
* It is preferable to subclass `AbstractCollection` to create your own typed
* collections. For example:
*
- * ``` php
+ * ```
* namespace My\Foo;
*
* class FooCollection extends \Ramsey\Collection\AbstractCollection
@@ -51,7 +51,7 @@ namespace Ramsey\Collection;
*
* And then use it similarly to the earlier example:
*
- * ``` php
+ * ```
* $fooCollection = new \My\Foo\FooCollection();
* $fooCollection->add(new \My\Foo());
* $fooCollection->add(new \My\Foo());
@@ -64,38 +64,27 @@ namespace Ramsey\Collection;
* The benefit with this approach is that you may do type-checking on the
* collection object:
*
- * ``` php
+ * ```
* if ($collection instanceof \My\Foo\FooCollection) {
* // the collection is a collection of My\Foo objects
* }
* ```
*
* @template T
- * @template-extends AbstractCollection
+ * @extends AbstractCollection
*/
class Collection extends AbstractCollection
{
- /**
- * The type of elements stored in this collection.
- *
- * A collection's type is immutable once it is set. For this reason, this
- * property is set private.
- *
- * @var string
- */
- private $collectionType;
-
/**
* Constructs a collection object of the specified type, optionally with the
* specified data.
*
- * @param string $collectionType The type (FQCN) associated with this
+ * @param string $collectionType The type or class name associated with this
* collection.
* @param array $data The initial items to store in the collection.
*/
- public function __construct(string $collectionType, array $data = [])
+ public function __construct(private readonly string $collectionType, array $data = [])
{
- $this->collectionType = $collectionType;
parent::__construct($data);
}
diff --git a/vendor/ramsey/collection/src/CollectionInterface.php b/vendor/ramsey/collection/src/CollectionInterface.php
index dfef6ca..3ffbb16 100644
--- a/vendor/ramsey/collection/src/CollectionInterface.php
+++ b/vendor/ramsey/collection/src/CollectionInterface.php
@@ -14,27 +14,23 @@ declare(strict_types=1);
namespace Ramsey\Collection;
+use Ramsey\Collection\Exception\CollectionMismatchException;
+use Ramsey\Collection\Exception\InvalidArgumentException;
+use Ramsey\Collection\Exception\InvalidPropertyOrMethod;
+use Ramsey\Collection\Exception\NoSuchElementException;
+use Ramsey\Collection\Exception\UnsupportedOperationException;
+
/**
- * A collection represents a group of objects, known as its elements.
+ * A collection represents a group of values, known as its elements.
*
* Some collections allow duplicate elements and others do not. Some are ordered
* and others unordered.
*
* @template T
- * @template-extends ArrayInterface
+ * @extends ArrayInterface
*/
interface CollectionInterface extends ArrayInterface
{
- /**
- * Ascending sort type.
- */
- public const SORT_ASC = 'asc';
-
- /**
- * Descending sort type.
- */
- public const SORT_DESC = 'desc';
-
/**
* Ensures that this collection contains the specified element (optional
* operation).
@@ -58,9 +54,11 @@ interface CollectionInterface extends ArrayInterface
* @param T $element The element to add to the collection.
*
* @return bool `true` if this collection changed as a result of the call.
+ *
+ * @throws InvalidArgumentException if the collection refuses to add the
+ * $element for any reason other than that it already contains the element.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function add($element): bool;
+ public function add(mixed $element): bool;
/**
* Returns `true` if this collection contains the specified element.
@@ -68,8 +66,7 @@ interface CollectionInterface extends ArrayInterface
* @param T $element The element to check whether the collection contains.
* @param bool $strict Whether to perform a strict type check on the value.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function contains($element, bool $strict = true): bool;
+ public function contains(mixed $element, bool $strict = true): bool;
/**
* Returns the type associated with this collection.
@@ -84,15 +81,20 @@ interface CollectionInterface extends ArrayInterface
*
* @return bool `true` if an element was removed as a result of this call.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function remove($element): bool;
+ public function remove(mixed $element): bool;
/**
- * Returns the values from the given property or method.
+ * Returns the values from the given property, method, or array key.
*
- * @param string $propertyOrMethod The property or method name to filter by.
+ * @param string $propertyOrMethod The name of the property, method, or
+ * array key to evaluate and return.
*
* @return list
+ *
+ * @throws InvalidPropertyOrMethod if the $propertyOrMethod does not exist
+ * on the elements in this collection.
+ * @throws UnsupportedOperationException if unable to call column() on this
+ * collection.
*/
public function column(string $propertyOrMethod): array;
@@ -100,29 +102,41 @@ interface CollectionInterface extends ArrayInterface
* Returns the first item of the collection.
*
* @return T
+ *
+ * @throws NoSuchElementException if this collection is empty.
*/
- public function first();
+ public function first(): mixed;
/**
* Returns the last item of the collection.
*
* @return T
+ *
+ * @throws NoSuchElementException if this collection is empty.
*/
- public function last();
+ public function last(): mixed;
/**
- * Sort the collection by a property or method with the given sort order.
+ * Sort the collection by a property, method, or array key with the given
+ * sort order.
+ *
+ * If $propertyOrMethod is `null`, this will sort by comparing each element.
*
* This will always leave the original collection untouched and will return
* a new one.
*
- * @param string $propertyOrMethod The property or method to sort by.
- * @param string $order The sort order for the resulting collection (one of
- * this interface's `SORT_*` constants).
+ * @param string | null $propertyOrMethod The property, method, or array key
+ * to sort by.
+ * @param Sort $order The sort order for the resulting collection.
*
* @return CollectionInterface
+ *
+ * @throws InvalidPropertyOrMethod if the $propertyOrMethod does not exist
+ * on the elements in this collection.
+ * @throws UnsupportedOperationException if unable to call sort() on this
+ * collection.
*/
- public function sort(string $propertyOrMethod, string $order = self::SORT_ASC): self;
+ public function sort(?string $propertyOrMethod = null, Sort $order = Sort::Ascending): self;
/**
* Filter out items of the collection which don't match the criteria of
@@ -134,24 +148,31 @@ interface CollectionInterface extends ArrayInterface
* See the {@link http://php.net/manual/en/function.array-filter.php PHP array_filter() documentation}
* for examples of how the `$callback` parameter works.
*
- * @param callable(T):bool $callback A callable to use for filtering elements.
+ * @param callable(T): bool $callback A callable to use for filtering elements.
*
* @return CollectionInterface
*/
public function filter(callable $callback): self;
/**
- * Create a new collection where items match the criteria of given callback.
+ * Create a new collection where the result of the given property, method,
+ * or array key of each item in the collection equals the given value.
*
* This will always leave the original collection untouched and will return
* a new one.
*
- * @param string $propertyOrMethod The property or method to evaluate.
+ * @param string | null $propertyOrMethod The property, method, or array key
+ * to evaluate. If `null`, the element itself is compared to $value.
* @param mixed $value The value to match.
*
* @return CollectionInterface
+ *
+ * @throws InvalidPropertyOrMethod if the $propertyOrMethod does not exist
+ * on the elements in this collection.
+ * @throws UnsupportedOperationException if unable to call where() on this
+ * collection.
*/
- public function where(string $propertyOrMethod, $value): self;
+ public function where(?string $propertyOrMethod, mixed $value): self;
/**
* Apply a given callback method on each item of the collection.
@@ -163,7 +184,7 @@ interface CollectionInterface extends ArrayInterface
* See the {@link http://php.net/manual/en/function.array-map.php PHP array_map() documentation}
* for examples of how the `$callback` parameter works.
*
- * @param callable(T):TCallbackReturn $callback A callable to apply to each
+ * @param callable(T): TCallbackReturn $callback A callable to apply to each
* item of the collection.
*
* @return CollectionInterface
@@ -172,6 +193,23 @@ interface CollectionInterface extends ArrayInterface
*/
public function map(callable $callback): self;
+ /**
+ * Apply a given callback method on each item of the collection
+ * to reduce it to a single value.
+ *
+ * See the {@link http://php.net/manual/en/function.array-reduce.php PHP array_reduce() documentation}
+ * for examples of how the `$callback` and `$initial` parameters work.
+ *
+ * @param callable(TCarry, T): TCarry $callback A callable to apply to each
+ * item of the collection to reduce it to a single value.
+ * @param TCarry $initial This is the initial value provided to the callback.
+ *
+ * @return TCarry
+ *
+ * @template TCarry
+ */
+ public function reduce(callable $callback, mixed $initial): mixed;
+
/**
* Create a new collection with divergent items between current and given
* collection.
@@ -180,6 +218,9 @@ interface CollectionInterface extends ArrayInterface
* items.
*
* @return CollectionInterface
+ *
+ * @throws CollectionMismatchException if the compared collections are of
+ * differing types.
*/
public function diff(CollectionInterface $other): self;
@@ -191,6 +232,9 @@ interface CollectionInterface extends ArrayInterface
* intersecting items.
*
* @return CollectionInterface
+ *
+ * @throws CollectionMismatchException if the compared collections are of
+ * differing types.
*/
public function intersect(CollectionInterface $other): self;
@@ -200,6 +244,10 @@ interface CollectionInterface extends ArrayInterface
* @param CollectionInterface ...$collections The collections to merge.
*
* @return CollectionInterface
+ *
+ * @throws CollectionMismatchException if unable to merge any of the given
+ * collections or items within the given collections due to type
+ * mismatch errors.
*/
public function merge(CollectionInterface ...$collections): self;
}
diff --git a/vendor/ramsey/collection/src/DoubleEndedQueue.php b/vendor/ramsey/collection/src/DoubleEndedQueue.php
index 6ebdca5..62947a2 100644
--- a/vendor/ramsey/collection/src/DoubleEndedQueue.php
+++ b/vendor/ramsey/collection/src/DoubleEndedQueue.php
@@ -17,171 +17,150 @@ namespace Ramsey\Collection;
use Ramsey\Collection\Exception\InvalidArgumentException;
use Ramsey\Collection\Exception\NoSuchElementException;
+use function array_key_last;
+use function array_pop;
+use function array_unshift;
+
/**
* This class provides a basic implementation of `DoubleEndedQueueInterface`, to
* minimize the effort required to implement this interface.
*
* @template T
- * @template-extends Queue
- * @template-implements DoubleEndedQueueInterface
+ * @extends Queue
+ * @implements DoubleEndedQueueInterface
*/
class DoubleEndedQueue extends Queue implements DoubleEndedQueueInterface
{
/**
- * Index of the last element in the queue.
+ * Constructs a double-ended queue (dequeue) object of the specified type,
+ * optionally with the specified data.
*
- * @var int
+ * @param string $queueType The type or class name associated with this dequeue.
+ * @param array $data The initial items to store in the dequeue.
*/
- private $tail = -1;
-
- /**
- * @inheritDoc
- */
- public function offsetSet($offset, $value): void
+ public function __construct(private readonly string $queueType, array $data = [])
{
- if ($this->checkType($this->getType(), $value) === false) {
- throw new InvalidArgumentException(
- 'Value must be of type ' . $this->getType() . '; value is '
- . $this->toolValueToString($value)
- );
- }
-
- $this->tail++;
-
- $this->data[$this->tail] = $value;
+ parent::__construct($this->queueType, $data);
}
/**
- * @inheritDoc
+ * @throws InvalidArgumentException if $element is of the wrong type
*/
- public function addFirst($element): bool
+ public function addFirst(mixed $element): bool
{
if ($this->checkType($this->getType(), $element) === false) {
throw new InvalidArgumentException(
'Value must be of type ' . $this->getType() . '; value is '
- . $this->toolValueToString($element)
+ . $this->toolValueToString($element),
);
}
- $this->index--;
-
- $this->data[$this->index] = $element;
+ array_unshift($this->data, $element);
return true;
}
/**
- * @inheritDoc
+ * @throws InvalidArgumentException if $element is of the wrong type
*/
- public function addLast($element): bool
+ public function addLast(mixed $element): bool
{
return $this->add($element);
}
- /**
- * @inheritDoc
- */
- public function offerFirst($element): bool
+ public function offerFirst(mixed $element): bool
{
try {
return $this->addFirst($element);
- } catch (InvalidArgumentException $e) {
+ } catch (InvalidArgumentException) {
return false;
}
}
- /**
- * @inheritDoc
- */
- public function offerLast($element): bool
+ public function offerLast(mixed $element): bool
{
return $this->offer($element);
}
/**
- * @inheritDoc
+ * @return T the first element in this queue.
+ *
+ * @throws NoSuchElementException if the queue is empty
*/
- public function removeFirst()
+ public function removeFirst(): mixed
{
return $this->remove();
}
/**
- * @inheritDoc
+ * @return T the last element in this queue.
+ *
+ * @throws NoSuchElementException if this queue is empty.
*/
- public function removeLast()
+ public function removeLast(): mixed
{
- $tail = $this->pollLast();
-
- if ($tail === null) {
- throw new NoSuchElementException('Can\'t return element from Queue. Queue is empty.');
- }
-
- return $tail;
+ return $this->pollLast() ?? throw new NoSuchElementException(
+ 'Can\'t return element from Queue. Queue is empty.',
+ );
}
/**
- * @inheritDoc
+ * @return T | null the head of this queue, or `null` if this queue is empty.
*/
- public function pollFirst()
+ public function pollFirst(): mixed
{
return $this->poll();
}
/**
- * @inheritDoc
+ * @return T | null the tail of this queue, or `null` if this queue is empty.
*/
- public function pollLast()
+ public function pollLast(): mixed
{
- if ($this->count() === 0) {
- return null;
- }
-
- $tail = $this[$this->tail];
-
- unset($this[$this->tail]);
- $this->tail--;
-
- return $tail;
+ return array_pop($this->data);
}
/**
- * @inheritDoc
+ * @return T the head of this queue.
+ *
+ * @throws NoSuchElementException if this queue is empty.
*/
- public function firstElement()
+ public function firstElement(): mixed
{
return $this->element();
}
/**
- * @inheritDoc
+ * @return T the tail of this queue.
+ *
+ * @throws NoSuchElementException if this queue is empty.
*/
- public function lastElement()
+ public function lastElement(): mixed
{
- if ($this->count() === 0) {
- throw new NoSuchElementException('Can\'t return element from Queue. Queue is empty.');
- }
-
- return $this->data[$this->tail];
+ return $this->peekLast() ?? throw new NoSuchElementException(
+ 'Can\'t return element from Queue. Queue is empty.',
+ );
}
/**
- * @inheritDoc
+ * @return T | null the head of this queue, or `null` if this queue is empty.
*/
- public function peekFirst()
+ public function peekFirst(): mixed
{
return $this->peek();
}
/**
- * @inheritDoc
+ * @return T | null the tail of this queue, or `null` if this queue is empty.
*/
- public function peekLast()
+ public function peekLast(): mixed
{
- if ($this->count() === 0) {
+ $lastIndex = array_key_last($this->data);
+
+ if ($lastIndex === null) {
return null;
}
- return $this->data[$this->tail];
+ return $this->data[$lastIndex];
}
}
diff --git a/vendor/ramsey/collection/src/DoubleEndedQueueInterface.php b/vendor/ramsey/collection/src/DoubleEndedQueueInterface.php
index 67aae5e..15cc0e9 100644
--- a/vendor/ramsey/collection/src/DoubleEndedQueueInterface.php
+++ b/vendor/ramsey/collection/src/DoubleEndedQueueInterface.php
@@ -15,6 +15,7 @@ declare(strict_types=1);
namespace Ramsey\Collection;
use Ramsey\Collection\Exception\NoSuchElementException;
+use RuntimeException;
/**
* A linear collection that supports element insertion and removal at both ends.
@@ -160,7 +161,7 @@ use Ramsey\Collection\Exception\NoSuchElementException;
* empty.
*
* @template T
- * @template-extends QueueInterface
+ * @extends QueueInterface
*/
interface DoubleEndedQueueInterface extends QueueInterface
{
@@ -175,13 +176,12 @@ interface DoubleEndedQueueInterface extends QueueInterface
*
* @return bool `true` if this queue changed as a result of the call.
*
- * @throws \RuntimeException if a queue refuses to add a particular element
+ * @throws RuntimeException if a queue refuses to add a particular element
* for any reason other than that it already contains the element.
* Implementations should use a more-specific exception that extends
* `\RuntimeException`.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function addFirst($element): bool;
+ public function addFirst(mixed $element): bool;
/**
* Inserts the specified element at the end of this queue if it is possible
@@ -196,13 +196,12 @@ interface DoubleEndedQueueInterface extends QueueInterface
*
* @return bool `true` if this queue changed as a result of the call.
*
- * @throws \RuntimeException if a queue refuses to add a particular element
+ * @throws RuntimeException if a queue refuses to add a particular element
* for any reason other than that it already contains the element.
* Implementations should use a more-specific exception that extends
* `\RuntimeException`.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function addLast($element): bool;
+ public function addLast(mixed $element): bool;
/**
* Inserts the specified element at the front of this queue if it is
@@ -216,8 +215,7 @@ interface DoubleEndedQueueInterface extends QueueInterface
*
* @return bool `true` if the element was added to this queue, else `false`.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function offerFirst($element): bool;
+ public function offerFirst(mixed $element): bool;
/**
* Inserts the specified element at the end of this queue if it is possible
@@ -231,8 +229,7 @@ interface DoubleEndedQueueInterface extends QueueInterface
*
* @return bool `true` if the element was added to this queue, else `false`.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function offerLast($element): bool;
+ public function offerLast(mixed $element): bool;
/**
* Retrieves and removes the head of this queue.
@@ -244,7 +241,7 @@ interface DoubleEndedQueueInterface extends QueueInterface
*
* @throws NoSuchElementException if this queue is empty.
*/
- public function removeFirst();
+ public function removeFirst(): mixed;
/**
* Retrieves and removes the tail of this queue.
@@ -256,23 +253,23 @@ interface DoubleEndedQueueInterface extends QueueInterface
*
* @throws NoSuchElementException if this queue is empty.
*/
- public function removeLast();
+ public function removeLast(): mixed;
/**
* Retrieves and removes the head of this queue, or returns `null` if this
* queue is empty.
*
- * @return T|null the head of this queue, or `null` if this queue is empty.
+ * @return T | null the head of this queue, or `null` if this queue is empty.
*/
- public function pollFirst();
+ public function pollFirst(): mixed;
/**
* Retrieves and removes the tail of this queue, or returns `null` if this
* queue is empty.
*
- * @return T|null the tail of this queue, or `null` if this queue is empty.
+ * @return T | null the tail of this queue, or `null` if this queue is empty.
*/
- public function pollLast();
+ public function pollLast(): mixed;
/**
* Retrieves, but does not remove, the head of this queue.
@@ -284,7 +281,7 @@ interface DoubleEndedQueueInterface extends QueueInterface
*
* @throws NoSuchElementException if this queue is empty.
*/
- public function firstElement();
+ public function firstElement(): mixed;
/**
* Retrieves, but does not remove, the tail of this queue.
@@ -296,21 +293,21 @@ interface DoubleEndedQueueInterface extends QueueInterface
*
* @throws NoSuchElementException if this queue is empty.
*/
- public function lastElement();
+ public function lastElement(): mixed;
/**
* Retrieves, but does not remove, the head of this queue, or returns `null`
* if this queue is empty.
*
- * @return T|null the head of this queue, or `null` if this queue is empty.
+ * @return T | null the head of this queue, or `null` if this queue is empty.
*/
- public function peekFirst();
+ public function peekFirst(): mixed;
/**
* Retrieves, but does not remove, the tail of this queue, or returns `null`
* if this queue is empty.
*
- * @return T|null the tail of this queue, or `null` if this queue is empty.
+ * @return T | null the tail of this queue, or `null` if this queue is empty.
*/
- public function peekLast();
+ public function peekLast(): mixed;
}
diff --git a/vendor/ramsey/collection/src/Exception/InvalidSortOrderException.php b/vendor/ramsey/collection/src/Exception/CollectionException.php
similarity index 73%
rename from vendor/ramsey/collection/src/Exception/InvalidSortOrderException.php
rename to vendor/ramsey/collection/src/Exception/CollectionException.php
index 9337ccc..4aa92be 100644
--- a/vendor/ramsey/collection/src/Exception/InvalidSortOrderException.php
+++ b/vendor/ramsey/collection/src/Exception/CollectionException.php
@@ -14,9 +14,8 @@ declare(strict_types=1);
namespace Ramsey\Collection\Exception;
-/**
- * Thrown when attempting to use a sort order that is not recognized.
- */
-class InvalidSortOrderException extends \RuntimeException
+use Throwable;
+
+interface CollectionException extends Throwable
{
}
diff --git a/vendor/ramsey/collection/src/Exception/CollectionMismatchException.php b/vendor/ramsey/collection/src/Exception/CollectionMismatchException.php
index d4b335f..42f5be2 100644
--- a/vendor/ramsey/collection/src/Exception/CollectionMismatchException.php
+++ b/vendor/ramsey/collection/src/Exception/CollectionMismatchException.php
@@ -14,9 +14,11 @@ declare(strict_types=1);
namespace Ramsey\Collection\Exception;
+use RuntimeException;
+
/**
* Thrown when attempting to operate on collections of differing types.
*/
-class CollectionMismatchException extends \RuntimeException
+class CollectionMismatchException extends RuntimeException implements CollectionException
{
}
diff --git a/vendor/ramsey/collection/src/Exception/InvalidArgumentException.php b/vendor/ramsey/collection/src/Exception/InvalidArgumentException.php
index dcc3eac..7b41b4a 100644
--- a/vendor/ramsey/collection/src/Exception/InvalidArgumentException.php
+++ b/vendor/ramsey/collection/src/Exception/InvalidArgumentException.php
@@ -14,9 +14,11 @@ declare(strict_types=1);
namespace Ramsey\Collection\Exception;
+use InvalidArgumentException as PhpInvalidArgumentException;
+
/**
* Thrown to indicate an argument is not of the expected type.
*/
-class InvalidArgumentException extends \InvalidArgumentException
+class InvalidArgumentException extends PhpInvalidArgumentException implements CollectionException
{
}
diff --git a/vendor/ramsey/collection/src/Exception/ValueExtractionException.php b/vendor/ramsey/collection/src/Exception/InvalidPropertyOrMethod.php
similarity index 58%
rename from vendor/ramsey/collection/src/Exception/ValueExtractionException.php
rename to vendor/ramsey/collection/src/Exception/InvalidPropertyOrMethod.php
index f6c6cb4..a53be14 100644
--- a/vendor/ramsey/collection/src/Exception/ValueExtractionException.php
+++ b/vendor/ramsey/collection/src/Exception/InvalidPropertyOrMethod.php
@@ -14,9 +14,13 @@ declare(strict_types=1);
namespace Ramsey\Collection\Exception;
+use RuntimeException;
+
/**
- * Thrown when attempting to extract a value for a method or property that does not exist.
+ * Thrown when attempting to evaluate a property, method, or array key
+ * that doesn't exist on an element or cannot otherwise be evaluated in the
+ * current context.
*/
-class ValueExtractionException extends \RuntimeException
+class InvalidPropertyOrMethod extends RuntimeException implements CollectionException
{
}
diff --git a/vendor/ramsey/collection/src/Exception/NoSuchElementException.php b/vendor/ramsey/collection/src/Exception/NoSuchElementException.php
index 9debe8f..cd98f0c 100644
--- a/vendor/ramsey/collection/src/Exception/NoSuchElementException.php
+++ b/vendor/ramsey/collection/src/Exception/NoSuchElementException.php
@@ -14,9 +14,11 @@ declare(strict_types=1);
namespace Ramsey\Collection\Exception;
+use RuntimeException;
+
/**
* Thrown when attempting to access an element that does not exist.
*/
-class NoSuchElementException extends \RuntimeException
+class NoSuchElementException extends RuntimeException implements CollectionException
{
}
diff --git a/vendor/ramsey/collection/src/Exception/OutOfBoundsException.php b/vendor/ramsey/collection/src/Exception/OutOfBoundsException.php
index 4e9d16f..c75294e 100644
--- a/vendor/ramsey/collection/src/Exception/OutOfBoundsException.php
+++ b/vendor/ramsey/collection/src/Exception/OutOfBoundsException.php
@@ -14,9 +14,11 @@ declare(strict_types=1);
namespace Ramsey\Collection\Exception;
+use OutOfBoundsException as PhpOutOfBoundsException;
+
/**
* Thrown when attempting to access an element out of the range of the collection.
*/
-class OutOfBoundsException extends \OutOfBoundsException
+class OutOfBoundsException extends PhpOutOfBoundsException implements CollectionException
{
}
diff --git a/vendor/ramsey/collection/src/Exception/UnsupportedOperationException.php b/vendor/ramsey/collection/src/Exception/UnsupportedOperationException.php
index 8f45e58..d074f45 100644
--- a/vendor/ramsey/collection/src/Exception/UnsupportedOperationException.php
+++ b/vendor/ramsey/collection/src/Exception/UnsupportedOperationException.php
@@ -14,9 +14,11 @@ declare(strict_types=1);
namespace Ramsey\Collection\Exception;
+use RuntimeException;
+
/**
* Thrown to indicate that the requested operation is not supported.
*/
-class UnsupportedOperationException extends \RuntimeException
+class UnsupportedOperationException extends RuntimeException implements CollectionException
{
}
diff --git a/vendor/ramsey/collection/src/GenericArray.php b/vendor/ramsey/collection/src/GenericArray.php
index 9b95df3..2b079aa 100644
--- a/vendor/ramsey/collection/src/GenericArray.php
+++ b/vendor/ramsey/collection/src/GenericArray.php
@@ -17,7 +17,7 @@ namespace Ramsey\Collection;
/**
* `GenericArray` represents a standard array object.
*
- * @template-extends AbstractArray
+ * @extends AbstractArray
*/
class GenericArray extends AbstractArray
{
diff --git a/vendor/ramsey/collection/src/Map/AbstractMap.php b/vendor/ramsey/collection/src/Map/AbstractMap.php
index 70f7116..92f23e6 100644
--- a/vendor/ramsey/collection/src/Map/AbstractMap.php
+++ b/vendor/ramsey/collection/src/Map/AbstractMap.php
@@ -16,48 +16,64 @@ namespace Ramsey\Collection\Map;
use Ramsey\Collection\AbstractArray;
use Ramsey\Collection\Exception\InvalidArgumentException;
+use Traversable;
use function array_key_exists;
use function array_keys;
use function in_array;
+use function var_export;
/**
* This class provides a basic implementation of `MapInterface`, to minimize the
* effort required to implement this interface.
*
+ * @template K of array-key
* @template T
- * @template-extends AbstractArray
- * @template-implements MapInterface
+ * @extends AbstractArray
+ * @implements MapInterface
*/
abstract class AbstractMap extends AbstractArray implements MapInterface
{
/**
+ * @param array $data The initial items to add to this map.
+ */
+ public function __construct(array $data = [])
+ {
+ parent::__construct($data);
+ }
+
+ /**
+ * @return Traversable
+ */
+ public function getIterator(): Traversable
+ {
+ return parent::getIterator();
+ }
+
+ /**
+ * @param K $offset The offset to set
+ * @param T $value The value to set at the given offset.
+ *
* @inheritDoc
*/
- public function offsetSet($offset, $value): void
+ public function offsetSet(mixed $offset, mixed $value): void
{
if ($offset === null) {
throw new InvalidArgumentException(
'Map elements are key/value pairs; a key must be provided for '
- . 'value ' . var_export($value, true)
+ . 'value ' . var_export($value, true),
);
}
$this->data[$offset] = $value;
}
- /**
- * @inheritDoc
- */
- public function containsKey($key): bool
+ public function containsKey(int | string $key): bool
{
return array_key_exists($key, $this->data);
}
- /**
- * @inheritDoc
- */
- public function containsValue($value): bool
+ public function containsValue(mixed $value): bool
{
return in_array($value, $this->data, true);
}
@@ -67,25 +83,29 @@ abstract class AbstractMap extends AbstractArray implements MapInterface
*/
public function keys(): array
{
+ /** @var list */
return array_keys($this->data);
}
/**
- * @inheritDoc
+ * @param K $key The key to return from the map.
+ * @param T | null $defaultValue The default value to use if `$key` is not found.
+ *
+ * @return T | null the value or `null` if the key could not be found.
*/
- public function get($key, $defaultValue = null)
+ public function get(int | string $key, mixed $defaultValue = null): mixed
{
- if (!$this->containsKey($key)) {
- return $defaultValue;
- }
-
- return $this[$key];
+ return $this[$key] ?? $defaultValue;
}
/**
- * @inheritDoc
+ * @param K $key The key to put or replace in the map.
+ * @param T $value The value to store at `$key`.
+ *
+ * @return T | null the previous value associated with key, or `null` if
+ * there was no mapping for `$key`.
*/
- public function put($key, $value)
+ public function put(int | string $key, mixed $value): mixed
{
$previousValue = $this->get($key);
$this[$key] = $value;
@@ -94,9 +114,13 @@ abstract class AbstractMap extends AbstractArray implements MapInterface
}
/**
- * @inheritDoc
+ * @param K $key The key to put in the map.
+ * @param T $value The value to store at `$key`.
+ *
+ * @return T | null the previous value associated with key, or `null` if
+ * there was no mapping for `$key`.
*/
- public function putIfAbsent($key, $value)
+ public function putIfAbsent(int | string $key, mixed $value): mixed
{
$currentValue = $this->get($key);
@@ -108,9 +132,12 @@ abstract class AbstractMap extends AbstractArray implements MapInterface
}
/**
- * @inheritDoc
+ * @param K $key The key to remove from the map.
+ *
+ * @return T | null the previous value associated with key, or `null` if
+ * there was no mapping for `$key`.
*/
- public function remove($key)
+ public function remove(int | string $key): mixed
{
$previousValue = $this->get($key);
unset($this[$key]);
@@ -118,10 +145,7 @@ abstract class AbstractMap extends AbstractArray implements MapInterface
return $previousValue;
}
- /**
- * @inheritDoc
- */
- public function removeIf($key, $value): bool
+ public function removeIf(int | string $key, mixed $value): bool
{
if ($this->get($key) === $value) {
unset($this[$key]);
@@ -133,9 +157,13 @@ abstract class AbstractMap extends AbstractArray implements MapInterface
}
/**
- * @inheritDoc
+ * @param K $key The key to replace.
+ * @param T $value The value to set at `$key`.
+ *
+ * @return T | null the previous value associated with key, or `null` if
+ * there was no mapping for `$key`.
*/
- public function replace($key, $value)
+ public function replace(int | string $key, mixed $value): mixed
{
$currentValue = $this->get($key);
@@ -146,10 +174,7 @@ abstract class AbstractMap extends AbstractArray implements MapInterface
return $currentValue;
}
- /**
- * @inheritDoc
- */
- public function replaceIf($key, $oldValue, $newValue): bool
+ public function replaceIf(int | string $key, mixed $oldValue, mixed $newValue): bool
{
if ($this->get($key) === $oldValue) {
$this[$key] = $newValue;
@@ -159,4 +184,22 @@ abstract class AbstractMap extends AbstractArray implements MapInterface
return false;
}
+
+ /**
+ * @return array
+ */
+ public function __serialize(): array
+ {
+ /** @var array */
+ return parent::__serialize();
+ }
+
+ /**
+ * @return array
+ */
+ public function toArray(): array
+ {
+ /** @var array */
+ return parent::toArray();
+ }
}
diff --git a/vendor/ramsey/collection/src/Map/AbstractTypedMap.php b/vendor/ramsey/collection/src/Map/AbstractTypedMap.php
index baa6793..8b6cc04 100644
--- a/vendor/ramsey/collection/src/Map/AbstractTypedMap.php
+++ b/vendor/ramsey/collection/src/Map/AbstractTypedMap.php
@@ -22,10 +22,10 @@ use Ramsey\Collection\Tool\ValueToStringTrait;
* This class provides a basic implementation of `TypedMapInterface`, to
* minimize the effort required to implement this interface.
*
- * @template K
+ * @template K of array-key
* @template T
- * @template-extends AbstractMap
- * @template-implements TypedMapInterface
+ * @extends AbstractMap
+ * @implements TypedMapInterface
*/
abstract class AbstractTypedMap extends AbstractMap implements TypedMapInterface
{
@@ -33,37 +33,27 @@ abstract class AbstractTypedMap extends AbstractMap implements TypedMapInterface
use ValueToStringTrait;
/**
- * @param K|null $offset
+ * @param K $offset
* @param T $value
*
* @inheritDoc
- *
- * @psalm-suppress MoreSpecificImplementedParamType
*/
- public function offsetSet($offset, $value): void
+ public function offsetSet(mixed $offset, mixed $value): void
{
- if ($offset === null) {
- throw new InvalidArgumentException(
- 'Map elements are key/value pairs; a key must be provided for '
- . 'value ' . var_export($value, true)
- );
- }
-
if ($this->checkType($this->getKeyType(), $offset) === false) {
throw new InvalidArgumentException(
'Key must be of type ' . $this->getKeyType() . '; key is '
- . $this->toolValueToString($offset)
+ . $this->toolValueToString($offset),
);
}
if ($this->checkType($this->getValueType(), $value) === false) {
throw new InvalidArgumentException(
'Value must be of type ' . $this->getValueType() . '; value is '
- . $this->toolValueToString($value)
+ . $this->toolValueToString($value),
);
}
- /** @psalm-suppress MixedArgumentTypeCoercion */
parent::offsetSet($offset, $value);
}
}
diff --git a/vendor/ramsey/collection/src/Map/AssociativeArrayMap.php b/vendor/ramsey/collection/src/Map/AssociativeArrayMap.php
index 3274dc9..34e4e85 100644
--- a/vendor/ramsey/collection/src/Map/AssociativeArrayMap.php
+++ b/vendor/ramsey/collection/src/Map/AssociativeArrayMap.php
@@ -17,8 +17,7 @@ namespace Ramsey\Collection\Map;
/**
* `AssociativeArrayMap` represents a standard associative array object.
*
- * @template T
- * @template-extends AbstractMap
+ * @extends AbstractMap
*/
class AssociativeArrayMap extends AbstractMap
{
diff --git a/vendor/ramsey/collection/src/Map/MapInterface.php b/vendor/ramsey/collection/src/Map/MapInterface.php
index 04e52a2..22ba1bd 100644
--- a/vendor/ramsey/collection/src/Map/MapInterface.php
+++ b/vendor/ramsey/collection/src/Map/MapInterface.php
@@ -21,17 +21,18 @@ use Ramsey\Collection\ArrayInterface;
*
* A map cannot contain duplicate keys; each key can map to at most one value.
*
+ * @template K of array-key
* @template T
- * @template-extends ArrayInterface
+ * @extends ArrayInterface
*/
interface MapInterface extends ArrayInterface
{
/**
* Returns `true` if this map contains a mapping for the specified key.
*
- * @param array-key $key The key to check in the map.
+ * @param K $key The key to check in the map.
*/
- public function containsKey($key): bool;
+ public function containsKey(int | string $key): bool;
/**
* Returns `true` if this map maps one or more keys to the specified value.
@@ -40,13 +41,12 @@ interface MapInterface extends ArrayInterface
*
* @param T $value The value to check in the map.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function containsValue($value): bool;
+ public function containsValue(mixed $value): bool;
/**
* Return an array of the keys contained in this map.
*
- * @return list
+ * @return list
*/
public function keys(): array;
@@ -55,13 +55,12 @@ interface MapInterface extends ArrayInterface
* map contains no mapping for the key, or (optionally) `$defaultValue` if
* this map contains no mapping for the key.
*
- * @param array-key $key The key to return from the map.
- * @param T|null $defaultValue The default value to use if `$key` is not found.
+ * @param K $key The key to return from the map.
+ * @param T | null $defaultValue The default value to use if `$key` is not found.
*
- * @return T|null the value or `null` if the key could not be found.
+ * @return T | null the value or `null` if the key could not be found.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function get($key, $defaultValue = null);
+ public function get(int | string $key, mixed $defaultValue = null): mixed;
/**
* Associates the specified value with the specified key in this map.
@@ -69,14 +68,13 @@ interface MapInterface extends ArrayInterface
* If the map previously contained a mapping for the key, the old value is
* replaced by the specified value.
*
- * @param array-key $key The key to put or replace in the map.
+ * @param K $key The key to put or replace in the map.
* @param T $value The value to store at `$key`.
*
- * @return T|null the previous value associated with key, or `null` if
+ * @return T | null the previous value associated with key, or `null` if
* there was no mapping for `$key`.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function put($key, $value);
+ public function put(int | string $key, mixed $value): mixed;
/**
* Associates the specified value with the specified key in this map only if
@@ -85,25 +83,23 @@ interface MapInterface extends ArrayInterface
* If there is already a value associated with `$key`, this returns that
* value without replacing it.
*
- * @param array-key $key The key to put in the map.
+ * @param K $key The key to put in the map.
* @param T $value The value to store at `$key`.
*
- * @return T|null the previous value associated with key, or `null` if
+ * @return T | null the previous value associated with key, or `null` if
* there was no mapping for `$key`.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function putIfAbsent($key, $value);
+ public function putIfAbsent(int | string $key, mixed $value): mixed;
/**
* Removes the mapping for a key from this map if it is present.
*
- * @param array-key $key The key to remove from the map.
+ * @param K $key The key to remove from the map.
*
- * @return T|null the previous value associated with key, or `null` if
+ * @return T | null the previous value associated with key, or `null` if
* there was no mapping for `$key`.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function remove($key);
+ public function remove(int | string $key): mixed;
/**
* Removes the entry for the specified key only if it is currently mapped to
@@ -111,26 +107,24 @@ interface MapInterface extends ArrayInterface
*
* This performs a strict type check on the value.
*
- * @param array-key $key The key to remove from the map.
+ * @param K $key The key to remove from the map.
* @param T $value The value to match.
*
* @return bool true if the value was removed.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function removeIf($key, $value): bool;
+ public function removeIf(int | string $key, mixed $value): bool;
/**
* Replaces the entry for the specified key only if it is currently mapped
* to some value.
*
- * @param array-key $key The key to replace.
+ * @param K $key The key to replace.
* @param T $value The value to set at `$key`.
*
- * @return T|null the previous value associated with key, or `null` if
+ * @return T | null the previous value associated with key, or `null` if
* there was no mapping for `$key`.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function replace($key, $value);
+ public function replace(int | string $key, mixed $value): mixed;
/**
* Replaces the entry for the specified key only if currently mapped to the
@@ -138,12 +132,11 @@ interface MapInterface extends ArrayInterface
*
* This performs a strict type check on the value.
*
- * @param array-key $key The key to remove from the map.
+ * @param K $key The key to remove from the map.
* @param T $oldValue The value to match.
* @param T $newValue The value to use as a replacement.
*
* @return bool true if the value was replaced.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function replaceIf($key, $oldValue, $newValue): bool;
+ public function replaceIf(int | string $key, mixed $oldValue, mixed $newValue): bool;
}
diff --git a/vendor/ramsey/collection/src/Map/NamedParameterMap.php b/vendor/ramsey/collection/src/Map/NamedParameterMap.php
index ecc52f7..f948e47 100644
--- a/vendor/ramsey/collection/src/Map/NamedParameterMap.php
+++ b/vendor/ramsey/collection/src/Map/NamedParameterMap.php
@@ -26,7 +26,7 @@ use function is_int;
* `NamedParameterMap` represents a mapping of values to a set of named keys
* that may optionally be typed
*
- * @template-extends AbstractMap
+ * @extends AbstractMap
*/
class NamedParameterMap extends AbstractMap
{
@@ -38,13 +38,13 @@ class NamedParameterMap extends AbstractMap
*
* @var array
*/
- protected $namedParameters;
+ private readonly array $namedParameters;
/**
* Constructs a new `NamedParameterMap`.
*
* @param array $namedParameters The named parameters defined for this map.
- * @param array $data An initial set of data to set on this map.
+ * @param array $data An initial set of data to set on this map.
*/
public function __construct(array $namedParameters, array $data = [])
{
@@ -62,22 +62,12 @@ class NamedParameterMap extends AbstractMap
return $this->namedParameters;
}
- /**
- * @inheritDoc
- */
- public function offsetSet($offset, $value): void
+ public function offsetSet(mixed $offset, mixed $value): void
{
- if ($offset === null) {
- throw new InvalidArgumentException(
- 'Map elements are key/value pairs; a key must be provided for '
- . 'value ' . var_export($value, true)
- );
- }
-
if (!array_key_exists($offset, $this->namedParameters)) {
throw new InvalidArgumentException(
'Attempting to set value for unconfigured parameter \''
- . $offset . '\''
+ . $this->toolValueToString($offset) . '\'',
);
}
@@ -85,7 +75,7 @@ class NamedParameterMap extends AbstractMap
throw new InvalidArgumentException(
'Value for \'' . $offset . '\' must be of type '
. $this->namedParameters[$offset] . '; value is '
- . $this->toolValueToString($value)
+ . $this->toolValueToString($value),
);
}
diff --git a/vendor/ramsey/collection/src/Map/TypedMap.php b/vendor/ramsey/collection/src/Map/TypedMap.php
index 094551a..4a090c8 100644
--- a/vendor/ramsey/collection/src/Map/TypedMap.php
+++ b/vendor/ramsey/collection/src/Map/TypedMap.php
@@ -14,13 +14,11 @@ declare(strict_types=1);
namespace Ramsey\Collection\Map;
-use Ramsey\Collection\Tool\TypeTrait;
-
/**
* A `TypedMap` represents a map of elements where key and value are typed.
*
* Each element is identified by a key with defined type and a value of defined
- * type. The keys of the map must be unique. The values on the map can be=
+ * type. The keys of the map must be unique. The values on the map can be
* repeated but each with its own different key.
*
* The most common case is to use a string type key, but it's not limited to
@@ -31,7 +29,7 @@ use Ramsey\Collection\Tool\TypeTrait;
*
* Example usage:
*
- * ```php
+ * ```
* $map = new TypedMap('string', Foo::class);
* $map['x'] = new Foo();
* foreach ($map as $key => $value) {
@@ -53,7 +51,7 @@ use Ramsey\Collection\Tool\TypeTrait;
* It is preferable to subclass `AbstractTypedMap` to create your own typed map
* implementation:
*
- * ```php
+ * ```
* class FooTypedMap extends AbstractTypedMap
* {
* public function getKeyType()
@@ -70,7 +68,7 @@ use Ramsey\Collection\Tool\TypeTrait;
*
* … but you also may use the `TypedMap` class:
*
- * ```php
+ * ```
* class FooTypedMap extends TypedMap
* {
* public function __constructor(array $data = [])
@@ -80,34 +78,12 @@ use Ramsey\Collection\Tool\TypeTrait;
* }
* ```
*
- * @template K
+ * @template K of array-key
* @template T
- * @template-extends AbstractTypedMap
+ * @extends AbstractTypedMap
*/
class TypedMap extends AbstractTypedMap
{
- use TypeTrait;
-
- /**
- * The data type of keys stored in this collection.
- *
- * A map key's type is immutable once it is set. For this reason, this
- * property is set private.
- *
- * @var string data type of the map key.
- */
- private $keyType;
-
- /**
- * The data type of values stored in this collection.
- *
- * A map value's type is immutable once it is set. For this reason, this
- * property is set private.
- *
- * @var string data type of the map value.
- */
- private $valueType;
-
/**
* Constructs a map object of the specified key and value types,
* optionally with the specified data.
@@ -116,12 +92,11 @@ class TypedMap extends AbstractTypedMap
* @param string $valueType The data type of the map's values.
* @param array $data The initial data to set for this map.
*/
- public function __construct(string $keyType, string $valueType, array $data = [])
- {
- $this->keyType = $keyType;
- $this->valueType = $valueType;
-
- /** @psalm-suppress MixedArgumentTypeCoercion */
+ public function __construct(
+ private readonly string $keyType,
+ private readonly string $valueType,
+ array $data = [],
+ ) {
parent::__construct($data);
}
diff --git a/vendor/ramsey/collection/src/Map/TypedMapInterface.php b/vendor/ramsey/collection/src/Map/TypedMapInterface.php
index 51b6a81..5a44f06 100644
--- a/vendor/ramsey/collection/src/Map/TypedMapInterface.php
+++ b/vendor/ramsey/collection/src/Map/TypedMapInterface.php
@@ -18,8 +18,9 @@ namespace Ramsey\Collection\Map;
* A `TypedMapInterface` represents a map of elements where key and value are
* typed.
*
+ * @template K of array-key
* @template T
- * @template-extends MapInterface
+ * @extends MapInterface
*/
interface TypedMapInterface extends MapInterface
{
diff --git a/vendor/ramsey/collection/src/Queue.php b/vendor/ramsey/collection/src/Queue.php
index 4af2fdf..0f5b337 100644
--- a/vendor/ramsey/collection/src/Queue.php
+++ b/vendor/ramsey/collection/src/Queue.php
@@ -19,46 +19,30 @@ use Ramsey\Collection\Exception\NoSuchElementException;
use Ramsey\Collection\Tool\TypeTrait;
use Ramsey\Collection\Tool\ValueToStringTrait;
+use function array_key_first;
+
/**
* This class provides a basic implementation of `QueueInterface`, to minimize
* the effort required to implement this interface.
*
* @template T
- * @template-extends AbstractArray
- * @template-implements QueueInterface
+ * @extends AbstractArray
+ * @implements QueueInterface
*/
class Queue extends AbstractArray implements QueueInterface
{
use TypeTrait;
use ValueToStringTrait;
- /**
- * The type of elements stored in this queue.
- *
- * A queue's type is immutable once it is set. For this reason, this
- * property is set private.
- *
- * @var string
- */
- private $queueType;
-
- /**
- * The index of the head of the queue.
- *
- * @var int
- */
- protected $index = 0;
-
/**
* Constructs a queue object of the specified type, optionally with the
* specified data.
*
- * @param string $queueType The type (FQCN) associated with this queue.
- * @param array $data The initial items to store in the collection.
+ * @param string $queueType The type or class name associated with this queue.
+ * @param array $data The initial items to store in the queue.
*/
- public function __construct(string $queueType, array $data = [])
+ public function __construct(private readonly string $queueType, array $data = [])
{
- $this->queueType = $queueType;
parent::__construct($data);
}
@@ -68,13 +52,15 @@ class Queue extends AbstractArray implements QueueInterface
* Since arbitrary offsets may not be manipulated in a queue, this method
* serves only to fulfill the `ArrayAccess` interface requirements. It is
* invoked by other operations when adding values to the queue.
+ *
+ * @throws InvalidArgumentException if $value is of the wrong type.
*/
- public function offsetSet($offset, $value): void
+ public function offsetSet(mixed $offset, mixed $value): void
{
if ($this->checkType($this->getType(), $value) === false) {
throw new InvalidArgumentException(
'Value must be of type ' . $this->getType() . '; value is '
- . $this->toolValueToString($value)
+ . $this->toolValueToString($value),
);
}
@@ -82,9 +68,9 @@ class Queue extends AbstractArray implements QueueInterface
}
/**
- * @inheritDoc
+ * @throws InvalidArgumentException if $value is of the wrong type.
*/
- public function add($element): bool
+ public function add(mixed $element): bool
{
$this[] = $element;
@@ -92,74 +78,67 @@ class Queue extends AbstractArray implements QueueInterface
}
/**
- * @inheritDoc
+ * @return T
+ *
+ * @throws NoSuchElementException if this queue is empty.
*/
- public function element()
+ public function element(): mixed
{
- $element = $this->peek();
-
- if ($element === null) {
- throw new NoSuchElementException(
- 'Can\'t return element from Queue. Queue is empty.'
- );
- }
-
- return $element;
+ return $this->peek() ?? throw new NoSuchElementException(
+ 'Can\'t return element from Queue. Queue is empty.',
+ );
}
- /**
- * @inheritDoc
- */
- public function offer($element): bool
+ public function offer(mixed $element): bool
{
try {
return $this->add($element);
- } catch (InvalidArgumentException $e) {
+ } catch (InvalidArgumentException) {
return false;
}
}
/**
- * @inheritDoc
+ * @return T | null
*/
- public function peek()
+ public function peek(): mixed
{
- if ($this->count() === 0) {
+ $index = array_key_first($this->data);
+
+ if ($index === null) {
return null;
}
- return $this[$this->index];
+ return $this[$index];
}
/**
- * @inheritDoc
+ * @return T | null
*/
- public function poll()
+ public function poll(): mixed
{
- if ($this->count() === 0) {
+ $index = array_key_first($this->data);
+
+ if ($index === null) {
return null;
}
- $head = $this[$this->index];
-
- unset($this[$this->index]);
- $this->index++;
+ $head = $this[$index];
+ unset($this[$index]);
return $head;
}
/**
- * @inheritDoc
+ * @return T
+ *
+ * @throws NoSuchElementException if this queue is empty.
*/
- public function remove()
+ public function remove(): mixed
{
- $head = $this->poll();
-
- if ($head === null) {
- throw new NoSuchElementException('Can\'t return element from Queue. Queue is empty.');
- }
-
- return $head;
+ return $this->poll() ?? throw new NoSuchElementException(
+ 'Can\'t return element from Queue. Queue is empty.',
+ );
}
public function getType(): string
diff --git a/vendor/ramsey/collection/src/QueueInterface.php b/vendor/ramsey/collection/src/QueueInterface.php
index 7ebbb5d..f29ce43 100644
--- a/vendor/ramsey/collection/src/QueueInterface.php
+++ b/vendor/ramsey/collection/src/QueueInterface.php
@@ -15,6 +15,7 @@ declare(strict_types=1);
namespace Ramsey\Collection;
use Ramsey\Collection\Exception\NoSuchElementException;
+use RuntimeException;
/**
* A queue is a collection in which the entities in the collection are kept in
@@ -94,7 +95,7 @@ use Ramsey\Collection\Exception\NoSuchElementException;
* `poll()` method to indicate that the queue contains no elements.
*
* @template T
- * @template-extends ArrayInterface
+ * @extends ArrayInterface
*/
interface QueueInterface extends ArrayInterface
{
@@ -123,13 +124,12 @@ interface QueueInterface extends ArrayInterface
*
* @return bool `true` if this queue changed as a result of the call.
*
- * @throws \RuntimeException if a queue refuses to add a particular element
+ * @throws RuntimeException if a queue refuses to add a particular element
* for any reason other than that it already contains the element.
* Implementations should use a more-specific exception that extends
* `\RuntimeException`.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function add($element): bool;
+ public function add(mixed $element): bool;
/**
* Retrieves, but does not remove, the head of this queue.
@@ -143,7 +143,7 @@ interface QueueInterface extends ArrayInterface
*
* @throws NoSuchElementException if this queue is empty.
*/
- public function element();
+ public function element(): mixed;
/**
* Inserts the specified element into this queue if it is possible to do so
@@ -159,8 +159,7 @@ interface QueueInterface extends ArrayInterface
*
* @return bool `true` if the element was added to this queue, else `false`.
*/
- // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- public function offer($element): bool;
+ public function offer(mixed $element): bool;
/**
* Retrieves, but does not remove, the head of this queue, or returns `null`
@@ -168,9 +167,9 @@ interface QueueInterface extends ArrayInterface
*
* @see self::element()
*
- * @return T|null the head of this queue, or `null` if this queue is empty.
+ * @return T | null the head of this queue, or `null` if this queue is empty.
*/
- public function peek();
+ public function peek(): mixed;
/**
* Retrieves and removes the head of this queue, or returns `null`
@@ -178,9 +177,9 @@ interface QueueInterface extends ArrayInterface
*
* @see self::remove()
*
- * @return T|null the head of this queue, or `null` if this queue is empty.
+ * @return T | null the head of this queue, or `null` if this queue is empty.
*/
- public function poll();
+ public function poll(): mixed;
/**
* Retrieves and removes the head of this queue.
@@ -194,7 +193,7 @@ interface QueueInterface extends ArrayInterface
*
* @throws NoSuchElementException if this queue is empty.
*/
- public function remove();
+ public function remove(): mixed;
/**
* Returns the type associated with this queue.
diff --git a/vendor/ramsey/collection/src/Set.php b/vendor/ramsey/collection/src/Set.php
index ac1c5cb..d60f248 100644
--- a/vendor/ramsey/collection/src/Set.php
+++ b/vendor/ramsey/collection/src/Set.php
@@ -24,11 +24,11 @@ namespace Ramsey\Collection;
*
* Example usage:
*
- * ``` php
+ * ```
* $foo = new \My\Foo();
* $set = new Set(\My\Foo::class);
*
- * $set->add($foo); // returns TRUE, the element don't exists
+ * $set->add($foo); // returns TRUE, the element doesn't exist
* $set->add($foo); // returns FALSE, the element already exists
*
* $bar = new \My\Foo();
@@ -36,29 +36,19 @@ namespace Ramsey\Collection;
* ```
*
* @template T
- * @template-extends AbstractSet
+ * @extends AbstractSet
*/
class Set extends AbstractSet
{
- /**
- * The type of elements stored in this set
- *
- * A set's type is immutable. For this reason, this property is private.
- *
- * @var string
- */
- private $setType;
-
/**
* Constructs a set object of the specified type, optionally with the
* specified data.
*
- * @param string $setType The type (FQCN) associated with this set.
+ * @param string $setType The type or class name associated with this set.
* @param array $data The initial items to store in the set.
*/
- public function __construct(string $setType, array $data = [])
+ public function __construct(private readonly string $setType, array $data = [])
{
- $this->setType = $setType;
parent::__construct($data);
}
diff --git a/vendor/ramsey/collection/src/Sort.php b/vendor/ramsey/collection/src/Sort.php
new file mode 100644
index 0000000..0c3c192
--- /dev/null
+++ b/vendor/ramsey/collection/src/Sort.php
@@ -0,0 +1,31 @@
+
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Collection;
+
+/**
+ * Collection sorting
+ */
+enum Sort: string
+{
+ /**
+ * Sort items in a collection in ascending order.
+ */
+ case Ascending = 'asc';
+
+ /**
+ * Sort items in a collection in descending order.
+ */
+ case Descending = 'desc';
+}
diff --git a/vendor/ramsey/collection/src/Tool/TypeTrait.php b/vendor/ramsey/collection/src/Tool/TypeTrait.php
index 8214e96..ac51b7f 100644
--- a/vendor/ramsey/collection/src/Tool/TypeTrait.php
+++ b/vendor/ramsey/collection/src/Tool/TypeTrait.php
@@ -36,38 +36,22 @@ trait TypeTrait
* @param string $type The type to check the value against.
* @param mixed $value The value to check.
*/
- protected function checkType(string $type, $value): bool
+ protected function checkType(string $type, mixed $value): bool
{
- switch ($type) {
- case 'array':
- return is_array($value);
- case 'bool':
- case 'boolean':
- return is_bool($value);
- case 'callable':
- return is_callable($value);
- case 'float':
- case 'double':
- return is_float($value);
- case 'int':
- case 'integer':
- return is_int($value);
- case 'null':
- return $value === null;
- case 'numeric':
- return is_numeric($value);
- case 'object':
- return is_object($value);
- case 'resource':
- return is_resource($value);
- case 'scalar':
- return is_scalar($value);
- case 'string':
- return is_string($value);
- case 'mixed':
- return true;
- default:
- return $value instanceof $type;
- }
+ return match ($type) {
+ 'array' => is_array($value),
+ 'bool', 'boolean' => is_bool($value),
+ 'callable' => is_callable($value),
+ 'float', 'double' => is_float($value),
+ 'int', 'integer' => is_int($value),
+ 'null' => $value === null,
+ 'numeric' => is_numeric($value),
+ 'object' => is_object($value),
+ 'resource' => is_resource($value),
+ 'scalar' => is_scalar($value),
+ 'string' => is_string($value),
+ 'mixed' => true,
+ default => $value instanceof $type,
+ };
}
}
diff --git a/vendor/ramsey/collection/src/Tool/ValueExtractorTrait.php b/vendor/ramsey/collection/src/Tool/ValueExtractorTrait.php
index f9be1be..bbe27b4 100644
--- a/vendor/ramsey/collection/src/Tool/ValueExtractorTrait.php
+++ b/vendor/ramsey/collection/src/Tool/ValueExtractorTrait.php
@@ -14,9 +14,12 @@ declare(strict_types=1);
namespace Ramsey\Collection\Tool;
-use Ramsey\Collection\Exception\ValueExtractionException;
+use Ramsey\Collection\Exception\InvalidPropertyOrMethod;
+use Ramsey\Collection\Exception\UnsupportedOperationException;
+use ReflectionProperty;
-use function get_class;
+use function is_array;
+use function is_object;
use function method_exists;
use function property_exists;
use function sprintf;
@@ -27,32 +30,71 @@ use function sprintf;
trait ValueExtractorTrait
{
/**
- * Extracts the value of the given property or method from the object.
+ * Returns the type associated with this collection.
+ */
+ abstract public function getType(): string;
+
+ /**
+ * Extracts the value of the given property, method, or array key from the
+ * element.
*
- * @param mixed $object The object to extract the value from.
- * @param string $propertyOrMethod The property or method for which the
+ * If `$propertyOrMethod` is `null`, we return the element as-is.
+ *
+ * @param mixed $element The element to extract the value from.
+ * @param string | null $propertyOrMethod The property or method for which the
* value should be extracted.
*
- * @return mixed the value extracted from the specified property or method.
+ * @return mixed the value extracted from the specified property, method,
+ * or array key, or the element itself.
*
- * @throws ValueExtractionException if the method or property is not defined.
+ * @throws InvalidPropertyOrMethod
+ * @throws UnsupportedOperationException
*/
- protected function extractValue($object, string $propertyOrMethod)
+ protected function extractValue(mixed $element, ?string $propertyOrMethod): mixed
{
- if (!is_object($object)) {
- throw new ValueExtractionException('Unable to extract a value from a non-object');
+ if ($propertyOrMethod === null) {
+ return $element;
}
- if (property_exists($object, $propertyOrMethod)) {
- return $object->$propertyOrMethod;
+ if (!is_object($element) && !is_array($element)) {
+ throw new UnsupportedOperationException(sprintf(
+ 'The collection type "%s" does not support the $propertyOrMethod parameter',
+ $this->getType(),
+ ));
}
- if (method_exists($object, $propertyOrMethod)) {
- return $object->{$propertyOrMethod}();
+ if (is_array($element)) {
+ return $element[$propertyOrMethod] ?? throw new InvalidPropertyOrMethod(sprintf(
+ 'Key or index "%s" not found in collection elements',
+ $propertyOrMethod,
+ ));
}
- throw new ValueExtractionException(
- sprintf('Method or property "%s" not defined in %s', $propertyOrMethod, get_class($object))
- );
+ if (property_exists($element, $propertyOrMethod) && method_exists($element, $propertyOrMethod)) {
+ $reflectionProperty = new ReflectionProperty($element, $propertyOrMethod);
+ if ($reflectionProperty->isPublic()) {
+ return $element->$propertyOrMethod;
+ }
+
+ return $element->{$propertyOrMethod}();
+ }
+
+ if (property_exists($element, $propertyOrMethod)) {
+ return $element->$propertyOrMethod;
+ }
+
+ if (method_exists($element, $propertyOrMethod)) {
+ return $element->{$propertyOrMethod}();
+ }
+
+ if (isset($element->$propertyOrMethod)) {
+ return $element->$propertyOrMethod;
+ }
+
+ throw new InvalidPropertyOrMethod(sprintf(
+ 'Method or property "%s" not defined in %s',
+ $propertyOrMethod,
+ $element::class,
+ ));
}
}
diff --git a/vendor/ramsey/collection/src/Tool/ValueToStringTrait.php b/vendor/ramsey/collection/src/Tool/ValueToStringTrait.php
index 721ade0..40c7803 100644
--- a/vendor/ramsey/collection/src/Tool/ValueToStringTrait.php
+++ b/vendor/ramsey/collection/src/Tool/ValueToStringTrait.php
@@ -16,11 +16,12 @@ namespace Ramsey\Collection\Tool;
use DateTimeInterface;
-use function get_class;
+use function assert;
use function get_resource_type;
use function is_array;
use function is_bool;
use function is_callable;
+use function is_object;
use function is_resource;
use function is_scalar;
@@ -44,7 +45,7 @@ trait ValueToStringTrait
*
* @param mixed $value the value to return as a string.
*/
- protected function toolValueToString($value): string
+ protected function toolValueToString(mixed $value): string
{
// null
if ($value === null) {
@@ -71,16 +72,13 @@ trait ValueToStringTrait
return '(' . get_resource_type($value) . ' resource #' . (int) $value . ')';
}
- // If we don't know what it is, use var_export().
- if (!is_object($value)) {
- return '(' . var_export($value, true) . ')';
- }
-
// From here, $value should be an object.
+ assert(is_object($value));
// __toString() is implemented
if (is_callable([$value, '__toString'])) {
- return (string) $value->__toString();
+ /** @var string */
+ return $value->__toString();
}
// object of type \DateTime
@@ -89,6 +87,6 @@ trait ValueToStringTrait
}
// unknown type
- return '(' . get_class($value) . ' Object)';
+ return '(' . $value::class . ' Object)';
}
}
diff --git a/vendor/ramsey/uuid/LICENSE b/vendor/ramsey/uuid/LICENSE
index 5e06cf4..22b4d0d 100644
--- a/vendor/ramsey/uuid/LICENSE
+++ b/vendor/ramsey/uuid/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2012-2021 Ben Ramsey
+Copyright (c) 2012-2025 Ben Ramsey
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/vendor/ramsey/uuid/composer.json b/vendor/ramsey/uuid/composer.json
index 3f3b5ac..b34d9b1 100644
--- a/vendor/ramsey/uuid/composer.json
+++ b/vendor/ramsey/uuid/composer.json
@@ -1,65 +1,49 @@
{
"name": "ramsey/uuid",
- "type": "library",
"description": "A PHP library for generating and working with universally unique identifiers (UUIDs).",
+ "license": "MIT",
+ "type": "library",
"keywords": [
"uuid",
"identifier",
"guid"
],
- "license": "MIT",
"require": {
- "php": "^7.2 || ^8.0",
- "ext-json": "*",
- "brick/math": "^0.8 || ^0.9",
- "ramsey/collection": "^1.0",
- "symfony/polyfill-ctype": "^1.8",
- "symfony/polyfill-php80": "^1.14"
+ "php": "^8.0",
+ "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13 || ^0.14",
+ "ramsey/collection": "^1.2 || ^2.0"
+ },
+ "require-dev": {
+ "captainhook/captainhook": "^5.25",
+ "captainhook/plugin-composer": "^5.3",
+ "dealerdirect/phpcodesniffer-composer-installer": "^1.0",
+ "ergebnis/composer-normalize": "^2.47",
+ "mockery/mockery": "^1.6",
+ "paragonie/random-lib": "^2",
+ "php-mock/php-mock": "^2.6",
+ "php-mock/php-mock-mockery": "^1.5",
+ "php-parallel-lint/php-parallel-lint": "^1.4.0",
+ "phpbench/phpbench": "^1.2.14",
+ "phpstan/extension-installer": "^1.4",
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-mockery": "^2.0",
+ "phpstan/phpstan-phpunit": "^2.0",
+ "phpunit/phpunit": "^9.6",
+ "slevomat/coding-standard": "^8.18",
+ "squizlabs/php_codesniffer": "^3.13"
},
"replace": {
"rhumsaa/uuid": "self.version"
},
- "require-dev": {
- "captainhook/captainhook": "^5.10",
- "captainhook/plugin-composer": "^5.3",
- "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
- "doctrine/annotations": "^1.8",
- "ergebnis/composer-normalize": "^2.15",
- "mockery/mockery": "^1.3",
- "moontoast/math": "^1.1",
- "paragonie/random-lib": "^2",
- "php-mock/php-mock": "^2.2",
- "php-mock/php-mock-mockery": "^1.3",
- "php-parallel-lint/php-parallel-lint": "^1.1",
- "phpbench/phpbench": "^1.0",
- "phpstan/extension-installer": "^1.0",
- "phpstan/phpstan": "^0.12",
- "phpstan/phpstan-mockery": "^0.12",
- "phpstan/phpstan-phpunit": "^0.12",
- "phpunit/phpunit": "^8.5 || ^9",
- "slevomat/coding-standard": "^7.0",
- "squizlabs/php_codesniffer": "^3.5",
- "vimeo/psalm": "^4.9"
- },
"suggest": {
"ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.",
- "ext-ctype": "Enables faster processing of character classification using ctype functions.",
"ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.",
"ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.",
"paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter",
"ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type."
},
- "config": {
- "sort-packages": true
- },
- "extra": {
- "branch-alias": {
- "dev-main": "4.x-dev"
- },
- "captainhook": {
- "force-install": true
- }
- },
+ "minimum-stability": "dev",
+ "prefer-stable": true,
"autoload": {
"psr-4": {
"Ramsey\\Uuid\\": "src/"
@@ -75,33 +59,56 @@
"Ramsey\\Uuid\\Test\\": "tests/"
}
},
- "minimum-stability": "dev",
- "prefer-stable": true,
+ "config": {
+ "allow-plugins": {
+ "captainhook/plugin-composer": true,
+ "dealerdirect/phpcodesniffer-composer-installer": true,
+ "ergebnis/composer-normalize": true,
+ "phpstan/extension-installer": true
+ },
+ "sort-packages": true
+ },
+ "extra": {
+ "captainhook": {
+ "force-install": true
+ }
+ },
"scripts": {
- "analyze": [
- "@phpstan",
- "@psalm"
+ "dev:analyze": "@dev:analyze:phpstan",
+ "dev:analyze:phpstan": "phpstan analyse --ansi --memory-limit 1G",
+ "dev:bench": "@php -d 'error_reporting=24575' vendor/bin/phpbench run",
+ "dev:build:clean": "git clean -fX build/",
+ "dev:lint": [
+ "@dev:lint:syntax",
+ "@dev:lint:style"
],
- "build:clean": "git clean -fX build/",
- "lint": "parallel-lint src tests",
- "lint:paths": "parallel-lint",
- "phpbench": "phpbench run",
- "phpcbf": "phpcbf -vpw --cache=build/cache/phpcs.cache",
- "phpcs": "phpcs --cache=build/cache/phpcs.cache",
- "phpstan": [
- "phpstan analyse --no-progress",
- "phpstan analyse -c phpstan-tests.neon --no-progress"
+ "dev:lint:fix": "phpcbf --cache=build/cache/phpcs.cache",
+ "dev:lint:style": "phpcs --cache=build/cache/phpcs.cache --colors",
+ "dev:lint:syntax": "parallel-lint --colors src/ tests/",
+ "dev:test": [
+ "@dev:lint",
+ "@dev:bench",
+ "@dev:analyze",
+ "@dev:test:unit"
],
- "phpunit": "phpunit --verbose --colors=always",
- "phpunit-coverage": "phpunit --verbose --colors=always --coverage-html build/coverage",
- "psalm": "psalm --show-info=false --config=psalm.xml",
- "test": [
- "@lint",
- "@phpbench",
- "@phpcs",
- "@phpstan",
- "@psalm",
- "@phpunit"
- ]
+ "dev:test:coverage:ci": "@php -d 'xdebug.mode=coverage' vendor/bin/phpunit --colors=always --coverage-text --coverage-clover build/coverage/clover.xml --coverage-cobertura build/coverage/cobertura.xml --coverage-crap4j build/coverage/crap4j.xml --coverage-xml build/coverage/coverage-xml --log-junit build/junit.xml",
+ "dev:test:coverage:html": "@php -d 'xdebug.mode=coverage' vendor/bin/phpunit --colors=always --coverage-html build/coverage/coverage-html/",
+ "dev:test:unit": "phpunit --colors=always",
+ "test": "@dev:test"
+ },
+ "scripts-descriptions": {
+ "dev:analyze": "Runs all static analysis checks.",
+ "dev:analyze:phpstan": "Runs the PHPStan static analyzer.",
+ "dev:bench": "Runs PHPBench benchmark tests.",
+ "dev:build:clean": "Cleans the build/ directory.",
+ "dev:lint": "Runs all linting checks.",
+ "dev:lint:fix": "Auto-fixes coding standards issues, if possible.",
+ "dev:lint:style": "Checks for coding standards issues.",
+ "dev:lint:syntax": "Checks for syntax errors.",
+ "dev:test": "Runs linting, static analysis, and unit tests.",
+ "dev:test:coverage:ci": "Runs unit tests and generates CI coverage reports.",
+ "dev:test:coverage:html": "Runs unit tests and generates HTML coverage report.",
+ "dev:test:unit": "Runs unit tests.",
+ "test": "Runs linting, static analysis, and unit tests."
}
}
diff --git a/vendor/ramsey/uuid/src/BinaryUtils.php b/vendor/ramsey/uuid/src/BinaryUtils.php
index fb8ba9a..d8aac2e 100644
--- a/vendor/ramsey/uuid/src/BinaryUtils.php
+++ b/vendor/ramsey/uuid/src/BinaryUtils.php
@@ -20,44 +20,35 @@ namespace Ramsey\Uuid;
class BinaryUtils
{
/**
- * Applies the RFC 4122 variant field to the 16-bit clock sequence
+ * Applies the variant field to the 16-bit clock sequence
*
- * @link http://tools.ietf.org/html/rfc4122#section-4.1.1 RFC 4122, § 4.1.1: Variant
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.1 RFC 9562, 4.1. Variant Field
*
- * @param int $clockSeq The 16-bit clock sequence value before the RFC 4122
- * variant is applied
+ * @param int $clockSeq The 16-bit clock sequence value before the variant is applied
*
* @return int The 16-bit clock sequence multiplexed with the UUID variant
*
- * @psalm-pure
+ * @pure
*/
public static function applyVariant(int $clockSeq): int
{
- $clockSeq = $clockSeq & 0x3fff;
- $clockSeq |= 0x8000;
-
- return $clockSeq;
+ return ($clockSeq & 0x3fff) | 0x8000;
}
/**
- * Applies the RFC 4122 version number to the 16-bit `time_hi_and_version` field
+ * Applies the version field to the 16-bit `time_hi_and_version` field
*
- * @link http://tools.ietf.org/html/rfc4122#section-4.1.3 RFC 4122, § 4.1.3: Version
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-4.2 RFC 9562, 4.2. Version Field
*
- * @param int $timeHi The value of the 16-bit `time_hi_and_version` field
- * before the RFC 4122 version is applied
- * @param int $version The RFC 4122 version to apply to the `time_hi` field
+ * @param int $timeHi The value of the 16-bit `time_hi_and_version` field before the version is applied
+ * @param int $version The version to apply to the `time_hi` field
*
- * @return int The 16-bit time_hi field of the timestamp multiplexed with
- * the UUID version number
+ * @return int The 16-bit time_hi field of the timestamp multiplexed with the UUID version number
*
- * @psalm-pure
+ * @pure
*/
public static function applyVersion(int $timeHi, int $version): int
{
- $timeHi = $timeHi & 0x0fff;
- $timeHi |= $version << 12;
-
- return $timeHi;
+ return ($timeHi & 0x0fff) | ($version << 12);
}
}
diff --git a/vendor/ramsey/uuid/src/Builder/BuilderCollection.php b/vendor/ramsey/uuid/src/Builder/BuilderCollection.php
index 89fa1e3..2b2e0a2 100644
--- a/vendor/ramsey/uuid/src/Builder/BuilderCollection.php
+++ b/vendor/ramsey/uuid/src/Builder/BuilderCollection.php
@@ -27,6 +27,11 @@ use Traversable;
/**
* A collection of UuidBuilderInterface objects
*
+ * @deprecated this class has been deprecated and will be removed in 5.0.0. The use-case for this class comes from a
+ * pre-`phpstan/phpstan` and pre-`vimeo/psalm` ecosystem, in which type safety had to be mostly enforced at runtime:
+ * that is no longer necessary, now that you can safely verify your code to be correct, and use more generic types
+ * like `iterable` instead.
+ *
* @extends AbstractCollection
*/
class BuilderCollection extends AbstractCollection
@@ -36,11 +41,6 @@ class BuilderCollection extends AbstractCollection
return UuidBuilderInterface::class;
}
- /**
- * @psalm-mutation-free
- * @psalm-suppress ImpureMethodCall
- * @psalm-suppress InvalidTemplateParam
- */
public function getIterator(): Traversable
{
return parent::getIterator();
@@ -49,11 +49,7 @@ class BuilderCollection extends AbstractCollection
/**
* Re-constructs the object from its serialized form
*
- * @param string $serialized The serialized PHP string to unserialize into
- * a UuidInterface instance
- *
- * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- * @psalm-suppress RedundantConditionGivenDocblockType
+ * @param string $serialized The serialized PHP string to unserialize into a UuidInterface instance
*/
public function unserialize($serialized): void
{
@@ -73,8 +69,9 @@ class BuilderCollection extends AbstractCollection
$this->data = array_filter(
$data,
function ($unserialized): bool {
+ /** @phpstan-ignore instanceof.alwaysTrue */
return $unserialized instanceof UuidBuilderInterface;
- }
+ },
);
}
}
diff --git a/vendor/ramsey/uuid/src/Builder/DefaultUuidBuilder.php b/vendor/ramsey/uuid/src/Builder/DefaultUuidBuilder.php
index 7c4a6f8..3d62159 100644
--- a/vendor/ramsey/uuid/src/Builder/DefaultUuidBuilder.php
+++ b/vendor/ramsey/uuid/src/Builder/DefaultUuidBuilder.php
@@ -17,9 +17,9 @@ namespace Ramsey\Uuid\Builder;
use Ramsey\Uuid\Rfc4122\UuidBuilder as Rfc4122UuidBuilder;
/**
- * @deprecated Transition to {@see Rfc4122UuidBuilder}.
+ * @deprecated Please transition to {@see Rfc4122UuidBuilder}.
*
- * @psalm-immutable
+ * @immutable
*/
class DefaultUuidBuilder extends Rfc4122UuidBuilder
{
diff --git a/vendor/ramsey/uuid/src/Builder/DegradedUuidBuilder.php b/vendor/ramsey/uuid/src/Builder/DegradedUuidBuilder.php
index 23931e4..1554a97 100644
--- a/vendor/ramsey/uuid/src/Builder/DegradedUuidBuilder.php
+++ b/vendor/ramsey/uuid/src/Builder/DegradedUuidBuilder.php
@@ -23,34 +23,23 @@ use Ramsey\Uuid\Rfc4122\Fields as Rfc4122Fields;
use Ramsey\Uuid\UuidInterface;
/**
- * @deprecated DegradedUuid instances are no longer necessary to support 32-bit
- * systems. Transition to {@see DefaultUuidBuilder}.
+ * @deprecated DegradedUuid instances are no longer necessary to support 32-bit systems. Please transition to {@see DefaultUuidBuilder}.
*
- * @psalm-immutable
+ * @immutable
*/
class DegradedUuidBuilder implements UuidBuilderInterface
{
- /**
- * @var NumberConverterInterface
- */
- private $numberConverter;
+ private TimeConverterInterface $timeConverter;
/**
- * @var TimeConverterInterface
- */
- private $timeConverter;
-
- /**
- * @param NumberConverterInterface $numberConverter The number converter to
- * use when constructing the DegradedUuid
- * @param TimeConverterInterface|null $timeConverter The time converter to use
- * for converting timestamps extracted from a UUID to Unix timestamps
+ * @param NumberConverterInterface $numberConverter The number converter to use when constructing the DegradedUuid
+ * @param TimeConverterInterface|null $timeConverter The time converter to use for converting timestamps extracted
+ * from a UUID to Unix timestamps
*/
public function __construct(
- NumberConverterInterface $numberConverter,
+ private NumberConverterInterface $numberConverter,
?TimeConverterInterface $timeConverter = null
) {
- $this->numberConverter = $numberConverter;
$this->timeConverter = $timeConverter ?: new DegradedTimeConverter();
}
@@ -62,15 +51,10 @@ class DegradedUuidBuilder implements UuidBuilderInterface
*
* @return DegradedUuid The DegradedUuidBuild returns an instance of Ramsey\Uuid\DegradedUuid
*
- * @psalm-pure
+ * @phpstan-impure
*/
public function build(CodecInterface $codec, string $bytes): UuidInterface
{
- return new DegradedUuid(
- new Rfc4122Fields($bytes),
- $this->numberConverter,
- $codec,
- $this->timeConverter
- );
+ return new DegradedUuid(new Rfc4122Fields($bytes), $this->numberConverter, $codec, $this->timeConverter);
}
}
diff --git a/vendor/ramsey/uuid/src/Builder/FallbackBuilder.php b/vendor/ramsey/uuid/src/Builder/FallbackBuilder.php
index 470d2f7..e40f778 100644
--- a/vendor/ramsey/uuid/src/Builder/FallbackBuilder.php
+++ b/vendor/ramsey/uuid/src/Builder/FallbackBuilder.php
@@ -20,36 +20,28 @@ use Ramsey\Uuid\Exception\UnableToBuildUuidException;
use Ramsey\Uuid\UuidInterface;
/**
- * FallbackBuilder builds a UUID by stepping through a list of UUID builders
- * until a UUID can be constructed without exceptions
+ * FallbackBuilder builds a UUID by stepping through a list of UUID builders until a UUID can be constructed without exceptions
*
- * @psalm-immutable
+ * @immutable
*/
class FallbackBuilder implements UuidBuilderInterface
{
/**
- * @var BuilderCollection
+ * @param iterable $builders An array of UUID builders
*/
- private $builders;
-
- /**
- * @param BuilderCollection $builders An array of UUID builders
- */
- public function __construct(BuilderCollection $builders)
+ public function __construct(private iterable $builders)
{
- $this->builders = $builders;
}
/**
- * Builds and returns a UuidInterface instance using the first builder that
- * succeeds
+ * Builds and returns a UuidInterface instance using the first builder that succeeds
*
* @param CodecInterface $codec The codec to use for building this instance
* @param string $bytes The byte string from which to construct a UUID
*
* @return UuidInterface an instance of a UUID object
*
- * @psalm-pure
+ * @pure
*/
public function build(CodecInterface $codec, string $bytes): UuidInterface
{
@@ -68,7 +60,7 @@ class FallbackBuilder implements UuidBuilderInterface
throw new BuilderNotFoundException(
'Could not find a suitable builder for the provided codec and fields',
0,
- $lastBuilderException
+ $lastBuilderException,
);
}
}
diff --git a/vendor/ramsey/uuid/src/Builder/UuidBuilderInterface.php b/vendor/ramsey/uuid/src/Builder/UuidBuilderInterface.php
index 8e58b2b..c409878 100644
--- a/vendor/ramsey/uuid/src/Builder/UuidBuilderInterface.php
+++ b/vendor/ramsey/uuid/src/Builder/UuidBuilderInterface.php
@@ -20,7 +20,7 @@ use Ramsey\Uuid\UuidInterface;
/**
* A UUID builder builds instances of UuidInterface
*
- * @psalm-immutable
+ * @immutable
*/
interface UuidBuilderInterface
{
@@ -30,10 +30,9 @@ interface UuidBuilderInterface
* @param CodecInterface $codec The codec to use for building this UuidInterface instance
* @param string $bytes The byte string from which to construct a UUID
*
- * @return UuidInterface Implementations may choose to return more specific
- * instances of UUIDs that implement UuidInterface
+ * @return UuidInterface Implementations may choose to return more specific instances of UUIDs that implement UuidInterface
*
- * @psalm-pure
+ * @pure
*/
public function build(CodecInterface $codec, string $bytes): UuidInterface;
}
diff --git a/vendor/ramsey/uuid/src/Codec/CodecInterface.php b/vendor/ramsey/uuid/src/Codec/CodecInterface.php
index 85f8a7e..b1e554e 100644
--- a/vendor/ramsey/uuid/src/Codec/CodecInterface.php
+++ b/vendor/ramsey/uuid/src/Codec/CodecInterface.php
@@ -19,53 +19,51 @@ use Ramsey\Uuid\UuidInterface;
/**
* A codec encodes and decodes a UUID according to defined rules
*
- * @psalm-immutable
+ * @immutable
*/
interface CodecInterface
{
/**
* Returns a hexadecimal string representation of a UuidInterface
*
- * @param UuidInterface $uuid The UUID for which to create a hexadecimal
- * string representation
+ * @param UuidInterface $uuid The UUID for which to create a hexadecimal string representation
*
- * @return string Hexadecimal string representation of a UUID
+ * @return non-empty-string Hexadecimal string representation of a UUID
*
- * @psalm-return non-empty-string
+ * @pure
*/
public function encode(UuidInterface $uuid): string;
/**
* Returns a binary string representation of a UuidInterface
*
- * @param UuidInterface $uuid The UUID for which to create a binary string
- * representation
+ * @param UuidInterface $uuid The UUID for which to create a binary string representation
*
- * @return string Binary string representation of a UUID
+ * @return non-empty-string Binary string representation of a UUID
*
- * @psalm-return non-empty-string
+ * @pure
*/
public function encodeBinary(UuidInterface $uuid): string;
/**
* Returns a UuidInterface derived from a hexadecimal string representation
*
- * @param string $encodedUuid The hexadecimal string representation to
- * convert into a UuidInterface instance
+ * @param string $encodedUuid The hexadecimal string representation to convert into a UuidInterface instance
*
- * @return UuidInterface An instance of a UUID decoded from a hexadecimal
- * string representation
+ * @return UuidInterface An instance of a UUID decoded from a hexadecimal string representation
+ *
+ * @pure
*/
public function decode(string $encodedUuid): UuidInterface;
/**
* Returns a UuidInterface derived from a binary string representation
*
- * @param string $bytes The binary string representation to convert into a
- * UuidInterface instance
+ * @param string $bytes The binary string representation to convert into a UuidInterface instance
*
- * @return UuidInterface An instance of a UUID decoded from a binary string
- * representation
+ * @return UuidInterface An instance of a UUID decoded from a binary string representation
+ *
+ * @pure
*/
public function decodeBytes(string $bytes): UuidInterface;
}
diff --git a/vendor/ramsey/uuid/src/Codec/GuidStringCodec.php b/vendor/ramsey/uuid/src/Codec/GuidStringCodec.php
index f11e9d5..a1bd58a 100644
--- a/vendor/ramsey/uuid/src/Codec/GuidStringCodec.php
+++ b/vendor/ramsey/uuid/src/Codec/GuidStringCodec.php
@@ -18,6 +18,7 @@ use Ramsey\Uuid\Guid\Guid;
use Ramsey\Uuid\UuidInterface;
use function bin2hex;
+use function sprintf;
use function substr;
/**
@@ -25,20 +26,43 @@ use function substr;
*
* @see Guid
*
- * @psalm-immutable
+ * @immutable
*/
class GuidStringCodec extends StringCodec
{
+ public function encode(UuidInterface $uuid): string
+ {
+ /** @phpstan-ignore possiblyImpure.methodCall */
+ $hex = bin2hex($uuid->getFields()->getBytes());
+
+ /** @var non-empty-string */
+ return sprintf(
+ '%02s%02s%02s%02s-%02s%02s-%02s%02s-%04s-%012s',
+ substr($hex, 6, 2),
+ substr($hex, 4, 2),
+ substr($hex, 2, 2),
+ substr($hex, 0, 2),
+ substr($hex, 10, 2),
+ substr($hex, 8, 2),
+ substr($hex, 14, 2),
+ substr($hex, 12, 2),
+ substr($hex, 16, 4),
+ substr($hex, 20),
+ );
+ }
+
public function decode(string $encodedUuid): UuidInterface
{
+ /** @phpstan-ignore possiblyImpure.methodCall */
$bytes = $this->getBytes($encodedUuid);
+ /** @phpstan-ignore possiblyImpure.methodCall, possiblyImpure.methodCall */
return $this->getBuilder()->build($this, $this->swapBytes($bytes));
}
public function decodeBytes(string $bytes): UuidInterface
{
- // Specifically call parent::decode to preserve correct byte order
+ // Call parent::decode() to preserve the correct byte order.
return parent::decode(bin2hex($bytes));
}
@@ -48,8 +72,7 @@ class GuidStringCodec extends StringCodec
private function swapBytes(string $bytes): string
{
return $bytes[3] . $bytes[2] . $bytes[1] . $bytes[0]
- . $bytes[5] . $bytes[4]
- . $bytes[7] . $bytes[6]
+ . $bytes[5] . $bytes[4] . $bytes[7] . $bytes[6]
. substr($bytes, 8);
}
}
diff --git a/vendor/ramsey/uuid/src/Codec/OrderedTimeCodec.php b/vendor/ramsey/uuid/src/Codec/OrderedTimeCodec.php
index 0798ebc..ea533d9 100644
--- a/vendor/ramsey/uuid/src/Codec/OrderedTimeCodec.php
+++ b/vendor/ramsey/uuid/src/Codec/OrderedTimeCodec.php
@@ -24,59 +24,51 @@ use function strlen;
use function substr;
/**
- * OrderedTimeCodec encodes and decodes a UUID, optimizing the byte order for
- * more efficient storage
+ * OrderedTimeCodec encodes and decodes a UUID, optimizing the byte order for more efficient storage
*
- * For binary representations of version 1 UUID, this codec may be used to
- * reorganize the time fields, making the UUID closer to sequential when storing
- * the bytes. According to Percona, this optimization can improve database
- * INSERTs and SELECTs using the UUID column as a key.
+ * For binary representations of version 1 UUID, this codec may be used to reorganize the time fields, making the UUID
+ * closer to sequential when storing the bytes. According to Percona, this optimization can improve database INSERT and
+ * SELECT statements using the UUID column as a key.
*
- * The string representation of the UUID will remain unchanged. Only the binary
- * representation is reordered.
+ * The string representation of the UUID will remain unchanged. Only the binary representation is reordered.
*
- * **PLEASE NOTE:** Binary representations of UUIDs encoded with this codec must
- * be decoded with this codec. Decoding using another codec can result in
- * malformed UUIDs.
+ * PLEASE NOTE: Binary representations of UUIDs encoded with this codec must be decoded with this codec. Decoding using
+ * another codec can result in malformed UUIDs.
+ *
+ * @deprecated Please migrate to {@link https://uuid.ramsey.dev/en/stable/rfc4122/version6.html Version 6, reordered time-based UUIDs}.
*
* @link https://www.percona.com/blog/2014/12/19/store-uuid-optimized-way/ Storing UUID Values in MySQL
*
- * @psalm-immutable
+ * @immutable
*/
class OrderedTimeCodec extends StringCodec
{
/**
- * Returns a binary string representation of a UUID, with the timestamp
- * fields rearranged for optimized storage
+ * Returns a binary string representation of a UUID, with the timestamp fields rearranged for optimized storage
*
- * @inheritDoc
- * @psalm-return non-empty-string
- * @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty
- * @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty
+ * @return non-empty-string
*/
public function encodeBinary(UuidInterface $uuid): string
{
if (
+ /** @phpstan-ignore possiblyImpure.methodCall */
!($uuid->getFields() instanceof Rfc4122FieldsInterface)
+ /** @phpstan-ignore possiblyImpure.methodCall */
|| $uuid->getFields()->getVersion() !== Uuid::UUID_TYPE_TIME
) {
- throw new InvalidArgumentException(
- 'Expected RFC 4122 version 1 (time-based) UUID'
- );
+ throw new InvalidArgumentException('Expected version 1 (time-based) UUID');
}
+ /** @phpstan-ignore possiblyImpure.methodCall */
$bytes = $uuid->getFields()->getBytes();
- /** @phpstan-ignore-next-line PHPStan complains that this is not a non-empty-string. */
- return $bytes[6] . $bytes[7]
- . $bytes[4] . $bytes[5]
+ return $bytes[6] . $bytes[7] . $bytes[4] . $bytes[5]
. $bytes[0] . $bytes[1] . $bytes[2] . $bytes[3]
. substr($bytes, 8);
}
/**
- * Returns a UuidInterface derived from an ordered-time binary string
- * representation
+ * Returns a UuidInterface derived from an ordered-time binary string representation
*
* @throws InvalidArgumentException if $bytes is an invalid length
*
@@ -85,26 +77,22 @@ class OrderedTimeCodec extends StringCodec
public function decodeBytes(string $bytes): UuidInterface
{
if (strlen($bytes) !== 16) {
- throw new InvalidArgumentException(
- '$bytes string should contain 16 characters.'
- );
+ throw new InvalidArgumentException('$bytes string should contain 16 characters.');
}
// Rearrange the bytes to their original order.
$rearrangedBytes = $bytes[4] . $bytes[5] . $bytes[6] . $bytes[7]
- . $bytes[2] . $bytes[3]
- . $bytes[0] . $bytes[1]
+ . $bytes[2] . $bytes[3] . $bytes[0] . $bytes[1]
. substr($bytes, 8);
$uuid = parent::decodeBytes($rearrangedBytes);
- if (
- !($uuid->getFields() instanceof Rfc4122FieldsInterface)
- || $uuid->getFields()->getVersion() !== Uuid::UUID_TYPE_TIME
- ) {
+ /** @phpstan-ignore possiblyImpure.methodCall */
+ $fields = $uuid->getFields();
+
+ if (!$fields instanceof Rfc4122FieldsInterface || $fields->getVersion() !== Uuid::UUID_TYPE_TIME) {
throw new UnsupportedOperationException(
- 'Attempting to decode a non-time-based UUID using '
- . 'OrderedTimeCodec'
+ 'Attempting to decode a non-time-based UUID using OrderedTimeCodec',
);
}
diff --git a/vendor/ramsey/uuid/src/Codec/StringCodec.php b/vendor/ramsey/uuid/src/Codec/StringCodec.php
index 58c9f58..55f4f8b 100644
--- a/vendor/ramsey/uuid/src/Codec/StringCodec.php
+++ b/vendor/ramsey/uuid/src/Codec/StringCodec.php
@@ -17,61 +17,51 @@ namespace Ramsey\Uuid\Codec;
use Ramsey\Uuid\Builder\UuidBuilderInterface;
use Ramsey\Uuid\Exception\InvalidArgumentException;
use Ramsey\Uuid\Exception\InvalidUuidStringException;
-use Ramsey\Uuid\Rfc4122\FieldsInterface;
use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\UuidInterface;
+use function bin2hex;
use function hex2bin;
use function implode;
+use function sprintf;
use function str_replace;
use function strlen;
use function substr;
/**
- * StringCodec encodes and decodes RFC 4122 UUIDs
+ * StringCodec encodes and decodes RFC 9562 (formerly RFC 4122) UUIDs
*
- * @link http://tools.ietf.org/html/rfc4122
- *
- * @psalm-immutable
+ * @immutable
*/
class StringCodec implements CodecInterface
{
- /**
- * @var UuidBuilderInterface
- */
- private $builder;
-
/**
* Constructs a StringCodec
*
* @param UuidBuilderInterface $builder The builder to use when encoding UUIDs
*/
- public function __construct(UuidBuilderInterface $builder)
+ public function __construct(private UuidBuilderInterface $builder)
{
- $this->builder = $builder;
}
public function encode(UuidInterface $uuid): string
{
- /** @var FieldsInterface $fields */
- $fields = $uuid->getFields();
+ /** @phpstan-ignore possiblyImpure.methodCall */
+ $hex = bin2hex($uuid->getFields()->getBytes());
- return $fields->getTimeLow()->toString()
- . '-'
- . $fields->getTimeMid()->toString()
- . '-'
- . $fields->getTimeHiAndVersion()->toString()
- . '-'
- . $fields->getClockSeqHiAndReserved()->toString()
- . $fields->getClockSeqLow()->toString()
- . '-'
- . $fields->getNode()->toString();
+ /** @var non-empty-string */
+ return sprintf(
+ '%08s-%04s-%04s-%04s-%012s',
+ substr($hex, 0, 8),
+ substr($hex, 8, 4),
+ substr($hex, 12, 4),
+ substr($hex, 16, 4),
+ substr($hex, 20),
+ );
}
/**
- * @psalm-return non-empty-string
- * @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty
- * @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty
+ * @return non-empty-string
*/
public function encodeBinary(UuidInterface $uuid): string
{
@@ -86,15 +76,14 @@ class StringCodec implements CodecInterface
*/
public function decode(string $encodedUuid): UuidInterface
{
+ /** @phpstan-ignore possiblyImpure.methodCall */
return $this->builder->build($this, $this->getBytes($encodedUuid));
}
public function decodeBytes(string $bytes): UuidInterface
{
if (strlen($bytes) !== 16) {
- throw new InvalidArgumentException(
- '$bytes string should contain 16 characters.'
- );
+ throw new InvalidArgumentException('$bytes string should contain 16 characters.');
}
return $this->builder->build($this, $bytes);
@@ -113,11 +102,7 @@ class StringCodec implements CodecInterface
*/
protected function getBytes(string $encodedUuid): string
{
- $parsedUuid = str_replace(
- ['urn:', 'uuid:', 'URN:', 'UUID:', '{', '}', '-'],
- '',
- $encodedUuid
- );
+ $parsedUuid = str_replace(['urn:', 'uuid:', 'URN:', 'UUID:', '{', '}', '-'], '', $encodedUuid);
$components = [
substr($parsedUuid, 0, 8),
@@ -128,9 +113,7 @@ class StringCodec implements CodecInterface
];
if (!Uuid::isValid(implode('-', $components))) {
- throw new InvalidUuidStringException(
- 'Invalid UUID string: ' . $encodedUuid
- );
+ throw new InvalidUuidStringException('Invalid UUID string: ' . $encodedUuid);
}
return (string) hex2bin($parsedUuid);
diff --git a/vendor/ramsey/uuid/src/Codec/TimestampFirstCombCodec.php b/vendor/ramsey/uuid/src/Codec/TimestampFirstCombCodec.php
index 0e0042d..e7c8efd 100644
--- a/vendor/ramsey/uuid/src/Codec/TimestampFirstCombCodec.php
+++ b/vendor/ramsey/uuid/src/Codec/TimestampFirstCombCodec.php
@@ -23,40 +23,39 @@ use function substr;
use function substr_replace;
/**
- * TimestampFirstCombCodec encodes and decodes COMBs, with the timestamp as the
- * first 48 bits
+ * TimestampFirstCombCodec encodes and decodes COMBs, with the timestamp as the first 48 bits
*
- * In contrast with the TimestampLastCombCodec, the TimestampFirstCombCodec
- * adds the timestamp to the first 48 bits of the COMB. To generate a
- * timestamp-first COMB, set the TimestampFirstCombCodec as the codec, along
- * with the CombGenerator as the random generator.
+ * In contrast with the TimestampLastCombCodec, the TimestampFirstCombCodec adds the timestamp to the first 48 bits of
+ * the COMB. To generate a timestamp-first COMB, set the TimestampFirstCombCodec as the codec, along with the
+ * CombGenerator as the random generator.
*
- * ``` php
+ * ```
* $factory = new UuidFactory();
*
* $factory->setCodec(new TimestampFirstCombCodec($factory->getUuidBuilder()));
*
* $factory->setRandomGenerator(new CombGenerator(
* $factory->getRandomGenerator(),
- * $factory->getNumberConverter()
+ * $factory->getNumberConverter(),
* ));
*
* $timestampFirstComb = $factory->uuid4();
* ```
*
- * @link https://www.informit.com/articles/printerfriendly/25862 The Cost of GUIDs as Primary Keys
+ * @deprecated Please migrate to {@link https://uuid.ramsey.dev/en/stable/rfc4122/version7.html Version 7, Unix Epoch Time UUIDs}.
*
- * @psalm-immutable
+ * @link https://web.archive.org/web/20240118030355/https://www.informit.com/articles/printerfriendly/25862 The Cost of GUIDs as Primary Keys
+ *
+ * @immutable
*/
class TimestampFirstCombCodec extends StringCodec
{
/**
- * @psalm-return non-empty-string
- * @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty
- * @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty
+ * @return non-empty-string
*/
public function encode(UuidInterface $uuid): string
{
+ /** @phpstan-ignore possiblyImpure.methodCall */
$bytes = $this->swapBytes($uuid->getFields()->getBytes());
return sprintf(
@@ -70,9 +69,7 @@ class TimestampFirstCombCodec extends StringCodec
}
/**
- * @psalm-return non-empty-string
- * @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty
- * @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty
+ * @return non-empty-string
*/
public function encodeBinary(UuidInterface $uuid): string
{
@@ -87,27 +84,29 @@ class TimestampFirstCombCodec extends StringCodec
*/
public function decode(string $encodedUuid): UuidInterface
{
+ /** @phpstan-ignore possiblyImpure.methodCall */
$bytes = $this->getBytes($encodedUuid);
+ /** @phpstan-ignore possiblyImpure.methodCall */
return $this->getBuilder()->build($this, $this->swapBytes($bytes));
}
public function decodeBytes(string $bytes): UuidInterface
{
+ /** @phpstan-ignore possiblyImpure.methodCall */
return $this->getBuilder()->build($this, $this->swapBytes($bytes));
}
/**
* Swaps bytes according to the timestamp-first COMB rules
+ *
+ * @pure
*/
private function swapBytes(string $bytes): string
{
$first48Bits = substr($bytes, 0, 6);
$last48Bits = substr($bytes, -6);
- $bytes = substr_replace($bytes, $last48Bits, 0, 6);
- $bytes = substr_replace($bytes, $first48Bits, -6);
-
- return $bytes;
+ return substr_replace(substr_replace($bytes, $last48Bits, 0, 6), $first48Bits, -6);
}
}
diff --git a/vendor/ramsey/uuid/src/Codec/TimestampLastCombCodec.php b/vendor/ramsey/uuid/src/Codec/TimestampLastCombCodec.php
index 4856dea..14d10b6 100644
--- a/vendor/ramsey/uuid/src/Codec/TimestampLastCombCodec.php
+++ b/vendor/ramsey/uuid/src/Codec/TimestampLastCombCodec.php
@@ -15,36 +15,33 @@ declare(strict_types=1);
namespace Ramsey\Uuid\Codec;
/**
- * TimestampLastCombCodec encodes and decodes COMBs, with the timestamp as the
- * last 48 bits
+ * TimestampLastCombCodec encodes and decodes COMBs, with the timestamp as the last 48 bits
*
- * The CombGenerator when used with the StringCodec (and, by proxy, the
- * TimestampLastCombCodec) adds the timestamp to the last 48 bits of the COMB.
- * The TimestampLastCombCodec is provided for the sake of consistency. In
- * practice, it is identical to the standard StringCodec but, it may be used
- * with the CombGenerator for additional context when reading code.
+ * The CombGenerator when used with the StringCodec (and, by proxy, the TimestampLastCombCodec) adds the timestamp to
+ * the last 48 bits of the COMB. The TimestampLastCombCodec is provided for the sake of consistency. In practice, it is
+ * identical to the standard StringCodec, but it may be used with the CombGenerator for additional context when reading
+ * code.
*
- * Consider the following code. By default, the codec used by UuidFactory is the
- * StringCodec, but here, we explicitly set the TimestampLastCombCodec. It is
- * redundant, but it is clear that we intend this COMB to be generated with the
+ * Consider the following code. By default, the codec used by UuidFactory is the StringCodec, but here, we explicitly
+ * set the TimestampLastCombCodec. It is redundant, but it is clear that we intend this COMB to be generated with the
* timestamp appearing at the end.
*
- * ``` php
+ * ```
* $factory = new UuidFactory();
*
* $factory->setCodec(new TimestampLastCombCodec($factory->getUuidBuilder()));
*
* $factory->setRandomGenerator(new CombGenerator(
* $factory->getRandomGenerator(),
- * $factory->getNumberConverter()
+ * $factory->getNumberConverter(),
* ));
*
* $timestampLastComb = $factory->uuid4();
* ```
*
- * @link https://www.informit.com/articles/printerfriendly/25862 The Cost of GUIDs as Primary Keys
+ * @deprecated Please use {@see StringCodec} instead.
*
- * @psalm-immutable
+ * @immutable
*/
class TimestampLastCombCodec extends StringCodec
{
diff --git a/vendor/ramsey/uuid/src/Converter/Number/BigNumberConverter.php b/vendor/ramsey/uuid/src/Converter/Number/BigNumberConverter.php
index fef63fd..ff4e1cc 100644
--- a/vendor/ramsey/uuid/src/Converter/Number/BigNumberConverter.php
+++ b/vendor/ramsey/uuid/src/Converter/Number/BigNumberConverter.php
@@ -18,19 +18,16 @@ use Ramsey\Uuid\Converter\NumberConverterInterface;
use Ramsey\Uuid\Math\BrickMathCalculator;
/**
- * Previously used to integrate moontoast/math as a bignum arithmetic library,
- * BigNumberConverter is deprecated in favor of GenericNumberConverter
+ * Previously used to integrate moontoast/math as a bignum arithmetic library, BigNumberConverter is deprecated in favor
+ * of GenericNumberConverter
*
- * @deprecated Transition to {@see GenericNumberConverter}.
+ * @deprecated Please transition to {@see GenericNumberConverter}.
*
- * @psalm-immutable
+ * @immutable
*/
class BigNumberConverter implements NumberConverterInterface
{
- /**
- * @var NumberConverterInterface
- */
- private $converter;
+ private NumberConverterInterface $converter;
public function __construct()
{
@@ -38,8 +35,7 @@ class BigNumberConverter implements NumberConverterInterface
}
/**
- * @inheritDoc
- * @psalm-pure
+ * @pure
*/
public function fromHex(string $hex): string
{
@@ -47,8 +43,7 @@ class BigNumberConverter implements NumberConverterInterface
}
/**
- * @inheritDoc
- * @psalm-pure
+ * @pure
*/
public function toHex(string $number): string
{
diff --git a/vendor/ramsey/uuid/src/Converter/Number/DegradedNumberConverter.php b/vendor/ramsey/uuid/src/Converter/Number/DegradedNumberConverter.php
index c9cfa68..54e4e8c 100644
--- a/vendor/ramsey/uuid/src/Converter/Number/DegradedNumberConverter.php
+++ b/vendor/ramsey/uuid/src/Converter/Number/DegradedNumberConverter.php
@@ -15,10 +15,10 @@ declare(strict_types=1);
namespace Ramsey\Uuid\Converter\Number;
/**
- * @deprecated DegradedNumberConverter is no longer necessary for converting
- * numbers on 32-bit systems. Transition to {@see GenericNumberConverter}.
+ * @deprecated DegradedNumberConverter is no longer necessary for converting numbers on 32-bit systems. Please
+ * transition to {@see GenericNumberConverter}.
*
- * @psalm-immutable
+ * @immutable
*/
class DegradedNumberConverter extends BigNumberConverter
{
diff --git a/vendor/ramsey/uuid/src/Converter/Number/GenericNumberConverter.php b/vendor/ramsey/uuid/src/Converter/Number/GenericNumberConverter.php
index 501eac0..86968ab 100644
--- a/vendor/ramsey/uuid/src/Converter/Number/GenericNumberConverter.php
+++ b/vendor/ramsey/uuid/src/Converter/Number/GenericNumberConverter.php
@@ -19,29 +19,18 @@ use Ramsey\Uuid\Math\CalculatorInterface;
use Ramsey\Uuid\Type\Integer as IntegerObject;
/**
- * GenericNumberConverter uses the provided calculator to convert decimal
- * numbers to and from hexadecimal values
+ * GenericNumberConverter uses the provided calculator to convert decimal numbers to and from hexadecimal values
*
- * @psalm-immutable
+ * @immutable
*/
class GenericNumberConverter implements NumberConverterInterface
{
- /**
- * @var CalculatorInterface
- */
- private $calculator;
-
- public function __construct(CalculatorInterface $calculator)
+ public function __construct(private CalculatorInterface $calculator)
{
- $this->calculator = $calculator;
}
/**
- * @inheritDoc
- * @psalm-pure
- * @psalm-return numeric-string
- * @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty
- * @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty
+ * @pure
*/
public function fromHex(string $hex): string
{
@@ -49,15 +38,11 @@ class GenericNumberConverter implements NumberConverterInterface
}
/**
- * @inheritDoc
- * @psalm-pure
- * @psalm-return non-empty-string
- * @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty
- * @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty
+ * @pure
*/
public function toHex(string $number): string
{
- /** @phpstan-ignore-next-line PHPStan complains that this is not a non-empty-string. */
+ /** @phpstan-ignore return.type, possiblyImpure.new */
return $this->calculator->toBase(new IntegerObject($number), 16);
}
}
diff --git a/vendor/ramsey/uuid/src/Converter/NumberConverterInterface.php b/vendor/ramsey/uuid/src/Converter/NumberConverterInterface.php
index b33ec31..63eca6c 100644
--- a/vendor/ramsey/uuid/src/Converter/NumberConverterInterface.php
+++ b/vendor/ramsey/uuid/src/Converter/NumberConverterInterface.php
@@ -15,43 +15,35 @@ declare(strict_types=1);
namespace Ramsey\Uuid\Converter;
/**
- * A number converter converts UUIDs from hexadecimal characters into
- * representations of integers and vice versa
+ * A number converter converts UUIDs from hexadecimal characters into representations of integers and vice versa
*
- * @psalm-immutable
+ * @immutable
*/
interface NumberConverterInterface
{
/**
- * Converts a hexadecimal number into an string integer representation of
- * the number
+ * Converts a hexadecimal number into a string integer representation of the number
*
- * The integer representation returned is a string representation of the
- * integer, to accommodate unsigned integers greater than PHP_INT_MAX.
+ * The integer representation returned is a string representation of the integer to accommodate unsigned integers
+ * that are greater than `PHP_INT_MAX`.
*
* @param string $hex The hexadecimal string representation to convert
*
- * @return string String representation of an integer
+ * @return numeric-string String representation of an integer
*
- * @psalm-return numeric-string
- *
- * @psalm-pure
+ * @pure
*/
public function fromHex(string $hex): string;
/**
- * Converts a string integer representation into a hexadecimal string
- * representation of the number
+ * Converts a string integer representation into a hexadecimal string representation of the number
*
- * @param string $number A string integer representation to convert; this
- * must be a numeric string to accommodate unsigned integers greater
- * than PHP_INT_MAX.
+ * @param string $number A string integer representation to convert; this must be a numeric string to accommodate
+ * unsigned integers that are greater than `PHP_INT_MAX`.
*
- * @return string Hexadecimal string
+ * @return non-empty-string Hexadecimal string
*
- * @psalm-return non-empty-string
- *
- * @psalm-pure
+ * @pure
*/
public function toHex(string $number): string;
}
diff --git a/vendor/ramsey/uuid/src/Converter/Time/BigNumberTimeConverter.php b/vendor/ramsey/uuid/src/Converter/Time/BigNumberTimeConverter.php
index 7390dad..7112495 100644
--- a/vendor/ramsey/uuid/src/Converter/Time/BigNumberTimeConverter.php
+++ b/vendor/ramsey/uuid/src/Converter/Time/BigNumberTimeConverter.php
@@ -20,19 +20,16 @@ use Ramsey\Uuid\Type\Hexadecimal;
use Ramsey\Uuid\Type\Time;
/**
- * Previously used to integrate moontoast/math as a bignum arithmetic library,
- * BigNumberTimeConverter is deprecated in favor of GenericTimeConverter
+ * Previously used to integrate moontoast/math as a bignum arithmetic library, BigNumberTimeConverter is deprecated in
+ * favor of GenericTimeConverter
*
- * @deprecated Transition to {@see GenericTimeConverter}.
+ * @deprecated Please transition to {@see GenericTimeConverter}.
*
- * @psalm-immutable
+ * @immutable
*/
class BigNumberTimeConverter implements TimeConverterInterface
{
- /**
- * @var TimeConverterInterface
- */
- private $converter;
+ private TimeConverterInterface $converter;
public function __construct()
{
diff --git a/vendor/ramsey/uuid/src/Converter/Time/DegradedTimeConverter.php b/vendor/ramsey/uuid/src/Converter/Time/DegradedTimeConverter.php
index cdc2875..4720450 100644
--- a/vendor/ramsey/uuid/src/Converter/Time/DegradedTimeConverter.php
+++ b/vendor/ramsey/uuid/src/Converter/Time/DegradedTimeConverter.php
@@ -15,10 +15,10 @@ declare(strict_types=1);
namespace Ramsey\Uuid\Converter\Time;
/**
- * @deprecated DegradedTimeConverter is no longer necessary for converting
- * time on 32-bit systems. Transition to {@see GenericTimeConverter}.
+ * @deprecated DegradedTimeConverter is no longer necessary for converting time on 32-bit systems. Please transition to
+ * {@see GenericTimeConverter}.
*
- * @psalm-immutable
+ * @immutable
*/
class DegradedTimeConverter extends BigNumberTimeConverter
{
diff --git a/vendor/ramsey/uuid/src/Converter/Time/GenericTimeConverter.php b/vendor/ramsey/uuid/src/Converter/Time/GenericTimeConverter.php
index a8aa64b..1079e88 100644
--- a/vendor/ramsey/uuid/src/Converter/Time/GenericTimeConverter.php
+++ b/vendor/ramsey/uuid/src/Converter/Time/GenericTimeConverter.php
@@ -27,16 +27,14 @@ use function str_pad;
use const STR_PAD_LEFT;
/**
- * GenericTimeConverter uses the provided calculator to calculate and convert
- * time values
+ * GenericTimeConverter uses the provided calculator to calculate and convert time values
*
- * @psalm-immutable
+ * @immutable
*/
class GenericTimeConverter implements TimeConverterInterface
{
/**
- * The number of 100-nanosecond intervals from the Gregorian calendar epoch
- * to the Unix epoch.
+ * The number of 100-nanosecond intervals from the Gregorian calendar epoch to the Unix epoch.
*/
private const GREGORIAN_TO_UNIX_INTERVALS = '122192928000000000';
@@ -50,63 +48,52 @@ class GenericTimeConverter implements TimeConverterInterface
*/
private const MICROSECOND_INTERVALS = '10';
- /**
- * @var CalculatorInterface
- */
- private $calculator;
-
- public function __construct(CalculatorInterface $calculator)
+ public function __construct(private CalculatorInterface $calculator)
{
- $this->calculator = $calculator;
}
public function calculateTime(string $seconds, string $microseconds): Hexadecimal
{
+ /** @phpstan-ignore possiblyImpure.new */
$timestamp = new Time($seconds, $microseconds);
// Convert the seconds into a count of 100-nanosecond intervals.
$sec = $this->calculator->multiply(
$timestamp->getSeconds(),
- new IntegerObject(self::SECOND_INTERVALS)
+ new IntegerObject(self::SECOND_INTERVALS), /** @phpstan-ignore possiblyImpure.new */
);
// Convert the microseconds into a count of 100-nanosecond intervals.
$usec = $this->calculator->multiply(
$timestamp->getMicroseconds(),
- new IntegerObject(self::MICROSECOND_INTERVALS)
+ new IntegerObject(self::MICROSECOND_INTERVALS), /** @phpstan-ignore possiblyImpure.new */
);
- // Combine the seconds and microseconds intervals and add the count of
- // 100-nanosecond intervals from the Gregorian calendar epoch to the
- // Unix epoch. This gives us the correct count of 100-nanosecond
- // intervals since the Gregorian calendar epoch for the given seconds
- // and microseconds.
- /** @var IntegerObject $uuidTime */
- $uuidTime = $this->calculator->add(
- $sec,
- $usec,
- new IntegerObject(self::GREGORIAN_TO_UNIX_INTERVALS)
- );
+ /**
+ * Combine the intervals of seconds and microseconds and add the count of 100-nanosecond intervals from the
+ * Gregorian calendar epoch to the Unix epoch. This gives us the correct count of 100-nanosecond intervals since
+ * the Gregorian calendar epoch for the given seconds and microseconds.
+ *
+ * @var IntegerObject $uuidTime
+ * @phpstan-ignore possiblyImpure.new
+ */
+ $uuidTime = $this->calculator->add($sec, $usec, new IntegerObject(self::GREGORIAN_TO_UNIX_INTERVALS));
- $uuidTimeHex = str_pad(
- $this->calculator->toHexadecimal($uuidTime)->toString(),
- 16,
- '0',
- STR_PAD_LEFT
- );
-
- return new Hexadecimal($uuidTimeHex);
+ /**
+ * PHPStan considers CalculatorInterface::toHexadecimal, Hexadecimal:toString impure.
+ *
+ * @phpstan-ignore possiblyImpure.new
+ */
+ return new Hexadecimal(str_pad($this->calculator->toHexadecimal($uuidTime)->toString(), 16, '0', STR_PAD_LEFT));
}
public function convertTime(Hexadecimal $uuidTimestamp): Time
{
- // From the total, subtract the number of 100-nanosecond intervals from
- // the Gregorian calendar epoch to the Unix epoch. This gives us the
- // number of 100-nanosecond intervals from the Unix epoch, which also
- // includes the microtime.
+ // From the total, subtract the number of 100-nanosecond intervals from the Gregorian calendar epoch to the Unix
+ // epoch. This gives us the number of 100-nanosecond intervals from the Unix epoch, which also includes the microtime.
$epochNanoseconds = $this->calculator->subtract(
$this->calculator->toInteger($uuidTimestamp),
- new IntegerObject(self::GREGORIAN_TO_UNIX_INTERVALS)
+ new IntegerObject(self::GREGORIAN_TO_UNIX_INTERVALS), /** @phpstan-ignore possiblyImpure.new */
);
// Convert the 100-nanosecond intervals into seconds and microseconds.
@@ -114,11 +101,12 @@ class GenericTimeConverter implements TimeConverterInterface
RoundingMode::HALF_UP,
6,
$epochNanoseconds,
- new IntegerObject(self::SECOND_INTERVALS)
+ new IntegerObject(self::SECOND_INTERVALS), /** @phpstan-ignore possiblyImpure.new */
);
$split = explode('.', (string) $unixTimestamp, 2);
+ /** @phpstan-ignore possiblyImpure.new */
return new Time($split[0], $split[1] ?? 0);
}
}
diff --git a/vendor/ramsey/uuid/src/Converter/Time/PhpTimeConverter.php b/vendor/ramsey/uuid/src/Converter/Time/PhpTimeConverter.php
index 538d2f2..67dbf88 100644
--- a/vendor/ramsey/uuid/src/Converter/Time/PhpTimeConverter.php
+++ b/vendor/ramsey/uuid/src/Converter/Time/PhpTimeConverter.php
@@ -34,48 +34,35 @@ use const STR_PAD_LEFT;
use const STR_PAD_RIGHT;
/**
- * PhpTimeConverter uses built-in PHP functions and standard math operations
- * available to the PHP programming language to provide facilities for
- * converting parts of time into representations that may be used in UUIDs
+ * PhpTimeConverter uses built-in PHP functions and standard math operations available to the PHP programming language
+ * to provide facilities for converting parts of time into representations that may be used in UUIDs
*
- * @psalm-immutable
+ * @immutable
*/
class PhpTimeConverter implements TimeConverterInterface
{
/**
- * The number of 100-nanosecond intervals from the Gregorian calendar epoch
- * to the Unix epoch.
+ * The number of 100-nanosecond intervals from the Gregorian calendar epoch to the Unix epoch.
*/
private const GREGORIAN_TO_UNIX_INTERVALS = 0x01b21dd213814000;
/**
* The number of 100-nanosecond intervals in one second.
*/
- private const SECOND_INTERVALS = 10000000;
+ private const SECOND_INTERVALS = 10_000_000;
/**
* The number of 100-nanosecond intervals in one microsecond.
*/
private const MICROSECOND_INTERVALS = 10;
- /**
- * @var CalculatorInterface
- */
- private $calculator;
-
- /**
- * @var TimeConverterInterface
- */
- private $fallbackConverter;
-
- /**
- * @var int
- */
- private $phpPrecision;
+ private int $phpPrecision;
+ private CalculatorInterface $calculator;
+ private TimeConverterInterface $fallbackConverter;
public function __construct(
?CalculatorInterface $calculator = null,
- ?TimeConverterInterface $fallbackConverter = null
+ ?TimeConverterInterface $fallbackConverter = null,
) {
if ($calculator === null) {
$calculator = new BrickMathCalculator();
@@ -92,26 +79,29 @@ class PhpTimeConverter implements TimeConverterInterface
public function calculateTime(string $seconds, string $microseconds): Hexadecimal
{
- $seconds = new IntegerObject($seconds);
- $microseconds = new IntegerObject($microseconds);
+ $seconds = new IntegerObject($seconds); /** @phpstan-ignore possiblyImpure.new */
+ $microseconds = new IntegerObject($microseconds); /** @phpstan-ignore possiblyImpure.new */
- // Calculate the count of 100-nanosecond intervals since the Gregorian
- // calendar epoch for the given seconds and microseconds.
+ // Calculate the count of 100-nanosecond intervals since the Gregorian calendar epoch
+ // for the given seconds and microseconds.
$uuidTime = ((int) $seconds->toString() * self::SECOND_INTERVALS)
+ ((int) $microseconds->toString() * self::MICROSECOND_INTERVALS)
+ self::GREGORIAN_TO_UNIX_INTERVALS;
// Check to see whether we've overflowed the max/min integer size.
// If so, we will default to a different time converter.
- /** @psalm-suppress RedundantCondition */
+ // @phpstan-ignore function.alreadyNarrowedType (the integer value might have overflowed)
if (!is_int($uuidTime)) {
return $this->fallbackConverter->calculateTime(
$seconds->toString(),
- $microseconds->toString()
+ $microseconds->toString(),
);
}
- return new Hexadecimal(str_pad(dechex($uuidTime), 16, '0', STR_PAD_LEFT));
+ /** @phpstan-ignore possiblyImpure.new */
+ return new Hexadecimal(
+ str_pad(dechex($uuidTime), 16, '0', STR_PAD_LEFT)
+ );
}
public function convertTime(Hexadecimal $uuidTimestamp): Time
@@ -120,44 +110,41 @@ class PhpTimeConverter implements TimeConverterInterface
// Convert the 100-nanosecond intervals into seconds and microseconds.
$splitTime = $this->splitTime(
- ((int) $timestamp->toString() - self::GREGORIAN_TO_UNIX_INTERVALS)
- / self::SECOND_INTERVALS
+ ((int) $timestamp->toString() - self::GREGORIAN_TO_UNIX_INTERVALS) / self::SECOND_INTERVALS,
);
if (count($splitTime) === 0) {
return $this->fallbackConverter->convertTime($uuidTimestamp);
}
+ /** @phpstan-ignore possiblyImpure.new */
return new Time($splitTime['sec'], $splitTime['usec']);
}
/**
- * @param int|float $time The time to split into seconds and microseconds
+ * @param float | int $time The time to split into seconds and microseconds
*
* @return string[]
+ *
+ * @pure
*/
- private function splitTime($time): array
+ private function splitTime(float | int $time): array
{
$split = explode('.', (string) $time, 2);
- // If the $time value is a float but $split only has 1 element, then the
- // float math was rounded up to the next second, so we want to return
- // an empty array to allow use of the fallback converter.
+ // If the $time value is a float but $split only has 1 element, then the float math was rounded up to the next
+ // second, so we want to return an empty array to allow use of the fallback converter.
if (is_float($time) && count($split) === 1) {
return [];
}
if (count($split) === 1) {
- return [
- 'sec' => $split[0],
- 'usec' => '0',
- ];
+ return ['sec' => $split[0], 'usec' => '0'];
}
- // If the microseconds are less than six characters AND the length of
- // the number is greater than or equal to the PHP precision, then it's
- // possible that we lost some precision for the microseconds. Return an
- // empty array, so that we can choose to use the fallback converter.
+ // If the microseconds are less than six characters AND the length of the number is greater than or equal to the
+ // PHP precision, then it's possible that we lost some precision for the microseconds. Return an empty array so
+ // that we can choose to use the fallback converter.
if (strlen($split[1]) < 6 && strlen((string) $time) >= $this->phpPrecision) {
return [];
}
diff --git a/vendor/ramsey/uuid/src/Converter/Time/UnixTimeConverter.php b/vendor/ramsey/uuid/src/Converter/Time/UnixTimeConverter.php
new file mode 100644
index 0000000..4bd4125
--- /dev/null
+++ b/vendor/ramsey/uuid/src/Converter/Time/UnixTimeConverter.php
@@ -0,0 +1,92 @@
+
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Uuid\Converter\Time;
+
+use Ramsey\Uuid\Converter\TimeConverterInterface;
+use Ramsey\Uuid\Math\CalculatorInterface;
+use Ramsey\Uuid\Math\RoundingMode;
+use Ramsey\Uuid\Type\Hexadecimal;
+use Ramsey\Uuid\Type\Integer as IntegerObject;
+use Ramsey\Uuid\Type\Time;
+
+use function explode;
+use function str_pad;
+
+use const STR_PAD_LEFT;
+
+/**
+ * UnixTimeConverter converts Unix Epoch timestamps to/from hexadecimal values consisting of milliseconds elapsed since
+ * the Unix Epoch
+ *
+ * @immutable
+ */
+class UnixTimeConverter implements TimeConverterInterface
+{
+ private const MILLISECONDS = 1000;
+
+ public function __construct(private CalculatorInterface $calculator)
+ {
+ }
+
+ public function calculateTime(string $seconds, string $microseconds): Hexadecimal
+ {
+ /** @phpstan-ignore possiblyImpure.new */
+ $timestamp = new Time($seconds, $microseconds);
+
+ // Convert the seconds into milliseconds.
+ $sec = $this->calculator->multiply(
+ $timestamp->getSeconds(),
+ new IntegerObject(self::MILLISECONDS) /** @phpstan-ignore possiblyImpure.new */
+ );
+
+ // Convert the microseconds into milliseconds; the scale is zero because we need to discard the fractional part.
+ $usec = $this->calculator->divide(
+ RoundingMode::DOWN, // Always round down to stay in the previous millisecond.
+ 0,
+ $timestamp->getMicroseconds(),
+ new IntegerObject(self::MILLISECONDS), /** @phpstan-ignore possiblyImpure.new */
+ );
+
+ /** @var IntegerObject $unixTime */
+ $unixTime = $this->calculator->add($sec, $usec);
+
+ /** @phpstan-ignore possiblyImpure.new */
+ return new Hexadecimal(
+ str_pad(
+ $this->calculator->toHexadecimal($unixTime)->toString(),
+ 12,
+ '0',
+ STR_PAD_LEFT
+ ),
+ );
+ }
+
+ public function convertTime(Hexadecimal $uuidTimestamp): Time
+ {
+ $milliseconds = $this->calculator->toInteger($uuidTimestamp);
+
+ $unixTimestamp = $this->calculator->divide(
+ RoundingMode::HALF_UP,
+ 6,
+ $milliseconds,
+ new IntegerObject(self::MILLISECONDS), /** @phpstan-ignore possiblyImpure.new */
+ );
+
+ $split = explode('.', (string) $unixTimestamp, 2);
+
+ /** @phpstan-ignore possiblyImpure.new */
+ return new Time($split[0], $split[1] ?? '0');
+ }
+}
diff --git a/vendor/ramsey/uuid/src/Converter/TimeConverterInterface.php b/vendor/ramsey/uuid/src/Converter/TimeConverterInterface.php
index 1e84807..065e3b7 100644
--- a/vendor/ramsey/uuid/src/Converter/TimeConverterInterface.php
+++ b/vendor/ramsey/uuid/src/Converter/TimeConverterInterface.php
@@ -18,41 +18,36 @@ use Ramsey\Uuid\Type\Hexadecimal;
use Ramsey\Uuid\Type\Time;
/**
- * A time converter converts timestamps into representations that may be used
- * in UUIDs
+ * A time converter converts timestamps into representations that may be used in UUIDs
*
- * @psalm-immutable
+ * @immutable
*/
interface TimeConverterInterface
{
/**
- * Uses the provided seconds and micro-seconds to calculate the count of
- * 100-nanosecond intervals since UTC 00:00:00.00, 15 October 1582, for
- * RFC 4122 variant UUIDs
+ * Uses the provided seconds and micro-seconds to calculate the count of 100-nanosecond intervals since
+ * UTC 00:00:00.00, 15 October 1582, for RFC 9562 (formerly RFC 4122) variant UUIDs
*
- * @link http://tools.ietf.org/html/rfc4122#section-4.2.2 RFC 4122, § 4.2.2: Generation Details
+ * @link https://www.rfc-editor.org/rfc/rfc9562#appendix-A RFC 9562, Appendix A. Test Vectors
*
- * @param string $seconds A string representation of the number of seconds
- * since the Unix epoch for the time to calculate
- * @param string $microseconds A string representation of the micro-seconds
- * associated with the time to calculate
+ * @param string $seconds A string representation of seconds since the Unix epoch for the time to calculate
+ * @param string $microseconds A string representation of the micro-seconds associated with the time to calculate
*
* @return Hexadecimal The full UUID timestamp as a Hexadecimal value
*
- * @psalm-pure
+ * @pure
*/
public function calculateTime(string $seconds, string $microseconds): Hexadecimal;
/**
* Converts a timestamp extracted from a UUID to a Unix timestamp
*
- * @param Hexadecimal $uuidTimestamp A hexadecimal representation of a UUID
- * timestamp; a UUID timestamp is a count of 100-nanosecond intervals
- * since UTC 00:00:00.00, 15 October 1582.
+ * @param Hexadecimal $uuidTimestamp A hexadecimal representation of a UUID timestamp; a UUID timestamp is a count
+ * of 100-nanosecond intervals since UTC 00:00:00.00, 15 October 1582.
*
* @return Time An instance of {@see Time}
*
- * @psalm-pure
+ * @pure
*/
public function convertTime(Hexadecimal $uuidTimestamp): Time;
}
diff --git a/vendor/ramsey/uuid/src/DegradedUuid.php b/vendor/ramsey/uuid/src/DegradedUuid.php
index 9166042..169976e 100644
--- a/vendor/ramsey/uuid/src/DegradedUuid.php
+++ b/vendor/ramsey/uuid/src/DegradedUuid.php
@@ -15,10 +15,10 @@ declare(strict_types=1);
namespace Ramsey\Uuid;
/**
- * @deprecated DegradedUuid is no longer necessary to represent UUIDs on 32-bit
- * systems. Transition typehints to {@see UuidInterface}.
+ * @deprecated DegradedUuid is no longer necessary to represent UUIDs on 32-bit systems.
+ * Transition any type declarations using this class to {@see UuidInterface}.
*
- * @psalm-immutable
+ * @immutable
*/
class DegradedUuid extends Uuid
{
diff --git a/vendor/ramsey/uuid/src/DeprecatedUuidInterface.php b/vendor/ramsey/uuid/src/DeprecatedUuidInterface.php
index ed6d9de..91dbbc6 100644
--- a/vendor/ramsey/uuid/src/DeprecatedUuidInterface.php
+++ b/vendor/ramsey/uuid/src/DeprecatedUuidInterface.php
@@ -18,128 +18,107 @@ use DateTimeInterface;
use Ramsey\Uuid\Converter\NumberConverterInterface;
/**
- * This interface encapsulates deprecated methods for ramsey/uuid; this
- * interface and its methods will be removed in ramsey/uuid 5.0.0.
+ * This interface encapsulates deprecated methods for ramsey/uuid
*
- * @psalm-immutable
+ * @immutable
*/
interface DeprecatedUuidInterface
{
/**
- * @deprecated This method will be removed in 5.0.0. There is no alternative
- * recommendation, so plan accordingly.
+ * @deprecated This method will be removed in 5.0.0. There is no alternative recommendation, so plan accordingly.
*/
public function getNumberConverter(): NumberConverterInterface;
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance.
*
* @return string[]
*/
public function getFieldsHex(): array;
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeqHiAndReserved()}.
*/
public function getClockSeqHiAndReservedHex(): string;
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeqLow()}.
*/
public function getClockSeqLowHex(): string;
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeq()}.
*/
public function getClockSequenceHex(): string;
/**
- * @deprecated In ramsey/uuid version 5.0.0, this will be removed from the
- * interface. It is available at {@see UuidV1::getDateTime()}.
+ * @deprecated In ramsey/uuid version 5.0.0, this will be removed from the interface. It is available at
+ * {@see UuidV1::getDateTime()}.
*/
public function getDateTime(): DateTimeInterface;
/**
- * @deprecated This method will be removed in 5.0.0. There is no direct
- * alternative, but the same information may be obtained by splitting
- * in half the value returned by {@see UuidInterface::getHex()}.
+ * @deprecated This method will be removed in 5.0.0. There is no direct alternative, but the same information may be
+ * obtained by splitting in half the value returned by {@see UuidInterface::getHex()}.
*/
public function getLeastSignificantBitsHex(): string;
/**
- * @deprecated This method will be removed in 5.0.0. There is no direct
- * alternative, but the same information may be obtained by splitting
- * in half the value returned by {@see UuidInterface::getHex()}.
+ * @deprecated This method will be removed in 5.0.0. There is no direct alternative, but the same information may be
+ * obtained by splitting in half the value returned by {@see UuidInterface::getHex()}.
*/
public function getMostSignificantBitsHex(): string;
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getNode()}.
*/
public function getNodeHex(): string;
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeHiAndVersion()}.
*/
public function getTimeHiAndVersionHex(): string;
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeLow()}.
*/
public function getTimeLowHex(): string;
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeMid()}.
*/
public function getTimeMidHex(): string;
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimestamp()}.
*/
public function getTimestampHex(): string;
/**
- * @deprecated In ramsey/uuid version 5.0.0, this will be removed from this
- * interface. It has moved to {@see \Ramsey\Uuid\Rfc4122\UuidInterface::getUrn()}.
- */
- public function getUrn(): string;
-
- /**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getVariant()}.
*/
public function getVariant(): ?int;
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getVersion()}.
*/
diff --git a/vendor/ramsey/uuid/src/DeprecatedUuidMethodsTrait.php b/vendor/ramsey/uuid/src/DeprecatedUuidMethodsTrait.php
index 3428295..fb88578 100644
--- a/vendor/ramsey/uuid/src/DeprecatedUuidMethodsTrait.php
+++ b/vendor/ramsey/uuid/src/DeprecatedUuidMethodsTrait.php
@@ -17,10 +17,8 @@ namespace Ramsey\Uuid;
use DateTimeImmutable;
use DateTimeInterface;
use Ramsey\Uuid\Converter\NumberConverterInterface;
-use Ramsey\Uuid\Converter\TimeConverterInterface;
use Ramsey\Uuid\Exception\DateTimeException;
use Ramsey\Uuid\Exception\UnsupportedOperationException;
-use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
use Throwable;
use function str_pad;
@@ -29,34 +27,19 @@ use function substr;
use const STR_PAD_LEFT;
/**
- * This trait encapsulates deprecated methods for ramsey/uuid; this trait and
- * its methods will be removed in ramsey/uuid 5.0.0.
+ * This trait encapsulates deprecated methods for ramsey/uuid; this trait and its methods will be removed in ramsey/uuid 5.0.0.
*
- * @psalm-immutable
+ * @deprecated This trait and its methods will be removed in ramsey/uuid 5.0.0.
+ *
+ * @immutable
*/
trait DeprecatedUuidMethodsTrait
{
/**
- * @var Rfc4122FieldsInterface
- */
- protected $fields;
-
- /**
- * @var NumberConverterInterface
- */
- protected $numberConverter;
-
- /**
- * @var TimeConverterInterface
- */
- protected $timeConverter;
-
- /**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getClockSeqHiAndReserved()}
- * and use the arbitrary-precision math library of your choice to
- * convert it to a string integer.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeqHiAndReserved()} and use the arbitrary-precision math
+ * library of your choice to convert it to a string integer.
*/
public function getClockSeqHiAndReserved(): string
{
@@ -64,9 +47,9 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getClockSeqHiAndReserved()}.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeqHiAndReserved()}.
*/
public function getClockSeqHiAndReservedHex(): string
{
@@ -74,11 +57,10 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getClockSeqLow()}
- * and use the arbitrary-precision math library of your choice to
- * convert it to a string integer.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeqLow()} and use the arbitrary-precision math library of
+ * your choice to convert it to a string integer.
*/
public function getClockSeqLow(): string
{
@@ -86,9 +68,9 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getClockSeqLow()}.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeqLow()}.
*/
public function getClockSeqLowHex(): string
{
@@ -96,11 +78,10 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getClockSeq()}
- * and use the arbitrary-precision math library of your choice to
- * convert it to a string integer.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeq()} and use the arbitrary-precision math library of
+ * your choice to convert it to a string integer.
*/
public function getClockSequence(): string
{
@@ -108,9 +89,9 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getClockSeq()}.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeq()}.
*/
public function getClockSequenceHex(): string
{
@@ -118,8 +99,7 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated This method will be removed in 5.0.0. There is no alternative
- * recommendation, so plan accordingly.
+ * @deprecated This method will be removed in 5.0.0. There is no alternative recommendation, so plan accordingly.
*/
public function getNumberConverter(): NumberConverterInterface
{
@@ -127,8 +107,7 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated In ramsey/uuid version 5.0.0, this will be removed.
- * It is available at {@see UuidV1::getDateTime()}.
+ * @deprecated In ramsey/uuid version 5.0.0, this will be removed. It is available at {@see UuidV1::getDateTime()}.
*
* @return DateTimeImmutable An immutable instance of DateTimeInterface
*
@@ -156,8 +135,7 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
*
* @return string[]
*/
@@ -174,9 +152,8 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated This method will be removed in 5.0.0. There is no direct
- * alternative, but the same information may be obtained by splitting
- * in half the value returned by {@see UuidInterface::getHex()}.
+ * @deprecated This method will be removed in 5.0.0. There is no direct alternative, but the same information may be
+ * obtained by splitting in half the value returned by {@see UuidInterface::getHex()}.
*/
public function getLeastSignificantBits(): string
{
@@ -186,9 +163,8 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated This method will be removed in 5.0.0. There is no direct
- * alternative, but the same information may be obtained by splitting
- * in half the value returned by {@see UuidInterface::getHex()}.
+ * @deprecated This method will be removed in 5.0.0. There is no direct alternative, but the same information may be
+ * obtained by splitting in half the value returned by {@see UuidInterface::getHex()}.
*/
public function getLeastSignificantBitsHex(): string
{
@@ -196,9 +172,8 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated This method will be removed in 5.0.0. There is no direct
- * alternative, but the same information may be obtained by splitting
- * in half the value returned by {@see UuidInterface::getHex()}.
+ * @deprecated This method will be removed in 5.0.0. There is no direct alternative, but the same information may be
+ * obtained by splitting in half the value returned by {@see UuidInterface::getHex()}.
*/
public function getMostSignificantBits(): string
{
@@ -208,9 +183,8 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated This method will be removed in 5.0.0. There is no direct
- * alternative, but the same information may be obtained by splitting
- * in half the value returned by {@see UuidInterface::getHex()}.
+ * @deprecated This method will be removed in 5.0.0. There is no direct alternative, but the same information may be
+ * obtained by splitting in half the value returned by {@see UuidInterface::getHex()}.
*/
public function getMostSignificantBitsHex(): string
{
@@ -218,11 +192,10 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getNode()}
- * and use the arbitrary-precision math library of your choice to
- * convert it to a string integer.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getNode()} and use the arbitrary-precision math library of your
+ * choice to convert it to a string integer.
*/
public function getNode(): string
{
@@ -230,9 +203,9 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getNode()}.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getNode()}.
*/
public function getNodeHex(): string
{
@@ -240,11 +213,10 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getTimeHiAndVersion()}
- * and use the arbitrary-precision math library of your choice to
- * convert it to a string integer.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeHiAndVersion()} and use the arbitrary-precision math
+ * library of your choice to convert it to a string integer.
*/
public function getTimeHiAndVersion(): string
{
@@ -252,9 +224,9 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getTimeHiAndVersion()}.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeHiAndVersion()}.
*/
public function getTimeHiAndVersionHex(): string
{
@@ -262,11 +234,10 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getTimeLow()}
- * and use the arbitrary-precision math library of your choice to
- * convert it to a string integer.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeLow()} and use the arbitrary-precision math library of
+ * your choice to convert it to a string integer.
*/
public function getTimeLow(): string
{
@@ -274,9 +245,9 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getTimeLow()}.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeLow()}.
*/
public function getTimeLowHex(): string
{
@@ -284,11 +255,10 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getTimeMid()}
- * and use the arbitrary-precision math library of your choice to
- * convert it to a string integer.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeMid()} and use the arbitrary-precision math library of
+ * your choice to convert it to a string integer.
*/
public function getTimeMid(): string
{
@@ -296,9 +266,9 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getTimeMid()}.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeMid()}.
*/
public function getTimeMidHex(): string
{
@@ -306,11 +276,10 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getTimestamp()}
- * and use the arbitrary-precision math library of your choice to
- * convert it to a string integer.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimestamp()} and use the arbitrary-precision math library of
+ * your choice to convert it to a string integer.
*/
public function getTimestamp(): string
{
@@ -322,9 +291,9 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getTimestamp()}.
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimestamp()}.
*/
public function getTimestampHex(): string
{
@@ -336,20 +305,8 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated This has moved to {@see Rfc4122FieldsInterface::getUrn()} and
- * is available on {@see \Ramsey\Uuid\Rfc4122\UuidV1},
- * {@see \Ramsey\Uuid\Rfc4122\UuidV3}, {@see \Ramsey\Uuid\Rfc4122\UuidV4},
- * and {@see \Ramsey\Uuid\Rfc4122\UuidV5}.
- */
- public function getUrn(): string
- {
- return 'urn:uuid:' . $this->toString();
- }
-
- /**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a
- * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getVariant()}.
*/
public function getVariant(): ?int
@@ -358,9 +315,8 @@ trait DeprecatedUuidMethodsTrait
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a
- * {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.
+ * If it is a {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getVersion()}.
*/
public function getVersion(): ?int
diff --git a/vendor/ramsey/uuid/src/Exception/DceSecurityException.php b/vendor/ramsey/uuid/src/Exception/DceSecurityException.php
index e6d8001..bd8ca4c 100644
--- a/vendor/ramsey/uuid/src/Exception/DceSecurityException.php
+++ b/vendor/ramsey/uuid/src/Exception/DceSecurityException.php
@@ -17,8 +17,7 @@ namespace Ramsey\Uuid\Exception;
use RuntimeException as PhpRuntimeException;
/**
- * Thrown to indicate an exception occurred while dealing with DCE Security
- * (version 2) UUIDs
+ * Thrown to indicate an exception occurred while dealing with DCE Security (version 2) UUIDs
*/
class DceSecurityException extends PhpRuntimeException implements UuidExceptionInterface
{
diff --git a/vendor/ramsey/uuid/src/Exception/InvalidUuidStringException.php b/vendor/ramsey/uuid/src/Exception/InvalidUuidStringException.php
index 6d97581..cfc7eee 100644
--- a/vendor/ramsey/uuid/src/Exception/InvalidUuidStringException.php
+++ b/vendor/ramsey/uuid/src/Exception/InvalidUuidStringException.php
@@ -17,8 +17,8 @@ namespace Ramsey\Uuid\Exception;
/**
* Thrown to indicate that the string received is not a valid UUID
*
- * The InvalidArgumentException that this extends is the ramsey/uuid version
- * of this exception. It exists in the same namespace as this class.
+ * The InvalidArgumentException that this extends is the ramsey/uuid version of this exception. It exists in the same
+ * namespace as this class.
*/
class InvalidUuidStringException extends InvalidArgumentException implements UuidExceptionInterface
{
diff --git a/vendor/ramsey/uuid/src/Exception/NameException.php b/vendor/ramsey/uuid/src/Exception/NameException.php
index fd96a1f..ee72e16 100644
--- a/vendor/ramsey/uuid/src/Exception/NameException.php
+++ b/vendor/ramsey/uuid/src/Exception/NameException.php
@@ -17,8 +17,7 @@ namespace Ramsey\Uuid\Exception;
use RuntimeException as PhpRuntimeException;
/**
- * Thrown to indicate that an error occurred while attempting to hash a
- * namespace and name
+ * Thrown to indicate that an error occurred while attempting to hash a namespace and name
*/
class NameException extends PhpRuntimeException implements UuidExceptionInterface
{
diff --git a/vendor/ramsey/uuid/src/Exception/RandomSourceException.php b/vendor/ramsey/uuid/src/Exception/RandomSourceException.php
index a44dd34..7b24604 100644
--- a/vendor/ramsey/uuid/src/Exception/RandomSourceException.php
+++ b/vendor/ramsey/uuid/src/Exception/RandomSourceException.php
@@ -19,8 +19,8 @@ use RuntimeException as PhpRuntimeException;
/**
* Thrown to indicate that the source of random data encountered an error
*
- * This exception is used mostly to indicate that random_bytes() or random_int()
- * threw an exception. However, it may be used for other sources of random data.
+ * This exception is used mostly to indicate that random_bytes() or random_int() threw an exception. However, it may be
+ * used for other sources of random data.
*/
class RandomSourceException extends PhpRuntimeException implements UuidExceptionInterface
{
diff --git a/vendor/ramsey/uuid/src/FeatureSet.php b/vendor/ramsey/uuid/src/FeatureSet.php
index a8ab2fd..88ce7c4 100644
--- a/vendor/ramsey/uuid/src/FeatureSet.php
+++ b/vendor/ramsey/uuid/src/FeatureSet.php
@@ -14,7 +14,6 @@ declare(strict_types=1);
namespace Ramsey\Uuid;
-use Ramsey\Uuid\Builder\BuilderCollection;
use Ramsey\Uuid\Builder\FallbackBuilder;
use Ramsey\Uuid\Builder\UuidBuilderInterface;
use Ramsey\Uuid\Codec\CodecInterface;
@@ -36,6 +35,7 @@ use Ramsey\Uuid\Generator\RandomGeneratorFactory;
use Ramsey\Uuid\Generator\RandomGeneratorInterface;
use Ramsey\Uuid\Generator\TimeGeneratorFactory;
use Ramsey\Uuid\Generator\TimeGeneratorInterface;
+use Ramsey\Uuid\Generator\UnixTimeGenerator;
use Ramsey\Uuid\Guid\GuidBuilder;
use Ramsey\Uuid\Math\BrickMathCalculator;
use Ramsey\Uuid\Math\CalculatorInterface;
@@ -43,7 +43,6 @@ use Ramsey\Uuid\Nonstandard\UuidBuilder as NonstandardUuidBuilder;
use Ramsey\Uuid\Provider\Dce\SystemDceSecurityProvider;
use Ramsey\Uuid\Provider\DceSecurityProviderInterface;
use Ramsey\Uuid\Provider\Node\FallbackNodeProvider;
-use Ramsey\Uuid\Provider\Node\NodeProviderCollection;
use Ramsey\Uuid\Provider\Node\RandomNodeProvider;
use Ramsey\Uuid\Provider\Node\SystemNodeProvider;
use Ramsey\Uuid\Provider\NodeProviderInterface;
@@ -58,123 +57,52 @@ use const PHP_INT_SIZE;
/**
* FeatureSet detects and exposes available features in the current environment
*
- * A feature set is used by UuidFactory to determine the available features and
- * capabilities of the environment.
+ * A feature set is used by UuidFactory to determine the available features and capabilities of the environment.
*/
class FeatureSet
{
- /**
- * @var bool
- */
- private $disableBigNumber = false;
-
- /**
- * @var bool
- */
- private $disable64Bit = false;
-
- /**
- * @var bool
- */
- private $ignoreSystemNode = false;
-
- /**
- * @var bool
- */
- private $enablePecl = false;
-
- /**
- * @var UuidBuilderInterface
- */
- private $builder;
-
- /**
- * @var CodecInterface
- */
- private $codec;
-
- /**
- * @var DceSecurityGeneratorInterface
- */
- private $dceSecurityGenerator;
-
- /**
- * @var NameGeneratorInterface
- */
- private $nameGenerator;
-
- /**
- * @var NodeProviderInterface
- */
- private $nodeProvider;
-
- /**
- * @var NumberConverterInterface
- */
- private $numberConverter;
-
- /**
- * @var TimeConverterInterface
- */
- private $timeConverter;
-
- /**
- * @var RandomGeneratorInterface
- */
- private $randomGenerator;
-
- /**
- * @var TimeGeneratorInterface
- */
- private $timeGenerator;
-
- /**
- * @var TimeProviderInterface
- */
- private $timeProvider;
-
- /**
- * @var ValidatorInterface
- */
- private $validator;
-
- /**
- * @var CalculatorInterface
- */
- private $calculator;
+ private ?TimeProviderInterface $timeProvider = null;
+ private CalculatorInterface $calculator;
+ private CodecInterface $codec;
+ private DceSecurityGeneratorInterface $dceSecurityGenerator;
+ private NameGeneratorInterface $nameGenerator;
+ private NodeProviderInterface $nodeProvider;
+ private NumberConverterInterface $numberConverter;
+ private RandomGeneratorInterface $randomGenerator;
+ private TimeConverterInterface $timeConverter;
+ private TimeGeneratorInterface $timeGenerator;
+ private TimeGeneratorInterface $unixTimeGenerator;
+ private UuidBuilderInterface $builder;
+ private ValidatorInterface $validator;
/**
* @param bool $useGuids True build UUIDs using the GuidStringCodec
- * @param bool $force32Bit True to force the use of 32-bit functionality
- * (primarily for testing purposes)
- * @param bool $forceNoBigNumber True to disable the use of moontoast/math
- * (primarily for testing purposes)
- * @param bool $ignoreSystemNode True to disable attempts to check for the
- * system node ID (primarily for testing purposes)
- * @param bool $enablePecl True to enable the use of the PeclUuidTimeGenerator
- * to generate version 1 UUIDs
+ * @param bool $force32Bit True to force the use of 32-bit functionality (primarily for testing purposes)
+ * @param bool $forceNoBigNumber (obsolete)
+ * @param bool $ignoreSystemNode True to disable attempts to check for the system node ID (primarily for testing purposes)
+ * @param bool $enablePecl True to enable the use of the PeclUuidTimeGenerator to generate version 1 UUIDs
+ *
+ * @phpstan-ignore constructor.unusedParameter ($forceNoBigNumber is deprecated)
*/
public function __construct(
bool $useGuids = false,
- bool $force32Bit = false,
+ private bool $force32Bit = false,
bool $forceNoBigNumber = false,
- bool $ignoreSystemNode = false,
- bool $enablePecl = false
+ private bool $ignoreSystemNode = false,
+ private bool $enablePecl = false,
) {
- $this->disableBigNumber = $forceNoBigNumber;
- $this->disable64Bit = $force32Bit;
- $this->ignoreSystemNode = $ignoreSystemNode;
- $this->enablePecl = $enablePecl;
-
+ $this->randomGenerator = $this->buildRandomGenerator();
$this->setCalculator(new BrickMathCalculator());
$this->builder = $this->buildUuidBuilder($useGuids);
$this->codec = $this->buildCodec($useGuids);
$this->nodeProvider = $this->buildNodeProvider();
$this->nameGenerator = $this->buildNameGenerator();
- $this->randomGenerator = $this->buildRandomGenerator();
$this->setTimeProvider(new SystemTimeProvider());
$this->setDceSecurityProvider(new SystemDceSecurityProvider());
$this->validator = new GenericValidator();
+
+ assert($this->timeProvider !== null);
+ $this->unixTimeGenerator = $this->buildUnixTimeGenerator();
}
/**
@@ -257,6 +185,14 @@ class FeatureSet
return $this->timeGenerator;
}
+ /**
+ * Returns the Unix Epoch time generator configured for this environment
+ */
+ public function getUnixTimeGenerator(): TimeGeneratorInterface
+ {
+ return $this->unixTimeGenerator;
+ }
+
/**
* Returns the validator configured for this environment
*/
@@ -274,7 +210,6 @@ class FeatureSet
$this->numberConverter = $this->buildNumberConverter($calculator);
$this->timeConverter = $this->buildTimeConverter($calculator);
- /** @psalm-suppress RedundantPropertyInitializationCheck */
if (isset($this->timeProvider)) {
$this->timeGenerator = $this->buildTimeGenerator($this->timeProvider);
}
@@ -294,7 +229,10 @@ class FeatureSet
public function setNodeProvider(NodeProviderInterface $nodeProvider): void
{
$this->nodeProvider = $nodeProvider;
- $this->timeGenerator = $this->buildTimeGenerator($this->timeProvider);
+
+ if (isset($this->timeProvider)) {
+ $this->timeGenerator = $this->buildTimeGenerator($this->timeProvider);
+ }
}
/**
@@ -332,13 +270,9 @@ class FeatureSet
* Returns a DCE Security generator configured for this environment
*/
private function buildDceSecurityGenerator(
- DceSecurityProviderInterface $dceSecurityProvider
+ DceSecurityProviderInterface $dceSecurityProvider,
): DceSecurityGeneratorInterface {
- return new DceSecurityGenerator(
- $this->numberConverter,
- $this->timeGenerator,
- $dceSecurityProvider
- );
+ return new DceSecurityGenerator($this->numberConverter, $this->timeGenerator, $dceSecurityProvider);
}
/**
@@ -350,10 +284,7 @@ class FeatureSet
return new RandomNodeProvider();
}
- return new FallbackNodeProvider(new NodeProviderCollection([
- new SystemNodeProvider(),
- new RandomNodeProvider(),
- ]));
+ return new FallbackNodeProvider([new SystemNodeProvider(), new RandomNodeProvider()]);
}
/**
@@ -388,11 +319,15 @@ class FeatureSet
return new PeclUuidTimeGenerator();
}
- return (new TimeGeneratorFactory(
- $this->nodeProvider,
- $this->timeConverter,
- $timeProvider
- ))->getGenerator();
+ return (new TimeGeneratorFactory($this->nodeProvider, $this->timeConverter, $timeProvider))->getGenerator();
+ }
+
+ /**
+ * Returns a Unix Epoch time generator configured for this environment
+ */
+ private function buildUnixTimeGenerator(): TimeGeneratorInterface
+ {
+ return new UnixTimeGenerator($this->randomGenerator);
}
/**
@@ -432,11 +367,10 @@ class FeatureSet
return new GuidBuilder($this->numberConverter, $this->timeConverter);
}
- /** @psalm-suppress ImpureArgument */
- return new FallbackBuilder(new BuilderCollection([
+ return new FallbackBuilder([
new Rfc4122UuidBuilder($this->numberConverter, $this->timeConverter),
new NonstandardUuidBuilder($this->numberConverter, $this->timeConverter),
- ]));
+ ]);
}
/**
@@ -444,6 +378,6 @@ class FeatureSet
*/
private function is64BitSystem(): bool
{
- return PHP_INT_SIZE === 8 && !$this->disable64Bit;
+ return PHP_INT_SIZE === 8 && !$this->force32Bit;
}
}
diff --git a/vendor/ramsey/uuid/src/Fields/FieldsInterface.php b/vendor/ramsey/uuid/src/Fields/FieldsInterface.php
index f1b7a29..f17ea88 100644
--- a/vendor/ramsey/uuid/src/Fields/FieldsInterface.php
+++ b/vendor/ramsey/uuid/src/Fields/FieldsInterface.php
@@ -17,16 +17,17 @@ namespace Ramsey\Uuid\Fields;
use Serializable;
/**
- * UUIDs are comprised of unsigned integers, the bytes of which are separated
- * into fields and arranged in a particular layout defined by the specification
- * for the variant
+ * UUIDs consist of unsigned integers, the bytes of which are separated into fields and arranged in a particular layout
+ * defined by the specification for the variant
*
- * @psalm-immutable
+ * @immutable
*/
interface FieldsInterface extends Serializable
{
/**
* Returns the bytes that comprise the fields
+ *
+ * @pure
*/
public function getBytes(): string;
}
diff --git a/vendor/ramsey/uuid/src/Fields/SerializableFieldsTrait.php b/vendor/ramsey/uuid/src/Fields/SerializableFieldsTrait.php
index 16e6525..9ea47c6 100644
--- a/vendor/ramsey/uuid/src/Fields/SerializableFieldsTrait.php
+++ b/vendor/ramsey/uuid/src/Fields/SerializableFieldsTrait.php
@@ -23,7 +23,7 @@ use function strlen;
/**
* Provides common serialization functionality to fields
*
- * @psalm-immutable
+ * @immutable
*/
trait SerializableFieldsTrait
{
@@ -38,7 +38,7 @@ trait SerializableFieldsTrait
abstract public function getBytes(): string;
/**
- * Returns a string representation of object
+ * Returns a string representation of the object
*/
public function serialize(): string
{
@@ -56,22 +56,19 @@ trait SerializableFieldsTrait
/**
* Constructs the object from a serialized string representation
*
- * @param string $serialized The serialized string representation of the object
- *
- * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
- * @psalm-suppress UnusedMethodCall
+ * @param string $data The serialized string representation of the object
*/
- public function unserialize($serialized): void
+ public function unserialize(string $data): void
{
- if (strlen($serialized) === 16) {
- $this->__construct($serialized);
+ if (strlen($data) === 16) {
+ $this->__construct($data);
} else {
- $this->__construct(base64_decode($serialized));
+ $this->__construct(base64_decode($data));
}
}
/**
- * @param array{bytes: string} $data
+ * @param array{bytes?: string} $data
*/
public function __unserialize(array $data): void
{
diff --git a/vendor/ramsey/uuid/src/Generator/CombGenerator.php b/vendor/ramsey/uuid/src/Generator/CombGenerator.php
index 49b0938..5f6fa1d 100644
--- a/vendor/ramsey/uuid/src/Generator/CombGenerator.php
+++ b/vendor/ramsey/uuid/src/Generator/CombGenerator.php
@@ -29,94 +29,79 @@ use const STR_PAD_LEFT;
/**
* CombGenerator generates COMBs (combined UUID/timestamp)
*
- * The CombGenerator, when used with the StringCodec (and, by proxy, the
- * TimestampLastCombCodec) or the TimestampFirstCombCodec, combines the current
- * timestamp with a UUID (hence the name "COMB"). The timestamp either appears
- * as the first or last 48 bits of the COMB, depending on the codec used.
+ * The CombGenerator, when used with the StringCodec (and, by proxy, the TimestampLastCombCodec) or the
+ * TimestampFirstCombCodec, combines the current timestamp with a UUID (hence the name "COMB"). The timestamp either
+ * appears as the first or last 48 bits of the COMB, depending on the codec used.
*
- * By default, COMBs will have the timestamp set as the last 48 bits of the
- * identifier.
+ * By default, COMBs will have the timestamp set as the last 48 bits of the identifier.
*
- * ``` php
+ * ```
* $factory = new UuidFactory();
*
* $factory->setRandomGenerator(new CombGenerator(
* $factory->getRandomGenerator(),
- * $factory->getNumberConverter()
+ * $factory->getNumberConverter(),
* ));
*
* $comb = $factory->uuid4();
* ```
*
- * To generate a COMB with the timestamp as the first 48 bits, set the
- * TimestampFirstCombCodec as the codec.
+ * To generate a COMB with the timestamp as the first 48 bits, set the TimestampFirstCombCodec as the codec.
*
- * ``` php
+ * ```
* $factory->setCodec(new TimestampFirstCombCodec($factory->getUuidBuilder()));
* ```
*
- * @link https://www.informit.com/articles/printerfriendly/25862 The Cost of GUIDs as Primary Keys
+ * @deprecated Please migrate to {@link https://uuid.ramsey.dev/en/stable/rfc4122/version7.html Version 7, Unix Epoch Time UUIDs}.
+ *
+ * @link https://web.archive.org/web/20240118030355/https://www.informit.com/articles/printerfriendly/25862 The Cost of GUIDs as Primary Keys
*/
class CombGenerator implements RandomGeneratorInterface
{
public const TIMESTAMP_BYTES = 6;
- /**
- * @var RandomGeneratorInterface
- */
- private $randomGenerator;
-
- /**
- * @var NumberConverterInterface
- */
- private $converter;
-
public function __construct(
- RandomGeneratorInterface $generator,
- NumberConverterInterface $numberConverter
+ private RandomGeneratorInterface $generator,
+ private NumberConverterInterface $numberConverter
) {
- $this->converter = $numberConverter;
- $this->randomGenerator = $generator;
}
/**
- * @throws InvalidArgumentException if $length is not a positive integer
- * greater than or equal to CombGenerator::TIMESTAMP_BYTES
+ * @throws InvalidArgumentException if $length is not a positive integer greater than or equal to CombGenerator::TIMESTAMP_BYTES
*
* @inheritDoc
*/
public function generate(int $length): string
{
- if ($length < self::TIMESTAMP_BYTES || $length < 0) {
+ if ($length < self::TIMESTAMP_BYTES) {
throw new InvalidArgumentException(
'Length must be a positive integer greater than or equal to ' . self::TIMESTAMP_BYTES
);
}
+ if ($length % 2 !== 0) {
+ throw new InvalidArgumentException('Length must be an even number');
+ }
+
$hash = '';
+
+ /** @phpstan-ignore greater.alwaysTrue (TIMESTAMP_BYTES constant could change in child classes) */
if (self::TIMESTAMP_BYTES > 0 && $length > self::TIMESTAMP_BYTES) {
- $hash = $this->randomGenerator->generate($length - self::TIMESTAMP_BYTES);
+ $hash = $this->generator->generate($length - self::TIMESTAMP_BYTES);
}
$lsbTime = str_pad(
- $this->converter->toHex($this->timestamp()),
+ $this->numberConverter->toHex($this->timestamp()),
self::TIMESTAMP_BYTES * 2,
'0',
- STR_PAD_LEFT
+ STR_PAD_LEFT,
);
- return (string) hex2bin(
- str_pad(
- bin2hex($hash),
- $length - self::TIMESTAMP_BYTES,
- '0'
- )
- . $lsbTime
- );
+ return (string) hex2bin(str_pad(bin2hex($hash), $length - self::TIMESTAMP_BYTES, '0') . $lsbTime);
}
/**
- * Returns current timestamp a string integer, precise to 0.00001 seconds
+ * Returns the current timestamp as a string integer, precise to 0.00001 seconds
*/
private function timestamp(): string
{
diff --git a/vendor/ramsey/uuid/src/Generator/DceSecurityGenerator.php b/vendor/ramsey/uuid/src/Generator/DceSecurityGenerator.php
index aca8c5d..71192c0 100644
--- a/vendor/ramsey/uuid/src/Generator/DceSecurityGenerator.php
+++ b/vendor/ramsey/uuid/src/Generator/DceSecurityGenerator.php
@@ -31,8 +31,8 @@ use function substr_replace;
use const STR_PAD_LEFT;
/**
- * DceSecurityGenerator generates strings of binary data based on a local
- * domain, local identifier, node ID, clock sequence, and the current time
+ * DceSecurityGenerator generates strings of binary data based on a local domain, local identifier, node ID, clock
+ * sequence, and the current time
*/
class DceSecurityGenerator implements DceSecurityGeneratorInterface
{
@@ -52,61 +52,37 @@ class DceSecurityGenerator implements DceSecurityGeneratorInterface
*/
private const CLOCK_SEQ_LOW = 0;
- /**
- * @var NumberConverterInterface
- */
- private $numberConverter;
-
- /**
- * @var TimeGeneratorInterface
- */
- private $timeGenerator;
-
- /**
- * @var DceSecurityProviderInterface
- */
- private $dceSecurityProvider;
-
public function __construct(
- NumberConverterInterface $numberConverter,
- TimeGeneratorInterface $timeGenerator,
- DceSecurityProviderInterface $dceSecurityProvider
+ private NumberConverterInterface $numberConverter,
+ private TimeGeneratorInterface $timeGenerator,
+ private DceSecurityProviderInterface $dceSecurityProvider,
) {
- $this->numberConverter = $numberConverter;
- $this->timeGenerator = $timeGenerator;
- $this->dceSecurityProvider = $dceSecurityProvider;
}
public function generate(
int $localDomain,
?IntegerObject $localIdentifier = null,
?Hexadecimal $node = null,
- ?int $clockSeq = null
+ ?int $clockSeq = null,
): string {
if (!in_array($localDomain, self::DOMAINS)) {
- throw new DceSecurityException(
- 'Local domain must be a valid DCE Security domain'
- );
+ throw new DceSecurityException('Local domain must be a valid DCE Security domain');
}
if ($localIdentifier && $localIdentifier->isNegative()) {
throw new DceSecurityException(
- 'Local identifier out of bounds; it must be a value between 0 and 4294967295'
+ 'Local identifier out of bounds; it must be a value between 0 and 4294967295',
);
}
if ($clockSeq > self::CLOCK_SEQ_HIGH || $clockSeq < self::CLOCK_SEQ_LOW) {
- throw new DceSecurityException(
- 'Clock sequence out of bounds; it must be a value between 0 and 63'
- );
+ throw new DceSecurityException('Clock sequence out of bounds; it must be a value between 0 and 63');
}
switch ($localDomain) {
case Uuid::DCE_DOMAIN_ORG:
if ($localIdentifier === null) {
- throw new DceSecurityException(
- 'A local identifier must be provided for the org domain'
- );
+ throw new DceSecurityException('A local identifier must be provided for the org domain');
}
break;
@@ -127,13 +103,11 @@ class DceSecurityGenerator implements DceSecurityGeneratorInterface
$identifierHex = $this->numberConverter->toHex($localIdentifier->toString());
- // The maximum value for the local identifier is 0xffffffff, or
- // 4294967295. This is 8 hexadecimal digits, so if the length of
- // hexadecimal digits is greater than 8, we know the value is greater
- // than 0xffffffff.
+ // The maximum value for the local identifier is 0xffffffff, or 4,294,967,295. This is 8 hexadecimal digits, so
+ // if the length of hexadecimal digits is greater than 8, we know the value is greater than 0xffffffff.
if (strlen($identifierHex) > 8) {
throw new DceSecurityException(
- 'Local identifier out of bounds; it must be a value between 0 and 4294967295'
+ 'Local identifier out of bounds; it must be a value between 0 and 4294967295',
);
}
@@ -153,8 +127,7 @@ class DceSecurityGenerator implements DceSecurityGeneratorInterface
// Replace bytes in the time-based UUID with DCE Security values.
$bytes = substr_replace($bytes, $identifierBytes, 0, 4);
- $bytes = substr_replace($bytes, $domainByte, 9, 1);
- return $bytes;
+ return substr_replace($bytes, $domainByte, 9, 1);
}
}
diff --git a/vendor/ramsey/uuid/src/Generator/DceSecurityGeneratorInterface.php b/vendor/ramsey/uuid/src/Generator/DceSecurityGeneratorInterface.php
index faa29a5..f52eb55 100644
--- a/vendor/ramsey/uuid/src/Generator/DceSecurityGeneratorInterface.php
+++ b/vendor/ramsey/uuid/src/Generator/DceSecurityGeneratorInterface.php
@@ -19,28 +19,23 @@ use Ramsey\Uuid\Type\Hexadecimal;
use Ramsey\Uuid\Type\Integer as IntegerObject;
/**
- * A DCE Security generator generates strings of binary data based on a local
- * domain, local identifier, node ID, clock sequence, and the current time
+ * A DCE Security generator generates strings of binary data based on a local domain, local identifier, node ID, clock
+ * sequence, and the current time
*
* @see UuidV2
*/
interface DceSecurityGeneratorInterface
{
/**
- * Generate a binary string from a local domain, local identifier, node ID,
- * clock sequence, and current time
+ * Generate a binary string from a local domain, local identifier, node ID, clock sequence, and current time
*
- * @param int $localDomain The local domain to use when generating bytes,
- * according to DCE Security
- * @param IntegerObject|null $localIdentifier The local identifier for the
- * given domain; this may be a UID or GID on POSIX systems, if the local
- * domain is person or group, or it may be a site-defined identifier
- * if the local domain is org
- * @param Hexadecimal|null $node A 48-bit number representing the hardware
- * address
- * @param int|null $clockSeq A 14-bit number used to help avoid duplicates
- * that could arise when the clock is set backwards in time or if the
- * node ID changes
+ * @param int $localDomain The local domain to use when generating bytes, according to DCE Security
+ * @param IntegerObject | null $localIdentifier The local identifier for the given domain; this may be a UID or GID
+ * on POSIX systems if the local domain is "person" or "group," or it may be a site-defined identifier if the
+ * local domain is "org"
+ * @param Hexadecimal | null $node A 48-bit number representing the hardware address
+ * @param int | null $clockSeq A 14-bit number used to help avoid duplicates that could arise when the clock is set
+ * backwards in time or if the node ID changes
*
* @return string A binary string
*/
@@ -48,6 +43,6 @@ interface DceSecurityGeneratorInterface
int $localDomain,
?IntegerObject $localIdentifier = null,
?Hexadecimal $node = null,
- ?int $clockSeq = null
+ ?int $clockSeq = null,
): string;
}
diff --git a/vendor/ramsey/uuid/src/Generator/DefaultNameGenerator.php b/vendor/ramsey/uuid/src/Generator/DefaultNameGenerator.php
index 7303e9f..cf37b45 100644
--- a/vendor/ramsey/uuid/src/Generator/DefaultNameGenerator.php
+++ b/vendor/ramsey/uuid/src/Generator/DefaultNameGenerator.php
@@ -21,28 +21,22 @@ use ValueError;
use function hash;
/**
- * DefaultNameGenerator generates strings of binary data based on a namespace,
- * name, and hashing algorithm
+ * DefaultNameGenerator generates strings of binary data based on a namespace, name, and hashing algorithm
*/
class DefaultNameGenerator implements NameGeneratorInterface
{
- /** @psalm-pure */
+ /**
+ * @pure
+ */
public function generate(UuidInterface $ns, string $name, string $hashAlgorithm): string
{
try {
- /** @var string|bool $bytes */
- $bytes = @hash($hashAlgorithm, $ns->getBytes() . $name, true);
+ return hash($hashAlgorithm, $ns->getBytes() . $name, true);
} catch (ValueError $e) {
- $bytes = false; // keep same behavior than PHP 7
+ throw new NameException(
+ message: sprintf('Unable to hash namespace and name with algorithm \'%s\'', $hashAlgorithm),
+ previous: $e,
+ );
}
-
- if ($bytes === false) {
- throw new NameException(sprintf(
- 'Unable to hash namespace and name with algorithm \'%s\'',
- $hashAlgorithm
- ));
- }
-
- return (string) $bytes;
}
}
diff --git a/vendor/ramsey/uuid/src/Generator/DefaultTimeGenerator.php b/vendor/ramsey/uuid/src/Generator/DefaultTimeGenerator.php
index d245c7b..6ded59d 100644
--- a/vendor/ramsey/uuid/src/Generator/DefaultTimeGenerator.php
+++ b/vendor/ramsey/uuid/src/Generator/DefaultTimeGenerator.php
@@ -23,11 +23,11 @@ use Ramsey\Uuid\Provider\TimeProviderInterface;
use Ramsey\Uuid\Type\Hexadecimal;
use Throwable;
-use function ctype_xdigit;
use function dechex;
use function hex2bin;
use function is_int;
use function pack;
+use function preg_match;
use function sprintf;
use function str_pad;
use function strlen;
@@ -35,34 +35,15 @@ use function strlen;
use const STR_PAD_LEFT;
/**
- * DefaultTimeGenerator generates strings of binary data based on a node ID,
- * clock sequence, and the current time
+ * DefaultTimeGenerator generates strings of binary data based on a node ID, clock sequence, and the current time
*/
class DefaultTimeGenerator implements TimeGeneratorInterface
{
- /**
- * @var NodeProviderInterface
- */
- private $nodeProvider;
-
- /**
- * @var TimeConverterInterface
- */
- private $timeConverter;
-
- /**
- * @var TimeProviderInterface
- */
- private $timeProvider;
-
public function __construct(
- NodeProviderInterface $nodeProvider,
- TimeConverterInterface $timeConverter,
- TimeProviderInterface $timeProvider
+ private NodeProviderInterface $nodeProvider,
+ private TimeConverterInterface $timeConverter,
+ private TimeProviderInterface $timeProvider,
) {
- $this->nodeProvider = $nodeProvider;
- $this->timeConverter = $timeConverter;
- $this->timeProvider = $timeProvider;
}
/**
@@ -81,14 +62,10 @@ class DefaultTimeGenerator implements TimeGeneratorInterface
if ($clockSeq === null) {
try {
- // This does not use "stable storage"; see RFC 4122, Section 4.2.1.1.
+ // This does not use "stable storage"; see RFC 9562, section 6.3.
$clockSeq = random_int(0, 0x3fff);
} catch (Throwable $exception) {
- throw new RandomSourceException(
- $exception->getMessage(),
- (int) $exception->getCode(),
- $exception
- );
+ throw new RandomSourceException($exception->getMessage(), (int) $exception->getCode(), $exception);
}
}
@@ -102,43 +79,37 @@ class DefaultTimeGenerator implements TimeGeneratorInterface
$timeHex = str_pad($uuidTime->toString(), 16, '0', STR_PAD_LEFT);
if (strlen($timeHex) !== 16) {
- throw new TimeSourceException(sprintf(
- 'The generated time of \'%s\' is larger than expected',
- $timeHex
- ));
+ throw new TimeSourceException(sprintf('The generated time of \'%s\' is larger than expected', $timeHex));
}
$timeBytes = (string) hex2bin($timeHex);
return $timeBytes[4] . $timeBytes[5] . $timeBytes[6] . $timeBytes[7]
- . $timeBytes[2] . $timeBytes[3]
- . $timeBytes[0] . $timeBytes[1]
- . pack('n*', $clockSeq)
- . $node;
+ . $timeBytes[2] . $timeBytes[3] . $timeBytes[0] . $timeBytes[1]
+ . pack('n*', $clockSeq) . $node;
}
/**
- * Uses the node provider given when constructing this instance to get
- * the node ID (usually a MAC address)
+ * Uses the node provider given when constructing this instance to get the node ID (usually a MAC address)
*
- * @param string|int|null $node A node value that may be used to override the node provider
+ * @param int | string | null $node A node value that may be used to override the node provider
*
* @return string 6-byte binary string representation of the node
*
* @throws InvalidArgumentException
*/
- private function getValidNode($node): string
+ private function getValidNode(int | string | null $node): string
{
if ($node === null) {
$node = $this->nodeProvider->getNode();
}
- // Convert the node to hex, if it is still an integer.
+ // Convert the node to hex if it is still an integer.
if (is_int($node)) {
$node = dechex($node);
}
- if (!ctype_xdigit((string) $node) || strlen((string) $node) > 12) {
+ if (!preg_match('/^[A-Fa-f0-9]+$/', (string) $node) || strlen((string) $node) > 12) {
throw new InvalidArgumentException('Invalid node value');
}
diff --git a/vendor/ramsey/uuid/src/Generator/NameGeneratorFactory.php b/vendor/ramsey/uuid/src/Generator/NameGeneratorFactory.php
index 6f08e29..d68e94b 100644
--- a/vendor/ramsey/uuid/src/Generator/NameGeneratorFactory.php
+++ b/vendor/ramsey/uuid/src/Generator/NameGeneratorFactory.php
@@ -15,8 +15,7 @@ declare(strict_types=1);
namespace Ramsey\Uuid\Generator;
/**
- * NameGeneratorFactory retrieves a default name generator, based on the
- * environment
+ * NameGeneratorFactory retrieves a default name generator, based on the environment
*/
class NameGeneratorFactory
{
diff --git a/vendor/ramsey/uuid/src/Generator/NameGeneratorInterface.php b/vendor/ramsey/uuid/src/Generator/NameGeneratorInterface.php
index cc43dd0..f0fb8da 100644
--- a/vendor/ramsey/uuid/src/Generator/NameGeneratorInterface.php
+++ b/vendor/ramsey/uuid/src/Generator/NameGeneratorInterface.php
@@ -17,14 +17,13 @@ namespace Ramsey\Uuid\Generator;
use Ramsey\Uuid\UuidInterface;
/**
- * A name generator generates strings of binary data created by hashing together
- * a namespace with a name, according to a hashing algorithm
+ * A name generator generates strings of binary data created by hashing together a namespace with a name, according to a
+ * hashing algorithm
*/
interface NameGeneratorInterface
{
/**
- * Generate a binary string from a namespace and name hashed together with
- * the specified hashing algorithm
+ * Generate a binary string from a namespace and name hashed together with the specified hashing algorithm
*
* @param UuidInterface $ns The namespace
* @param string $name The name to use for creating a UUID
@@ -32,7 +31,7 @@ interface NameGeneratorInterface
*
* @return string A binary string
*
- * @psalm-pure
+ * @pure
*/
public function generate(UuidInterface $ns, string $name, string $hashAlgorithm): string;
}
diff --git a/vendor/ramsey/uuid/src/Generator/PeclUuidNameGenerator.php b/vendor/ramsey/uuid/src/Generator/PeclUuidNameGenerator.php
index 3780c5c..d13bafc 100644
--- a/vendor/ramsey/uuid/src/Generator/PeclUuidNameGenerator.php
+++ b/vendor/ramsey/uuid/src/Generator/PeclUuidNameGenerator.php
@@ -23,32 +23,26 @@ use function uuid_generate_sha1;
use function uuid_parse;
/**
- * PeclUuidNameGenerator generates strings of binary data from a namespace and a
- * name, using ext-uuid
+ * PeclUuidNameGenerator generates strings of binary data from a namespace and a name, using ext-uuid
*
* @link https://pecl.php.net/package/uuid ext-uuid
*/
class PeclUuidNameGenerator implements NameGeneratorInterface
{
- /** @psalm-pure */
+ /**
+ * @pure
+ */
public function generate(UuidInterface $ns, string $name, string $hashAlgorithm): string
{
- switch ($hashAlgorithm) {
- case 'md5':
- $uuid = uuid_generate_md5($ns->toString(), $name);
+ $uuid = match ($hashAlgorithm) {
+ 'md5' => uuid_generate_md5($ns->toString(), $name), /** @phpstan-ignore possiblyImpure.functionCall */
+ 'sha1' => uuid_generate_sha1($ns->toString(), $name), /** @phpstan-ignore possiblyImpure.functionCall */
+ default => throw new NameException(
+ sprintf('Unable to hash namespace and name with algorithm \'%s\'', $hashAlgorithm),
+ ),
+ };
- break;
- case 'sha1':
- $uuid = uuid_generate_sha1($ns->toString(), $name);
-
- break;
- default:
- throw new NameException(sprintf(
- 'Unable to hash namespace and name with algorithm \'%s\'',
- $hashAlgorithm
- ));
- }
-
- return uuid_parse($uuid);
+ /** @phpstan-ignore possiblyImpure.functionCall */
+ return (string) uuid_parse($uuid);
}
}
diff --git a/vendor/ramsey/uuid/src/Generator/PeclUuidRandomGenerator.php b/vendor/ramsey/uuid/src/Generator/PeclUuidRandomGenerator.php
index 07c47d2..6ad45ac 100644
--- a/vendor/ramsey/uuid/src/Generator/PeclUuidRandomGenerator.php
+++ b/vendor/ramsey/uuid/src/Generator/PeclUuidRandomGenerator.php
@@ -30,6 +30,6 @@ class PeclUuidRandomGenerator implements RandomGeneratorInterface
{
$uuid = uuid_create(UUID_TYPE_RANDOM);
- return uuid_parse($uuid);
+ return (string) uuid_parse($uuid);
}
}
diff --git a/vendor/ramsey/uuid/src/Generator/PeclUuidTimeGenerator.php b/vendor/ramsey/uuid/src/Generator/PeclUuidTimeGenerator.php
index e01f44e..558abf7 100644
--- a/vendor/ramsey/uuid/src/Generator/PeclUuidTimeGenerator.php
+++ b/vendor/ramsey/uuid/src/Generator/PeclUuidTimeGenerator.php
@@ -20,8 +20,7 @@ use function uuid_parse;
use const UUID_TYPE_TIME;
/**
- * PeclUuidTimeGenerator generates strings of binary data for time-base UUIDs,
- * using ext-uuid
+ * PeclUuidTimeGenerator generates strings of binary data for time-base UUIDs, using ext-uuid
*
* @link https://pecl.php.net/package/uuid ext-uuid
*/
@@ -34,6 +33,6 @@ class PeclUuidTimeGenerator implements TimeGeneratorInterface
{
$uuid = uuid_create(UUID_TYPE_TIME);
- return uuid_parse($uuid);
+ return (string) uuid_parse($uuid);
}
}
diff --git a/vendor/ramsey/uuid/src/Generator/RandomBytesGenerator.php b/vendor/ramsey/uuid/src/Generator/RandomBytesGenerator.php
index 12edb96..c169e63 100644
--- a/vendor/ramsey/uuid/src/Generator/RandomBytesGenerator.php
+++ b/vendor/ramsey/uuid/src/Generator/RandomBytesGenerator.php
@@ -18,8 +18,7 @@ use Ramsey\Uuid\Exception\RandomSourceException;
use Throwable;
/**
- * RandomBytesGenerator generates strings of random binary data using the
- * built-in `random_bytes()` PHP function
+ * RandomBytesGenerator generates strings of random binary data using the built-in `random_bytes()` PHP function
*
* @link http://php.net/random_bytes random_bytes()
*/
@@ -35,11 +34,7 @@ class RandomBytesGenerator implements RandomGeneratorInterface
try {
return random_bytes($length);
} catch (Throwable $exception) {
- throw new RandomSourceException(
- $exception->getMessage(),
- (int) $exception->getCode(),
- $exception
- );
+ throw new RandomSourceException($exception->getMessage(), (int) $exception->getCode(), $exception);
}
}
}
diff --git a/vendor/ramsey/uuid/src/Generator/RandomGeneratorFactory.php b/vendor/ramsey/uuid/src/Generator/RandomGeneratorFactory.php
index b723ac2..f4c3a6f 100644
--- a/vendor/ramsey/uuid/src/Generator/RandomGeneratorFactory.php
+++ b/vendor/ramsey/uuid/src/Generator/RandomGeneratorFactory.php
@@ -15,8 +15,7 @@ declare(strict_types=1);
namespace Ramsey\Uuid\Generator;
/**
- * RandomGeneratorFactory retrieves a default random generator, based on the
- * environment
+ * RandomGeneratorFactory retrieves a default random generator, based on the environment
*/
class RandomGeneratorFactory
{
diff --git a/vendor/ramsey/uuid/src/Generator/RandomGeneratorInterface.php b/vendor/ramsey/uuid/src/Generator/RandomGeneratorInterface.php
index 5c83cb4..ddd8732 100644
--- a/vendor/ramsey/uuid/src/Generator/RandomGeneratorInterface.php
+++ b/vendor/ramsey/uuid/src/Generator/RandomGeneratorInterface.php
@@ -22,7 +22,7 @@ interface RandomGeneratorInterface
/**
* Generates a string of randomized binary data
*
- * @param int $length The number of bytes of random binary data to generate
+ * @param int<1, max> $length The number of bytes to generate of random binary data
*
* @return string A binary string
*/
diff --git a/vendor/ramsey/uuid/src/Generator/RandomLibAdapter.php b/vendor/ramsey/uuid/src/Generator/RandomLibAdapter.php
index 24ed569..b6d401d 100644
--- a/vendor/ramsey/uuid/src/Generator/RandomLibAdapter.php
+++ b/vendor/ramsey/uuid/src/Generator/RandomLibAdapter.php
@@ -18,25 +18,24 @@ use RandomLib\Factory;
use RandomLib\Generator;
/**
- * RandomLibAdapter generates strings of random binary data using the
- * paragonie/random-lib library
+ * RandomLibAdapter generates strings of random binary data using the paragonie/random-lib library
+ *
+ * @deprecated This class will be removed in 5.0.0. Use the default RandomBytesGenerator or implement your own generator
+ * that implements RandomGeneratorInterface.
*
* @link https://packagist.org/packages/paragonie/random-lib paragonie/random-lib
*/
class RandomLibAdapter implements RandomGeneratorInterface
{
- /**
- * @var Generator
- */
- private $generator;
+ private Generator $generator;
/**
* Constructs a RandomLibAdapter
*
- * By default, if no Generator is passed in, this creates a high-strength
- * generator to use when generating random binary data.
+ * By default, if no Generator is passed in, this creates a high-strength generator to use when generating random
+ * binary data.
*
- * @param Generator|null $generator The generator to use when generating binary data
+ * @param Generator | null $generator The generator to use when generating binary data
*/
public function __construct(?Generator $generator = null)
{
diff --git a/vendor/ramsey/uuid/src/Generator/TimeGeneratorFactory.php b/vendor/ramsey/uuid/src/Generator/TimeGeneratorFactory.php
index 3d55fc4..433e74c 100644
--- a/vendor/ramsey/uuid/src/Generator/TimeGeneratorFactory.php
+++ b/vendor/ramsey/uuid/src/Generator/TimeGeneratorFactory.php
@@ -19,34 +19,15 @@ use Ramsey\Uuid\Provider\NodeProviderInterface;
use Ramsey\Uuid\Provider\TimeProviderInterface;
/**
- * TimeGeneratorFactory retrieves a default time generator, based on the
- * environment
+ * TimeGeneratorFactory retrieves a default time generator, based on the environment
*/
class TimeGeneratorFactory
{
- /**
- * @var NodeProviderInterface
- */
- private $nodeProvider;
-
- /**
- * @var TimeConverterInterface
- */
- private $timeConverter;
-
- /**
- * @var TimeProviderInterface
- */
- private $timeProvider;
-
public function __construct(
- NodeProviderInterface $nodeProvider,
- TimeConverterInterface $timeConverter,
- TimeProviderInterface $timeProvider
+ private NodeProviderInterface $nodeProvider,
+ private TimeConverterInterface $timeConverter,
+ private TimeProviderInterface $timeProvider,
) {
- $this->nodeProvider = $nodeProvider;
- $this->timeConverter = $timeConverter;
- $this->timeProvider = $timeProvider;
}
/**
@@ -54,10 +35,6 @@ class TimeGeneratorFactory
*/
public function getGenerator(): TimeGeneratorInterface
{
- return new DefaultTimeGenerator(
- $this->nodeProvider,
- $this->timeConverter,
- $this->timeProvider
- );
+ return new DefaultTimeGenerator($this->nodeProvider, $this->timeConverter, $this->timeProvider);
}
}
diff --git a/vendor/ramsey/uuid/src/Generator/TimeGeneratorInterface.php b/vendor/ramsey/uuid/src/Generator/TimeGeneratorInterface.php
index 18f21c4..c15d820 100644
--- a/vendor/ramsey/uuid/src/Generator/TimeGeneratorInterface.php
+++ b/vendor/ramsey/uuid/src/Generator/TimeGeneratorInterface.php
@@ -17,20 +17,17 @@ namespace Ramsey\Uuid\Generator;
use Ramsey\Uuid\Type\Hexadecimal;
/**
- * A time generator generates strings of binary data based on a node ID,
- * clock sequence, and the current time
+ * A time generator generates strings of binary data based on a node ID, clock sequence, and the current time
*/
interface TimeGeneratorInterface
{
/**
* Generate a binary string from a node ID, clock sequence, and current time
*
- * @param Hexadecimal|int|string|null $node A 48-bit number representing the
- * hardware address; this number may be represented as an integer or a
- * hexadecimal string
- * @param int|null $clockSeq A 14-bit number used to help avoid duplicates
- * that could arise when the clock is set backwards in time or if the
- * node ID changes
+ * @param Hexadecimal | int | string | null $node A 48-bit number representing the hardware address; this number may
+ * be represented as an integer or a hexadecimal string
+ * @param int | null $clockSeq A 14-bit number used to help avoid duplicates that could arise when the clock is set
+ * backwards in time or if the node ID changes
*
* @return string A binary string
*/
diff --git a/vendor/ramsey/uuid/src/Generator/UnixTimeGenerator.php b/vendor/ramsey/uuid/src/Generator/UnixTimeGenerator.php
new file mode 100644
index 0000000..a2615f1
--- /dev/null
+++ b/vendor/ramsey/uuid/src/Generator/UnixTimeGenerator.php
@@ -0,0 +1,165 @@
+
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Uuid\Generator;
+
+use Brick\Math\BigInteger;
+use DateTimeInterface;
+use Ramsey\Uuid\Type\Hexadecimal;
+
+use function assert;
+use function hash;
+use function pack;
+use function str_pad;
+use function strlen;
+use function substr;
+use function substr_replace;
+use function unpack;
+
+use const PHP_INT_SIZE;
+use const STR_PAD_LEFT;
+
+/**
+ * UnixTimeGenerator generates bytes, combining a 48-bit timestamp in milliseconds since the Unix Epoch with 80 random bits
+ *
+ * Code and concepts within this class are borrowed from the symfony/uid package and are used under the terms of the MIT
+ * license distributed with symfony/uid.
+ *
+ * symfony/uid is copyright (c) Fabien Potencier.
+ *
+ * @link https://symfony.com/components/Uid Symfony Uid component
+ * @link https://github.com/symfony/uid/blob/4f9f537e57261519808a7ce1d941490736522bbc/UuidV7.php Symfony UuidV7 class
+ * @link https://github.com/symfony/uid/blob/6.2/LICENSE MIT License
+ */
+class UnixTimeGenerator implements TimeGeneratorInterface
+{
+ private static string $time = '';
+ private static ?string $seed = null;
+ private static int $seedIndex = 0;
+
+ /** @var int[] */
+ private static array $rand = [];
+
+ /** @var int[] */
+ private static array $seedParts;
+
+ public function __construct(
+ private RandomGeneratorInterface $randomGenerator,
+ private int $intSize = PHP_INT_SIZE,
+ ) {
+ }
+
+ /**
+ * @param Hexadecimal | int | string | null $node Unused in this generator
+ * @param int | null $clockSeq Unused in this generator
+ * @param DateTimeInterface | null $dateTime A date-time instance to use when generating bytes
+ */
+ public function generate($node = null, ?int $clockSeq = null, ?DateTimeInterface $dateTime = null): string
+ {
+ if ($dateTime === null) {
+ $time = microtime(false);
+ $time = substr($time, 11) . substr($time, 2, 3);
+ } else {
+ $time = $dateTime->format('Uv');
+ }
+
+ if ($time > self::$time || ($dateTime !== null && $time !== self::$time)) {
+ $this->randomize($time);
+ } else {
+ $time = $this->increment();
+ }
+
+ if ($this->intSize >= 8) {
+ $time = substr(pack('J', (int) $time), -6);
+ } else {
+ $time = str_pad(BigInteger::of($time)->toBytes(false), 6, "\x00", STR_PAD_LEFT);
+ }
+
+ assert(strlen($time) === 6);
+
+ return $time . pack('n*', self::$rand[1], self::$rand[2], self::$rand[3], self::$rand[4], self::$rand[5]);
+ }
+
+ private function randomize(string $time): void
+ {
+ if (self::$seed === null) {
+ $seed = $this->randomGenerator->generate(16);
+ self::$seed = $seed;
+ } else {
+ $seed = $this->randomGenerator->generate(10);
+ }
+
+ /** @var int[] $rand */
+ $rand = unpack('n*', $seed);
+ $rand[1] &= 0x03ff;
+
+ self::$rand = $rand;
+ self::$time = $time;
+ }
+
+ /**
+ * Special thanks to Nicolas Grekas () for sharing the following information:
+ *
+ * Within the same ms, we increment the rand part by a random 24-bit number.
+ *
+ * Instead of getting this number from random_bytes(), which is slow, we get it by sha512-hashing self::$seed. This
+ * produces 64 bytes of entropy, which we need to split in a list of 24-bit numbers. `unpack()` first splits them
+ * into 16 x 32-bit numbers; we take the first byte of each number to get 5 extra 24-bit numbers. Then, we consume
+ * each number one-by-one and run this logic every 21 iterations.
+ *
+ * `self::$rand` holds the random part of the UUID, split into 5 x 16-bit numbers for x86 portability. We increment
+ * this random part by the next 24-bit number in the `self::$seedParts` list and decrement `self::$seedIndex`.
+ */
+ private function increment(): string
+ {
+ if (self::$seedIndex === 0 && self::$seed !== null) {
+ self::$seed = hash('sha512', self::$seed, true);
+
+ /** @var int[] $s */
+ $s = unpack('l*', self::$seed);
+ $s[] = ($s[1] >> 8 & 0xff0000) | ($s[2] >> 16 & 0xff00) | ($s[3] >> 24 & 0xff);
+ $s[] = ($s[4] >> 8 & 0xff0000) | ($s[5] >> 16 & 0xff00) | ($s[6] >> 24 & 0xff);
+ $s[] = ($s[7] >> 8 & 0xff0000) | ($s[8] >> 16 & 0xff00) | ($s[9] >> 24 & 0xff);
+ $s[] = ($s[10] >> 8 & 0xff0000) | ($s[11] >> 16 & 0xff00) | ($s[12] >> 24 & 0xff);
+ $s[] = ($s[13] >> 8 & 0xff0000) | ($s[14] >> 16 & 0xff00) | ($s[15] >> 24 & 0xff);
+
+ self::$seedParts = $s;
+ self::$seedIndex = 21;
+ }
+
+ self::$rand[5] = 0xffff & $carry = self::$rand[5] + 1 + (self::$seedParts[self::$seedIndex--] & 0xffffff);
+ self::$rand[4] = 0xffff & $carry = self::$rand[4] + ($carry >> 16);
+ self::$rand[3] = 0xffff & $carry = self::$rand[3] + ($carry >> 16);
+ self::$rand[2] = 0xffff & $carry = self::$rand[2] + ($carry >> 16);
+ self::$rand[1] += $carry >> 16;
+
+ if (0xfc00 & self::$rand[1]) {
+ $time = self::$time;
+ $mtime = (int) substr($time, -9);
+
+ if ($this->intSize >= 8 || strlen($time) < 10) {
+ $time = (string) ((int) $time + 1);
+ } elseif ($mtime === 999999999) {
+ $time = (1 + (int) substr($time, 0, -9)) . '000000000';
+ } else {
+ $mtime++;
+ $time = substr_replace($time, str_pad((string) $mtime, 9, '0', STR_PAD_LEFT), -9);
+ }
+
+ $this->randomize($time);
+ }
+
+ return self::$time;
+ }
+}
diff --git a/vendor/ramsey/uuid/src/Guid/Fields.php b/vendor/ramsey/uuid/src/Guid/Fields.php
index d8a1a2b..58aa5e1 100644
--- a/vendor/ramsey/uuid/src/Guid/Fields.php
+++ b/vendor/ramsey/uuid/src/Guid/Fields.php
@@ -17,6 +17,7 @@ namespace Ramsey\Uuid\Guid;
use Ramsey\Uuid\Exception\InvalidArgumentException;
use Ramsey\Uuid\Fields\SerializableFieldsTrait;
use Ramsey\Uuid\Rfc4122\FieldsInterface;
+use Ramsey\Uuid\Rfc4122\MaxTrait;
use Ramsey\Uuid\Rfc4122\NilTrait;
use Ramsey\Uuid\Rfc4122\VariantTrait;
use Ramsey\Uuid\Rfc4122\VersionTrait;
@@ -36,24 +37,20 @@ use function unpack;
use const STR_PAD_LEFT;
/**
- * GUIDs are comprised of a set of named fields, according to RFC 4122
+ * GUIDs consist of a set of named fields, according to RFC 9562 (formerly RFC 4122)
*
* @see Guid
*
- * @psalm-immutable
+ * @immutable
*/
final class Fields implements FieldsInterface
{
+ use MaxTrait;
use NilTrait;
use SerializableFieldsTrait;
use VariantTrait;
use VersionTrait;
- /**
- * @var string
- */
- private $bytes;
-
/**
* @param string $bytes A 16-byte binary string representation of a UUID
*
@@ -61,28 +58,23 @@ final class Fields implements FieldsInterface
* @throws InvalidArgumentException if the byte string does not represent a GUID
* @throws InvalidArgumentException if the byte string does not contain a valid version
*/
- public function __construct(string $bytes)
+ public function __construct(private string $bytes)
{
- if (strlen($bytes) !== 16) {
+ if (strlen($this->bytes) !== 16) {
throw new InvalidArgumentException(
- 'The byte string must be 16 bytes long; '
- . 'received ' . strlen($bytes) . ' bytes'
+ 'The byte string must be 16 bytes long; received ' . strlen($this->bytes) . ' bytes',
);
}
- $this->bytes = $bytes;
-
if (!$this->isCorrectVariant()) {
throw new InvalidArgumentException(
- 'The byte string received does not conform to the RFC '
- . '4122 or Microsoft Corporation variants'
+ 'The byte string received does not conform to the RFC 9562 (formerly RFC 4122) '
+ . 'or Microsoft Corporation variants',
);
}
if (!$this->isCorrectVersion()) {
- throw new InvalidArgumentException(
- 'The byte string received does not contain a valid version'
- );
+ throw new InvalidArgumentException('The byte string received does not contain a valid version');
}
}
@@ -94,47 +86,35 @@ final class Fields implements FieldsInterface
public function getTimeLow(): Hexadecimal
{
// Swap the bytes from little endian to network byte order.
- /** @var array $hex */
+ /** @var string[] $hex */
$hex = unpack(
'H*',
pack(
'v*',
hexdec(bin2hex(substr($this->bytes, 2, 2))),
- hexdec(bin2hex(substr($this->bytes, 0, 2)))
- )
+ hexdec(bin2hex(substr($this->bytes, 0, 2))),
+ ),
);
- return new Hexadecimal((string) ($hex[1] ?? ''));
+ return new Hexadecimal($hex[1] ?? '');
}
public function getTimeMid(): Hexadecimal
{
// Swap the bytes from little endian to network byte order.
- /** @var array $hex */
- $hex = unpack(
- 'H*',
- pack(
- 'v',
- hexdec(bin2hex(substr($this->bytes, 4, 2)))
- )
- );
+ /** @var string[] $hex */
+ $hex = unpack('H*', pack('v', hexdec(bin2hex(substr($this->bytes, 4, 2)))));
- return new Hexadecimal((string) ($hex[1] ?? ''));
+ return new Hexadecimal($hex[1] ?? '');
}
public function getTimeHiAndVersion(): Hexadecimal
{
// Swap the bytes from little endian to network byte order.
- /** @var array $hex */
- $hex = unpack(
- 'H*',
- pack(
- 'v',
- hexdec(bin2hex(substr($this->bytes, 6, 2)))
- )
- );
+ /** @var string[] $hex */
+ $hex = unpack('H*', pack('v', hexdec(bin2hex(substr($this->bytes, 6, 2)))));
- return new Hexadecimal((string) ($hex[1] ?? ''));
+ return new Hexadecimal($hex[1] ?? '');
}
public function getTimestamp(): Hexadecimal
@@ -149,7 +129,13 @@ final class Fields implements FieldsInterface
public function getClockSeq(): Hexadecimal
{
- $clockSeq = hexdec(bin2hex(substr($this->bytes, 8, 2))) & 0x3fff;
+ if ($this->isMax()) {
+ $clockSeq = 0xffff;
+ } elseif ($this->isNil()) {
+ $clockSeq = 0x0000;
+ } else {
+ $clockSeq = hexdec(bin2hex(substr($this->bytes, 8, 2))) & 0x3fff;
+ }
return new Hexadecimal(str_pad(dechex($clockSeq), 4, '0', STR_PAD_LEFT));
}
@@ -171,19 +157,19 @@ final class Fields implements FieldsInterface
public function getVersion(): ?int
{
- if ($this->isNil()) {
+ if ($this->isNil() || $this->isMax()) {
return null;
}
- /** @var array $parts */
+ /** @var int[] $parts */
$parts = unpack('n*', $this->bytes);
- return ((int) $parts[4] >> 4) & 0x00f;
+ return ($parts[4] >> 4) & 0x00f;
}
private function isCorrectVariant(): bool
{
- if ($this->isNil()) {
+ if ($this->isNil() || $this->isMax()) {
return true;
}
diff --git a/vendor/ramsey/uuid/src/Guid/Guid.php b/vendor/ramsey/uuid/src/Guid/Guid.php
index b3ed096..af551cf 100644
--- a/vendor/ramsey/uuid/src/Guid/Guid.php
+++ b/vendor/ramsey/uuid/src/Guid/Guid.php
@@ -24,29 +24,25 @@ use Ramsey\Uuid\Uuid;
*
* From Wikipedia:
*
- * > The first three fields are unsigned 32- and 16-bit integers and are subject
- * > to swapping, while the last two fields consist of uninterpreted bytes, not
- * > subject to swapping. This byte swapping applies even for versions 3, 4, and
- * > 5, where the canonical fields do not correspond to the content of the UUID.
+ * > The first three fields are unsigned 32- and 16-bit integers and are subject to swapping, while the last two fields
+ * > consist of uninterpreted bytes, not subject to swapping. This byte swapping applies even for versions 3, 4, and 5,
+ * > where the canonical fields do not correspond to the content of the UUID.
*
- * The first three fields of a GUID are encoded in little-endian byte order,
- * while the last three fields are in network (big-endian) byte order. This is
- * according to the history of the Microsoft definition of a GUID.
+ * The first three fields of a GUID are encoded in little-endian byte order, while the last three fields are in network
+ * (big-endian) byte order. This is according to the history of the Microsoft GUID definition.
*
* According to the .NET Guid.ToByteArray method documentation:
*
- * > Note that the order of bytes in the returned byte array is different from
- * > the string representation of a Guid value. The order of the beginning
- * > four-byte group and the next two two-byte groups is reversed, whereas the
- * > order of the last two-byte group and the closing six-byte group is the
- * > same.
+ * > Note that the order of bytes in the returned byte array is different from the string representation of a Guid value.
+ * > The order of the beginning four-byte group and the next two two-byte groups is reversed, whereas the order of the
+ * > last two-byte group and the closing six-byte group is the same.
*
* @link https://en.wikipedia.org/wiki/Universally_unique_identifier#Variants UUID Variants on Wikipedia
* @link https://docs.microsoft.com/en-us/windows/win32/api/guiddef/ns-guiddef-guid Windows GUID structure
* @link https://docs.microsoft.com/en-us/dotnet/api/system.guid .NET Guid Struct
* @link https://docs.microsoft.com/en-us/dotnet/api/system.guid.tobytearray .NET Guid.ToByteArray Method
*
- * @psalm-immutable
+ * @immutable
*/
final class Guid extends Uuid
{
@@ -54,7 +50,7 @@ final class Guid extends Uuid
Fields $fields,
NumberConverterInterface $numberConverter,
CodecInterface $codec,
- TimeConverterInterface $timeConverter
+ TimeConverterInterface $timeConverter,
) {
parent::__construct($fields, $numberConverter, $codec, $timeConverter);
}
diff --git a/vendor/ramsey/uuid/src/Guid/GuidBuilder.php b/vendor/ramsey/uuid/src/Guid/GuidBuilder.php
index 758dd6b..db743d9 100644
--- a/vendor/ramsey/uuid/src/Guid/GuidBuilder.php
+++ b/vendor/ramsey/uuid/src/Guid/GuidBuilder.php
@@ -27,32 +27,19 @@ use Throwable;
*
* @see Guid
*
- * @psalm-immutable
+ * @immutable
*/
class GuidBuilder implements UuidBuilderInterface
{
/**
- * @var NumberConverterInterface
- */
- private $numberConverter;
-
- /**
- * @var TimeConverterInterface
- */
- private $timeConverter;
-
- /**
- * @param NumberConverterInterface $numberConverter The number converter to
- * use when constructing the Guid
- * @param TimeConverterInterface $timeConverter The time converter to use
- * for converting timestamps extracted from a UUID to Unix timestamps
+ * @param NumberConverterInterface $numberConverter The number converter to use when constructing the Guid
+ * @param TimeConverterInterface $timeConverter The time converter to use for converting timestamps extracted from a
+ * UUID to Unix timestamps
*/
public function __construct(
- NumberConverterInterface $numberConverter,
- TimeConverterInterface $timeConverter
+ private NumberConverterInterface $numberConverter,
+ private TimeConverterInterface $timeConverter,
) {
- $this->numberConverter = $numberConverter;
- $this->timeConverter = $timeConverter;
}
/**
@@ -63,27 +50,27 @@ class GuidBuilder implements UuidBuilderInterface
*
* @return Guid The GuidBuilder returns an instance of Ramsey\Uuid\Guid\Guid
*
- * @psalm-pure
+ * @pure
*/
public function build(CodecInterface $codec, string $bytes): UuidInterface
{
try {
- return new Guid(
- $this->buildFields($bytes),
- $this->numberConverter,
- $codec,
- $this->timeConverter
- );
+ /** @phpstan-ignore possiblyImpure.new */
+ return new Guid($this->buildFields($bytes), $this->numberConverter, $codec, $this->timeConverter);
} catch (Throwable $e) {
+ /** @phpstan-ignore possiblyImpure.methodCall, possiblyImpure.methodCall */
throw new UnableToBuildUuidException($e->getMessage(), (int) $e->getCode(), $e);
}
}
/**
- * Proxy method to allow injecting a mock, for testing
+ * Proxy method to allow injecting a mock for testing
+ *
+ * @pure
*/
protected function buildFields(string $bytes): Fields
{
+ /** @phpstan-ignore possiblyImpure.new */
return new Fields($bytes);
}
}
diff --git a/vendor/ramsey/uuid/src/Lazy/LazyUuidFromString.php b/vendor/ramsey/uuid/src/Lazy/LazyUuidFromString.php
index 8ba7579..8d3129c 100644
--- a/vendor/ramsey/uuid/src/Lazy/LazyUuidFromString.php
+++ b/vendor/ramsey/uuid/src/Lazy/LazyUuidFromString.php
@@ -18,8 +18,8 @@ use DateTimeInterface;
use Ramsey\Uuid\Converter\NumberConverterInterface;
use Ramsey\Uuid\Exception\UnsupportedOperationException;
use Ramsey\Uuid\Fields\FieldsInterface;
-use Ramsey\Uuid\Nonstandard\UuidV6;
use Ramsey\Uuid\Rfc4122\UuidV1;
+use Ramsey\Uuid\Rfc4122\UuidV6;
use Ramsey\Uuid\Type\Hexadecimal;
use Ramsey\Uuid\Type\Integer as IntegerObject;
use Ramsey\Uuid\UuidFactory;
@@ -35,41 +35,32 @@ use function substr;
/**
* Lazy version of a UUID: its format has not been determined yet, so it is mostly only usable for string/bytes
- * conversion. This object optimizes instantiation, serialization and string conversion time, at the cost of
- * increased overhead for more advanced UUID operations.
+ * conversion. This object optimizes instantiation, serialization and string conversion time, at the cost of increased
+ * overhead for more advanced UUID operations.
*
- * @internal this type is used internally for performance reasons, and is not supposed to be directly referenced
- * in consumer libraries.
+ * > [!NOTE]
+ * > The {@see FieldsInterface} does not declare methods that deprecated API relies upon: the API has been ported from
+ * > the {@see \Ramsey\Uuid\Uuid} definition, and is deprecated anyway.
*
- * @psalm-immutable
+ * > [!NOTE]
+ * > The deprecated API from {@see \Ramsey\Uuid\Uuid} is in use here (on purpose): it will be removed once the
+ * > deprecated API is gone from this class too.
*
- * Note: the {@see FieldsInterface} does not declare methods that deprecated API
- * relies upon: the API has been ported from the {@see \Ramsey\Uuid\Uuid} definition,
- * and is deprecated anyway.
- * Note: the deprecated API from {@see \Ramsey\Uuid\Uuid} is in use here (on purpose): it will be removed
- * once the deprecated API is gone from this class too.
- *
- * @psalm-suppress UndefinedInterfaceMethod
- * @psalm-suppress DeprecatedMethod
+ * @internal this type is used internally for performance reasons and is not supposed to be directly referenced in consumer libraries.
*/
final class LazyUuidFromString implements UuidInterface
{
public const VALID_REGEX = '/\A[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\z/ms';
- /**
- * @var string
- * @psalm-var non-empty-string
- */
- private $uuid;
- /** @var UuidInterface|null */
- private $unwrapped;
- /** @psalm-param non-empty-string $uuid */
- public function __construct(string $uuid)
+ private ?UuidInterface $unwrapped = null;
+
+ /**
+ * @param non-empty-string $uuid
+ */
+ public function __construct(private string $uuid)
{
- $this->uuid = $uuid;
}
- /** @psalm-pure */
public static function fromBytes(string $bytes): self
{
$base16Uuid = bin2hex($bytes);
@@ -93,9 +84,7 @@ final class LazyUuidFromString implements UuidInterface
}
/**
- * @return array{string: string}
- *
- * @psalm-return array{string: non-empty-string}
+ * @return array{string: non-empty-string}
*/
public function __serialize(): array
{
@@ -105,19 +94,15 @@ final class LazyUuidFromString implements UuidInterface
/**
* {@inheritDoc}
*
- * @param string $serialized
- *
- * @psalm-param non-empty-string $serialized
+ * @param non-empty-string $data
*/
- public function unserialize($serialized): void
+ public function unserialize(string $data): void
{
- $this->uuid = $serialized;
+ $this->uuid = $data;
}
/**
- * @param array{string: string} $data
- *
- * @psalm-param array{string: non-empty-string} $data
+ * @param array{string?: non-empty-string} $data
*/
public function __unserialize(array $data): void
{
@@ -130,166 +115,125 @@ final class LazyUuidFromString implements UuidInterface
$this->unserialize($data['string']);
}
- /** @psalm-suppress DeprecatedMethod */
public function getNumberConverter(): NumberConverterInterface
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getNumberConverter();
+ return ($this->unwrapped ?? $this->unwrap())->getNumberConverter();
}
/**
- * {@inheritDoc}
- *
- * @psalm-suppress DeprecatedMethod
+ * @inheritDoc
*/
public function getFieldsHex(): array
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getFieldsHex();
+ return ($this->unwrapped ?? $this->unwrap())->getFieldsHex();
}
- /** @psalm-suppress DeprecatedMethod */
public function getClockSeqHiAndReservedHex(): string
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getClockSeqHiAndReservedHex();
+ return ($this->unwrapped ?? $this->unwrap())->getClockSeqHiAndReservedHex();
}
- /** @psalm-suppress DeprecatedMethod */
public function getClockSeqLowHex(): string
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getClockSeqLowHex();
+ return ($this->unwrapped ?? $this->unwrap())->getClockSeqLowHex();
}
- /** @psalm-suppress DeprecatedMethod */
public function getClockSequenceHex(): string
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getClockSequenceHex();
+ return ($this->unwrapped ?? $this->unwrap())->getClockSequenceHex();
}
- /** @psalm-suppress DeprecatedMethod */
public function getDateTime(): DateTimeInterface
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getDateTime();
+ return ($this->unwrapped ?? $this->unwrap())->getDateTime();
}
- /** @psalm-suppress DeprecatedMethod */
public function getLeastSignificantBitsHex(): string
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getLeastSignificantBitsHex();
+ return ($this->unwrapped ?? $this->unwrap())->getLeastSignificantBitsHex();
}
- /** @psalm-suppress DeprecatedMethod */
public function getMostSignificantBitsHex(): string
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getMostSignificantBitsHex();
+ return ($this->unwrapped ?? $this->unwrap())->getMostSignificantBitsHex();
}
- /** @psalm-suppress DeprecatedMethod */
public function getNodeHex(): string
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getNodeHex();
+ return ($this->unwrapped ?? $this->unwrap())->getNodeHex();
}
- /** @psalm-suppress DeprecatedMethod */
public function getTimeHiAndVersionHex(): string
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getTimeHiAndVersionHex();
+ return ($this->unwrapped ?? $this->unwrap())->getTimeHiAndVersionHex();
}
- /** @psalm-suppress DeprecatedMethod */
public function getTimeLowHex(): string
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getTimeLowHex();
+ return ($this->unwrapped ?? $this->unwrap())->getTimeLowHex();
}
- /** @psalm-suppress DeprecatedMethod */
public function getTimeMidHex(): string
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getTimeMidHex();
+ return ($this->unwrapped ?? $this->unwrap())->getTimeMidHex();
}
- /** @psalm-suppress DeprecatedMethod */
public function getTimestampHex(): string
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getTimestampHex();
+ return ($this->unwrapped ?? $this->unwrap())->getTimestampHex();
}
- /** @psalm-suppress DeprecatedMethod */
public function getUrn(): string
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getUrn();
+ return ($this->unwrapped ?? $this->unwrap())->getUrn();
}
- /** @psalm-suppress DeprecatedMethod */
public function getVariant(): ?int
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getVariant();
+ return ($this->unwrapped ?? $this->unwrap())->getVariant();
}
- /** @psalm-suppress DeprecatedMethod */
public function getVersion(): ?int
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getVersion();
+ return ($this->unwrapped ?? $this->unwrap())->getVersion();
}
public function compareTo(UuidInterface $other): int
{
- return ($this->unwrapped ?? $this->unwrap())
- ->compareTo($other);
+ return ($this->unwrapped ?? $this->unwrap())->compareTo($other);
}
public function equals(?object $other): bool
{
- if (! $other instanceof UuidInterface) {
+ if (!$other instanceof UuidInterface) {
return false;
}
return $this->uuid === $other->toString();
}
- /**
- * {@inheritDoc}
- *
- * @psalm-suppress MoreSpecificReturnType
- * @psalm-suppress LessSpecificReturnStatement we know that {@see self::$uuid} is a non-empty string, so
- * we know that {@see hex2bin} will retrieve a non-empty string too.
- */
public function getBytes(): string
{
- /** @phpstan-ignore-next-line PHPStan complains that this is not a non-empty-string. */
+ /**
+ * @var non-empty-string
+ * @phpstan-ignore possiblyImpure.functionCall, possiblyImpure.functionCall
+ */
return (string) hex2bin(str_replace('-', '', $this->uuid));
}
public function getFields(): FieldsInterface
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getFields();
+ return ($this->unwrapped ?? $this->unwrap())->getFields();
}
public function getHex(): Hexadecimal
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getHex();
+ return ($this->unwrapped ?? $this->unwrap())->getHex();
}
public function getInteger(): IntegerObject
{
- return ($this->unwrapped ?? $this->unwrap())
- ->getInteger();
+ return ($this->unwrapped ?? $this->unwrap())->getInteger();
}
public function toString(): string
@@ -308,232 +252,149 @@ final class LazyUuidFromString implements UuidInterface
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getClockSeqHiAndReserved()}
- * and use the arbitrary-precision math library of your choice to
- * convert it to a string integer.
- *
- * @psalm-suppress UndefinedInterfaceMethod
- * @psalm-suppress DeprecatedMethod
- * @psalm-suppress MixedArgument
- * @psalm-suppress MixedMethodCall
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
+ * {@see Rfc4122FieldsInterface} instance, you may call {@see Rfc4122FieldsInterface::getClockSeqHiAndReserved()}
+ * and use the arbitrary-precision math library of your choice to convert it to a string integer.
*/
public function getClockSeqHiAndReserved(): string
{
$instance = ($this->unwrapped ?? $this->unwrap());
- return $instance->getNumberConverter()
- ->fromHex(
- $instance->getFields()
- ->getClockSeqHiAndReserved()
- ->toString()
- );
+ $fields = $instance->getFields();
+ assert($fields instanceof \Ramsey\Uuid\Rfc4122\FieldsInterface);
+
+ return $instance->getNumberConverter()->fromHex($fields->getClockSeqHiAndReserved()->toString());
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getClockSeqLow()}
- * and use the arbitrary-precision math library of your choice to
- * convert it to a string integer.
- *
- * @psalm-suppress UndefinedInterfaceMethod
- * @psalm-suppress DeprecatedMethod
- * @psalm-suppress MixedArgument
- * @psalm-suppress MixedMethodCall
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
+ * {@see Rfc4122FieldsInterface} instance, you may call {@see Rfc4122FieldsInterface::getClockSeqLow()} and use
+ * the arbitrary-precision math library of your choice to convert it to a string integer.
*/
public function getClockSeqLow(): string
{
$instance = ($this->unwrapped ?? $this->unwrap());
- return $instance->getNumberConverter()
- ->fromHex(
- $instance->getFields()
- ->getClockSeqLow()
- ->toString()
- );
+ $fields = $instance->getFields();
+ assert($fields instanceof \Ramsey\Uuid\Rfc4122\FieldsInterface);
+
+ return $instance->getNumberConverter()->fromHex($fields->getClockSeqLow()->toString());
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getClockSeq()}
- * and use the arbitrary-precision math library of your choice to
- * convert it to a string integer.
- *
- * @psalm-suppress UndefinedInterfaceMethod
- * @psalm-suppress DeprecatedMethod
- * @psalm-suppress MixedArgument
- * @psalm-suppress MixedMethodCall
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
+ * {@see Rfc4122FieldsInterface} instance, you may call {@see Rfc4122FieldsInterface::getClockSeq()} and use the
+ * arbitrary-precision math library of your choice to convert it to a string integer.
*/
public function getClockSequence(): string
{
$instance = ($this->unwrapped ?? $this->unwrap());
- return $instance->getNumberConverter()
- ->fromHex(
- $instance->getFields()
- ->getClockSeq()
- ->toString()
- );
+ $fields = $instance->getFields();
+ assert($fields instanceof \Ramsey\Uuid\Rfc4122\FieldsInterface);
+
+ return $instance->getNumberConverter()->fromHex($fields->getClockSeq()->toString());
}
/**
- * @deprecated This method will be removed in 5.0.0. There is no direct
- * alternative, but the same information may be obtained by splitting
- * in half the value returned by {@see UuidInterface::getHex()}.
- *
- * @psalm-suppress UndefinedInterfaceMethod
- * @psalm-suppress DeprecatedMethod
- * @psalm-suppress MixedArgument
- * @psalm-suppress MixedMethodCall
+ * @deprecated This method will be removed in 5.0.0. There is no direct alternative, but the same information may be
+ * obtained by splitting in half the value returned by {@see UuidInterface::getHex()}.
*/
public function getLeastSignificantBits(): string
{
$instance = ($this->unwrapped ?? $this->unwrap());
- return $instance->getNumberConverter()
- ->fromHex(substr($instance->getHex()->toString(), 16));
+ return $instance->getNumberConverter()->fromHex(substr($instance->getHex()->toString(), 16));
}
/**
- * @deprecated This method will be removed in 5.0.0. There is no direct
- * alternative, but the same information may be obtained by splitting
- * in half the value returned by {@see UuidInterface::getHex()}.
- *
- * @psalm-suppress UndefinedInterfaceMethod
- * @psalm-suppress DeprecatedMethod
- * @psalm-suppress MixedArgument
- * @psalm-suppress MixedMethodCall
+ * @deprecated This method will be removed in 5.0.0. There is no direct alternative, but the same information may be
+ * obtained by splitting in half the value returned by {@see UuidInterface::getHex()}.
*/
public function getMostSignificantBits(): string
{
$instance = ($this->unwrapped ?? $this->unwrap());
- return $instance->getNumberConverter()
- ->fromHex(substr($instance->getHex()->toString(), 0, 16));
+ return $instance->getNumberConverter()->fromHex(substr($instance->getHex()->toString(), 0, 16));
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getNode()}
- * and use the arbitrary-precision math library of your choice to
- * convert it to a string integer.
- *
- * @psalm-suppress UndefinedInterfaceMethod
- * @psalm-suppress DeprecatedMethod
- * @psalm-suppress MixedArgument
- * @psalm-suppress MixedMethodCall
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
+ * {@see Rfc4122FieldsInterface} instance, you may call {@see Rfc4122FieldsInterface::getNode()} and use the
+ * arbitrary-precision math library of your choice to convert it to a string integer.
*/
public function getNode(): string
{
$instance = ($this->unwrapped ?? $this->unwrap());
- return $instance->getNumberConverter()
- ->fromHex(
- $instance->getFields()
- ->getNode()
- ->toString()
- );
+ $fields = $instance->getFields();
+ assert($fields instanceof \Ramsey\Uuid\Rfc4122\FieldsInterface);
+
+ return $instance->getNumberConverter()->fromHex($fields->getNode()->toString());
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getTimeHiAndVersion()}
- * and use the arbitrary-precision math library of your choice to
- * convert it to a string integer.
- *
- * @psalm-suppress UndefinedInterfaceMethod
- * @psalm-suppress DeprecatedMethod
- * @psalm-suppress MixedArgument
- * @psalm-suppress MixedMethodCall
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
+ * {@see Rfc4122FieldsInterface} instance, you may call {@see Rfc4122FieldsInterface::getTimeHiAndVersion()} and
+ * use the arbitrary-precision math library of your choice to convert it to a string integer.
*/
public function getTimeHiAndVersion(): string
{
$instance = ($this->unwrapped ?? $this->unwrap());
- return $instance->getNumberConverter()
- ->fromHex(
- $instance->getFields()
- ->getTimeHiAndVersion()
- ->toString()
- );
+ $fields = $instance->getFields();
+ assert($fields instanceof \Ramsey\Uuid\Rfc4122\FieldsInterface);
+
+ return $instance->getNumberConverter()->fromHex($fields->getTimeHiAndVersion()->toString());
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getTimeLow()}
- * and use the arbitrary-precision math library of your choice to
- * convert it to a string integer.
- *
- * @psalm-suppress UndefinedInterfaceMethod
- * @psalm-suppress DeprecatedMethod
- * @psalm-suppress MixedArgument
- * @psalm-suppress MixedMethodCall
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
+ * {@see Rfc4122FieldsInterface} instance, you may call {@see Rfc4122FieldsInterface::getTimeLow()} and use the
+ * arbitrary-precision math library of your choice to convert it to a string integer.
*/
public function getTimeLow(): string
{
$instance = ($this->unwrapped ?? $this->unwrap());
- return $instance->getNumberConverter()
- ->fromHex(
- $instance->getFields()
- ->getTimeLow()
- ->toString()
- );
+ $fields = $instance->getFields();
+ assert($fields instanceof \Ramsey\Uuid\Rfc4122\FieldsInterface);
+
+ return $instance->getNumberConverter()->fromHex($fields->getTimeLow()->toString());
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getTimeMid()}
- * and use the arbitrary-precision math library of your choice to
- * convert it to a string integer.
- *
- * @psalm-suppress UndefinedInterfaceMethod
- * @psalm-suppress DeprecatedMethod
- * @psalm-suppress MixedArgument
- * @psalm-suppress MixedMethodCall
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
+ * {@see Rfc4122FieldsInterface} instance, you may call {@see Rfc4122FieldsInterface::getTimeMid()} and use the
+ * arbitrary-precision math library of your choice to convert it to a string integer.
*/
public function getTimeMid(): string
{
$instance = ($this->unwrapped ?? $this->unwrap());
- return $instance->getNumberConverter()
- ->fromHex(
- $instance->getFields()
- ->getTimeMid()
- ->toString()
- );
+ $fields = $instance->getFields();
+ assert($fields instanceof \Ramsey\Uuid\Rfc4122\FieldsInterface);
+
+ return $instance->getNumberConverter()->fromHex($fields->getTimeMid()->toString());
}
/**
- * @deprecated Use {@see UuidInterface::getFields()} to get a
- * {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
- * instance, you may call {@see Rfc4122FieldsInterface::getTimestamp()}
- * and use the arbitrary-precision math library of your choice to
- * convert it to a string integer.
- *
- * @psalm-suppress UndefinedInterfaceMethod
- * @psalm-suppress DeprecatedMethod
- * @psalm-suppress MixedArgument
- * @psalm-suppress MixedMethodCall
+ * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
+ * {@see Rfc4122FieldsInterface} instance, you may call {@see Rfc4122FieldsInterface::getTimestamp()} and use
+ * the arbitrary-precision math library of your choice to convert it to a string integer.
*/
public function getTimestamp(): string
{
$instance = ($this->unwrapped ?? $this->unwrap());
+
$fields = $instance->getFields();
+ assert($fields instanceof \Ramsey\Uuid\Rfc4122\FieldsInterface);
if ($fields->getVersion() !== 1) {
throw new UnsupportedOperationException('Not a time-based UUID');
}
- return $instance->getNumberConverter()
- ->fromHex($fields->getTimestamp()->toString());
+ return $instance->getNumberConverter()->fromHex($fields->getTimestamp()->toString());
}
public function toUuidV1(): UuidV1
@@ -558,18 +419,8 @@ final class LazyUuidFromString implements UuidInterface
return $instance;
}
- /**
- * @psalm-suppress ImpureMethodCall the retrieval of the factory is a clear violation of purity here: this is a
- * known pitfall of the design of this library, where a value object contains
- * a mutable reference to a factory. We use a fixed factory here, so the violation
- * will not have real-world effects, as this object is only instantiated with the
- * default factory settings/features.
- * @psalm-suppress InaccessibleProperty property {@see $unwrapped} is used as a cache: we don't expose it to the
- * outside world, so we should be fine here.
- */
private function unwrap(): UuidInterface
{
- return $this->unwrapped = (new UuidFactory())
- ->fromString($this->uuid);
+ return $this->unwrapped = (new UuidFactory())->fromString($this->uuid);
}
}
diff --git a/vendor/ramsey/uuid/src/Math/BrickMathCalculator.php b/vendor/ramsey/uuid/src/Math/BrickMathCalculator.php
index f2d8678..649f580 100644
--- a/vendor/ramsey/uuid/src/Math/BrickMathCalculator.php
+++ b/vendor/ramsey/uuid/src/Math/BrickMathCalculator.php
@@ -27,7 +27,7 @@ use Ramsey\Uuid\Type\NumberInterface;
/**
* A calculator using the brick/math library for arbitrary-precision arithmetic
*
- * @psalm-immutable
+ * @immutable
*/
final class BrickMathCalculator implements CalculatorInterface
{
@@ -52,6 +52,7 @@ final class BrickMathCalculator implements CalculatorInterface
$sum = $sum->plus($addend->toString());
}
+ /** @phpstan-ignore possiblyImpure.new */
return new IntegerObject((string) $sum);
}
@@ -63,6 +64,7 @@ final class BrickMathCalculator implements CalculatorInterface
$difference = $difference->minus($subtrahend->toString());
}
+ /** @phpstan-ignore possiblyImpure.new */
return new IntegerObject((string) $difference);
}
@@ -74,6 +76,7 @@ final class BrickMathCalculator implements CalculatorInterface
$product = $product->multipliedBy($multiplier->toString());
}
+ /** @phpstan-ignore possiblyImpure.new */
return new IntegerObject((string) $product);
}
@@ -81,8 +84,9 @@ final class BrickMathCalculator implements CalculatorInterface
int $roundingMode,
int $scale,
NumberInterface $dividend,
- NumberInterface ...$divisors
+ NumberInterface ...$divisors,
): NumberInterface {
+ /** @phpstan-ignore possiblyImpure.methodCall */
$brickRounding = $this->getBrickRoundingMode($roundingMode);
$quotient = BigDecimal::of($dividend->toString());
@@ -92,15 +96,18 @@ final class BrickMathCalculator implements CalculatorInterface
}
if ($scale === 0) {
+ /** @phpstan-ignore possiblyImpure.new */
return new IntegerObject((string) $quotient->toBigInteger());
}
+ /** @phpstan-ignore possiblyImpure.new */
return new Decimal((string) $quotient);
}
public function fromBase(string $value, int $base): IntegerObject
{
try {
+ /** @phpstan-ignore possiblyImpure.new */
return new IntegerObject((string) BigInteger::fromBase($value, $base));
} catch (MathException | \InvalidArgumentException $exception) {
throw new InvalidArgumentException(
@@ -126,6 +133,7 @@ final class BrickMathCalculator implements CalculatorInterface
public function toHexadecimal(IntegerObject $value): Hexadecimal
{
+ /** @phpstan-ignore possiblyImpure.new */
return new Hexadecimal($this->toBase($value, 16));
}
@@ -136,9 +144,11 @@ final class BrickMathCalculator implements CalculatorInterface
/**
* Maps ramsey/uuid rounding modes to those used by brick/math
+ *
+ * @return BrickMathRounding::*
*/
- private function getBrickRoundingMode(int $roundingMode): int
+ private function getBrickRoundingMode(int $roundingMode)
{
- return self::ROUNDING_MODE_MAP[$roundingMode] ?? 0;
+ return self::ROUNDING_MODE_MAP[$roundingMode] ?? BrickMathRounding::UNNECESSARY;
}
}
diff --git a/vendor/ramsey/uuid/src/Math/CalculatorInterface.php b/vendor/ramsey/uuid/src/Math/CalculatorInterface.php
index f03645d..e6789a6 100644
--- a/vendor/ramsey/uuid/src/Math/CalculatorInterface.php
+++ b/vendor/ramsey/uuid/src/Math/CalculatorInterface.php
@@ -21,7 +21,7 @@ use Ramsey\Uuid\Type\NumberInterface;
/**
* A calculator performs arithmetic operations on numbers
*
- * @psalm-immutable
+ * @immutable
*/
interface CalculatorInterface
{
@@ -32,6 +32,8 @@ interface CalculatorInterface
* @param NumberInterface ...$addends The additional integers to a add to the augend
*
* @return NumberInterface The sum of all the parameters
+ *
+ * @pure
*/
public function add(NumberInterface $augend, NumberInterface ...$addends): NumberInterface;
@@ -42,6 +44,8 @@ interface CalculatorInterface
* @param NumberInterface ...$subtrahends The integers to subtract from the minuend
*
* @return NumberInterface The difference after subtracting all parameters
+ *
+ * @pure
*/
public function subtract(NumberInterface $minuend, NumberInterface ...$subtrahends): NumberInterface;
@@ -52,6 +56,8 @@ interface CalculatorInterface
* @param NumberInterface ...$multipliers The factors by which to multiply the multiplicand
*
* @return NumberInterface The product of multiplying all the provided parameters
+ *
+ * @pure
*/
public function multiply(NumberInterface $multiplicand, NumberInterface ...$multipliers): NumberInterface;
@@ -61,17 +67,18 @@ interface CalculatorInterface
* @param int $roundingMode The RoundingMode constant to use for this operation
* @param int $scale The scale to use for this operation
* @param NumberInterface $dividend The integer to be divided
- * @param NumberInterface ...$divisors The integers to divide $dividend by, in
- * the order in which the division operations should take place
- * (left-to-right)
+ * @param NumberInterface ...$divisors The integers to divide $dividend by, in the order in which the division
+ * operations should take place (left-to-right)
*
* @return NumberInterface The quotient of dividing the provided parameters left-to-right
+ *
+ * @pure
*/
public function divide(
int $roundingMode,
int $scale,
NumberInterface $dividend,
- NumberInterface ...$divisors
+ NumberInterface ...$divisors,
): NumberInterface;
/**
@@ -81,6 +88,8 @@ interface CalculatorInterface
* @param int $base The base to convert from (i.e., 2, 16, 32, etc.)
*
* @return IntegerObject The base-10 integer value of the converted value
+ *
+ * @pure
*/
public function fromBase(string $value, int $base): IntegerObject;
@@ -91,16 +100,22 @@ interface CalculatorInterface
* @param int $base The base to convert to (i.e., 2, 16, 32, etc.)
*
* @return string The value represented in the specified base
+ *
+ * @pure
*/
public function toBase(IntegerObject $value, int $base): string;
/**
* Converts an Integer instance to a Hexadecimal instance
+ *
+ * @pure
*/
public function toHexadecimal(IntegerObject $value): Hexadecimal;
/**
* Converts a Hexadecimal instance to an Integer instance
+ *
+ * @pure
*/
public function toInteger(Hexadecimal $value): IntegerObject;
}
diff --git a/vendor/ramsey/uuid/src/Math/RoundingMode.php b/vendor/ramsey/uuid/src/Math/RoundingMode.php
index e710270..1497aa6 100644
--- a/vendor/ramsey/uuid/src/Math/RoundingMode.php
+++ b/vendor/ramsey/uuid/src/Math/RoundingMode.php
@@ -31,19 +31,91 @@ declare(strict_types=1);
namespace Ramsey\Uuid\Math;
/**
- * Specifies a rounding behavior for numerical operations capable of discarding
- * precision.
+ * Specifies a rounding behavior for numerical operations capable of discarding precision.
*
- * Each rounding mode indicates how the least significant returned digit of a
- * rounded result is to be calculated. If fewer digits are returned than the
- * digits needed to represent the exact numerical result, the discarded digits
- * will be referred to as the discarded fraction regardless the digits'
- * contribution to the value of the number. In other words, considered as a
- * numerical value, the discarded fraction could have an absolute value greater
- * than one.
+ * Each rounding mode indicates how the least significant returned digit of a rounded result is to be calculated. If
+ * fewer digits are returned than the digits needed to represent the exact numerical result, the discarded digits will
+ * be referred to as the discarded fraction regardless of the digits' contribution to the value of the number. In other
+ * words, considered as a numerical value, the discarded fraction could have an absolute value greater than one.
*/
final class RoundingMode
{
+ /**
+ * Asserts that the requested operation has an exact result; hence no rounding is necessary.
+ */
+ public const UNNECESSARY = 0;
+
+ /**
+ * Rounds away from zero.
+ *
+ * Always increments the digit prior to a nonzero discarded fraction. Note that this rounding mode never decreases
+ * the magnitude of the calculated value.
+ */
+ public const UP = 1;
+
+ /**
+ * Rounds towards zero.
+ *
+ * Never increments the digit prior to a discarded fraction (i.e., truncates). Note that this rounding mode never
+ * increases the magnitude of the calculated value.
+ */
+ public const DOWN = 2;
+
+ /**
+ * Rounds towards positive infinity.
+ *
+ * If the result is positive, behaves as for UP; if negative, behaves as for DOWN. Note that this rounding mode
+ * never decreases the calculated value.
+ */
+ public const CEILING = 3;
+
+ /**
+ * Rounds towards negative infinity.
+ *
+ * If the result is positive, behave as for DOWN; if negative, behave as for UP. Note that this rounding mode never
+ * increases the calculated value.
+ */
+ public const FLOOR = 4;
+
+ /**
+ * Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round up.
+ *
+ * Behaves as for UP if the discarded fraction is >= 0.5; otherwise, behaves as for DOWN. Note that this is the
+ * rounding mode commonly taught at school.
+ */
+ public const HALF_UP = 5;
+
+ /**
+ * Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round down.
+ *
+ * Behaves as for UP if the discarded fraction is > 0.5; otherwise, behaves as for DOWN.
+ */
+ public const HALF_DOWN = 6;
+
+ /**
+ * Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round towards positive infinity.
+ *
+ * If the result is positive, behaves as for HALF_UP; if negative, behaves as for HALF_DOWN.
+ */
+ public const HALF_CEILING = 7;
+
+ /**
+ * Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round towards negative infinity.
+ *
+ * If the result is positive, behaves as for HALF_DOWN; if negative, behaves as for HALF_UP.
+ */
+ public const HALF_FLOOR = 8;
+
+ /**
+ * Rounds towards the "nearest neighbor" unless both neighbors are equidistant, in which case rounds towards the even neighbor.
+ *
+ * Behaves as for HALF_UP if the digit to the left of the discarded fraction is odd; behaves as for HALF_DOWN if it's even.
+ *
+ * Note that this is the rounding mode that statistically minimizes cumulative error when applied repeatedly over a
+ * sequence of calculations. It is sometimes known as "Banker's rounding", and is chiefly used in the USA.
+ */
+ public const HALF_EVEN = 9;
+
/**
* Private constructor. This class is not instantiable.
*
@@ -52,95 +124,4 @@ final class RoundingMode
private function __construct()
{
}
-
- /**
- * Asserts that the requested operation has an exact result, hence no
- * rounding is necessary.
- */
- public const UNNECESSARY = 0;
-
- /**
- * Rounds away from zero.
- *
- * Always increments the digit prior to a nonzero discarded fraction.
- * Note that this rounding mode never decreases the magnitude of the
- * calculated value.
- */
- public const UP = 1;
-
- /**
- * Rounds towards zero.
- *
- * Never increments the digit prior to a discarded fraction (i.e.,
- * truncates). Note that this rounding mode never increases the magnitude of
- * the calculated value.
- */
- public const DOWN = 2;
-
- /**
- * Rounds towards positive infinity.
- *
- * If the result is positive, behaves as for UP; if negative, behaves as for
- * DOWN. Note that this rounding mode never decreases the calculated value.
- */
- public const CEILING = 3;
-
- /**
- * Rounds towards negative infinity.
- *
- * If the result is positive, behave as for DOWN; if negative, behave as for
- * UP. Note that this rounding mode never increases the calculated value.
- */
- public const FLOOR = 4;
-
- /**
- * Rounds towards "nearest neighbor" unless both neighbors are equidistant,
- * in which case round up.
- *
- * Behaves as for UP if the discarded fraction is >= 0.5; otherwise, behaves
- * as for DOWN. Note that this is the rounding mode commonly taught at
- * school.
- */
- public const HALF_UP = 5;
-
- /**
- * Rounds towards "nearest neighbor" unless both neighbors are equidistant,
- * in which case round down.
- *
- * Behaves as for UP if the discarded fraction is > 0.5; otherwise, behaves
- * as for DOWN.
- */
- public const HALF_DOWN = 6;
-
- /**
- * Rounds towards "nearest neighbor" unless both neighbors are equidistant,
- * in which case round towards positive infinity.
- *
- * If the result is positive, behaves as for HALF_UP; if negative, behaves
- * as for HALF_DOWN.
- */
- public const HALF_CEILING = 7;
-
- /**
- * Rounds towards "nearest neighbor" unless both neighbors are equidistant,
- * in which case round towards negative infinity.
- *
- * If the result is positive, behaves as for HALF_DOWN; if negative, behaves
- * as for HALF_UP.
- */
- public const HALF_FLOOR = 8;
-
- /**
- * Rounds towards the "nearest neighbor" unless both neighbors are
- * equidistant, in which case rounds towards the even neighbor.
- *
- * Behaves as for HALF_UP if the digit to the left of the discarded fraction
- * is odd; behaves as for HALF_DOWN if it's even.
- *
- * Note that this is the rounding mode that statistically minimizes
- * cumulative error when applied repeatedly over a sequence of calculations.
- * It is sometimes known as "Banker's rounding", and is chiefly used in the
- * USA.
- */
- public const HALF_EVEN = 9;
}
diff --git a/vendor/ramsey/uuid/src/Nonstandard/Fields.php b/vendor/ramsey/uuid/src/Nonstandard/Fields.php
index 927bc6a..d309c9a 100644
--- a/vendor/ramsey/uuid/src/Nonstandard/Fields.php
+++ b/vendor/ramsey/uuid/src/Nonstandard/Fields.php
@@ -31,42 +31,32 @@ use function substr;
use const STR_PAD_LEFT;
/**
- * Nonstandard UUID fields do not conform to the RFC 4122 standard
+ * Nonstandard UUID fields do not conform to the RFC 9562 (formerly RFC 4122) standard
*
- * Since some systems may create nonstandard UUIDs, this implements the
- * Rfc4122\FieldsInterface, so that functionality of a nonstandard UUID is not
- * degraded, in the event these UUIDs are expected to contain RFC 4122 fields.
+ * Since some systems may create nonstandard UUIDs, this implements the {@see FieldsInterface}, so that functionality of
+ * a nonstandard UUID is not degraded, in the event these UUIDs are expected to contain RFC 9562 (formerly RFC 4122) fields.
*
- * Internally, this class represents the fields together as a 16-byte binary
- * string.
+ * Internally, this class represents the fields together as a 16-byte binary string.
*
- * @psalm-immutable
+ * @immutable
*/
final class Fields implements FieldsInterface
{
use SerializableFieldsTrait;
use VariantTrait;
- /**
- * @var string
- */
- private $bytes;
-
/**
* @param string $bytes A 16-byte binary string representation of a UUID
*
* @throws InvalidArgumentException if the byte string is not exactly 16 bytes
*/
- public function __construct(string $bytes)
+ public function __construct(private string $bytes)
{
- if (strlen($bytes) !== 16) {
+ if (strlen($this->bytes) !== 16) {
throw new InvalidArgumentException(
- 'The byte string must be 16 bytes long; '
- . 'received ' . strlen($bytes) . ' bytes'
+ 'The byte string must be 16 bytes long; received ' . strlen($this->bytes) . ' bytes',
);
}
-
- $this->bytes = $bytes;
}
public function getBytes(): string
@@ -130,4 +120,9 @@ final class Fields implements FieldsInterface
{
return false;
}
+
+ public function isMax(): bool
+ {
+ return false;
+ }
}
diff --git a/vendor/ramsey/uuid/src/Nonstandard/Uuid.php b/vendor/ramsey/uuid/src/Nonstandard/Uuid.php
index 715f825..7f15e6e 100644
--- a/vendor/ramsey/uuid/src/Nonstandard/Uuid.php
+++ b/vendor/ramsey/uuid/src/Nonstandard/Uuid.php
@@ -20,9 +20,10 @@ use Ramsey\Uuid\Converter\TimeConverterInterface;
use Ramsey\Uuid\Uuid as BaseUuid;
/**
- * Nonstandard\Uuid is a UUID that doesn't conform to RFC 4122
+ * Nonstandard\Uuid is a UUID that doesn't conform to RFC 9562 (formerly RFC 4122)
*
- * @psalm-immutable
+ * @immutable
+ * @pure
*/
final class Uuid extends BaseUuid
{
@@ -30,7 +31,7 @@ final class Uuid extends BaseUuid
Fields $fields,
NumberConverterInterface $numberConverter,
CodecInterface $codec,
- TimeConverterInterface $timeConverter
+ TimeConverterInterface $timeConverter,
) {
parent::__construct($fields, $numberConverter, $codec, $timeConverter);
}
diff --git a/vendor/ramsey/uuid/src/Nonstandard/UuidBuilder.php b/vendor/ramsey/uuid/src/Nonstandard/UuidBuilder.php
index 0c89277..74da992 100644
--- a/vendor/ramsey/uuid/src/Nonstandard/UuidBuilder.php
+++ b/vendor/ramsey/uuid/src/Nonstandard/UuidBuilder.php
@@ -25,32 +25,19 @@ use Throwable;
/**
* Nonstandard\UuidBuilder builds instances of Nonstandard\Uuid
*
- * @psalm-immutable
+ * @immutable
*/
class UuidBuilder implements UuidBuilderInterface
{
/**
- * @var NumberConverterInterface
- */
- private $numberConverter;
-
- /**
- * @var TimeConverterInterface
- */
- private $timeConverter;
-
- /**
- * @param NumberConverterInterface $numberConverter The number converter to
- * use when constructing the Nonstandard\Uuid
- * @param TimeConverterInterface $timeConverter The time converter to use
- * for converting timestamps extracted from a UUID to Unix timestamps
+ * @param NumberConverterInterface $numberConverter The number converter to use when constructing the Nonstandard\Uuid
+ * @param TimeConverterInterface $timeConverter The time converter to use for converting timestamps extracted from a
+ * UUID to Unix timestamps
*/
public function __construct(
- NumberConverterInterface $numberConverter,
- TimeConverterInterface $timeConverter
+ private NumberConverterInterface $numberConverter,
+ private TimeConverterInterface $timeConverter,
) {
- $this->numberConverter = $numberConverter;
- $this->timeConverter = $timeConverter;
}
/**
@@ -59,30 +46,29 @@ class UuidBuilder implements UuidBuilderInterface
* @param CodecInterface $codec The codec to use for building this instance
* @param string $bytes The byte string from which to construct a UUID
*
- * @return Uuid The Nonstandard\UuidBuilder returns an instance of
- * Nonstandard\Uuid
+ * @return Uuid The Nonstandard\UuidBuilder returns an instance of Nonstandard\Uuid
*
- * @psalm-pure
+ * @pure
*/
public function build(CodecInterface $codec, string $bytes): UuidInterface
{
try {
- return new Uuid(
- $this->buildFields($bytes),
- $this->numberConverter,
- $codec,
- $this->timeConverter
- );
+ /** @phpstan-ignore possiblyImpure.new */
+ return new Uuid($this->buildFields($bytes), $this->numberConverter, $codec, $this->timeConverter);
} catch (Throwable $e) {
+ /** @phpstan-ignore possiblyImpure.methodCall, possiblyImpure.methodCall */
throw new UnableToBuildUuidException($e->getMessage(), (int) $e->getCode(), $e);
}
}
/**
- * Proxy method to allow injecting a mock, for testing
+ * Proxy method to allow injecting a mock for testing
+ *
+ * @pure
*/
protected function buildFields(string $bytes): Fields
{
+ /** @phpstan-ignore possiblyImpure.new */
return new Fields($bytes);
}
}
diff --git a/vendor/ramsey/uuid/src/Nonstandard/UuidV6.php b/vendor/ramsey/uuid/src/Nonstandard/UuidV6.php
index 05586b3..e277afc 100644
--- a/vendor/ramsey/uuid/src/Nonstandard/UuidV6.php
+++ b/vendor/ramsey/uuid/src/Nonstandard/UuidV6.php
@@ -14,87 +14,57 @@ declare(strict_types=1);
namespace Ramsey\Uuid\Nonstandard;
-use DateTimeImmutable;
-use DateTimeInterface;
use Ramsey\Uuid\Codec\CodecInterface;
use Ramsey\Uuid\Converter\NumberConverterInterface;
use Ramsey\Uuid\Converter\TimeConverterInterface;
-use Ramsey\Uuid\Exception\DateTimeException;
use Ramsey\Uuid\Exception\InvalidArgumentException;
use Ramsey\Uuid\Lazy\LazyUuidFromString;
use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
+use Ramsey\Uuid\Rfc4122\TimeTrait;
use Ramsey\Uuid\Rfc4122\UuidInterface;
use Ramsey\Uuid\Rfc4122\UuidV1;
-use Ramsey\Uuid\Uuid;
-use Throwable;
-
-use function hex2bin;
-use function str_pad;
-use function substr;
-
-use const STR_PAD_LEFT;
+use Ramsey\Uuid\Uuid as BaseUuid;
/**
- * Ordered-time, or version 6, UUIDs include timestamp, clock sequence, and node
- * values that are combined into a 128-bit unsigned integer
+ * Reordered time, or version 6, UUIDs include timestamp, clock sequence, and node values that are combined into a
+ * 128-bit unsigned integer
+ *
+ * @deprecated Use {@see \Ramsey\Uuid\Rfc4122\UuidV6} instead.
*
* @link https://github.com/uuid6/uuid6-ietf-draft UUID version 6 IETF draft
* @link http://gh.peabody.io/uuidv6/ "Version 6" UUIDs
+ * @link https://www.rfc-editor.org/rfc/rfc9562#section-5.6 RFC 9562, 5.6. UUID Version 6
*
- * @psalm-immutable
+ * @immutable
*/
-final class UuidV6 extends Uuid implements UuidInterface
+class UuidV6 extends BaseUuid implements UuidInterface
{
+ use TimeTrait;
+
/**
- * Creates a version 6 (time-based) UUID
+ * Creates a version 6 (reordered Gregorian time) UUID
*
* @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID
- * @param NumberConverterInterface $numberConverter The number converter to use
- * for converting hex values to/from integers
- * @param CodecInterface $codec The codec to use when encoding or decoding
- * UUID strings
- * @param TimeConverterInterface $timeConverter The time converter to use
- * for converting timestamps extracted from a UUID to unix timestamps
+ * @param NumberConverterInterface $numberConverter The number converter to use for converting hex values to/from integers
+ * @param CodecInterface $codec The codec to use when encoding or decoding UUID strings
+ * @param TimeConverterInterface $timeConverter The time converter to use for converting timestamps extracted from a
+ * UUID to unix timestamps
*/
public function __construct(
Rfc4122FieldsInterface $fields,
NumberConverterInterface $numberConverter,
CodecInterface $codec,
- TimeConverterInterface $timeConverter
+ TimeConverterInterface $timeConverter,
) {
- if ($fields->getVersion() !== Uuid::UUID_TYPE_PEABODY) {
+ if ($fields->getVersion() !== BaseUuid::UUID_TYPE_REORDERED_TIME) {
throw new InvalidArgumentException(
- 'Fields used to create a UuidV6 must represent a '
- . 'version 6 (ordered-time) UUID'
+ 'Fields used to create a UuidV6 must represent a version 6 (reordered time) UUID',
);
}
parent::__construct($fields, $numberConverter, $codec, $timeConverter);
}
- /**
- * Returns a DateTimeInterface object representing the timestamp associated
- * with the UUID
- *
- * @return DateTimeImmutable A PHP DateTimeImmutable instance representing
- * the timestamp of a version 6 UUID
- */
- public function getDateTime(): DateTimeInterface
- {
- $time = $this->timeConverter->convertTime($this->fields->getTimestamp());
-
- try {
- return new DateTimeImmutable(
- '@'
- . $time->getSeconds()->toString()
- . '.'
- . str_pad($time->getMicroseconds()->toString(), 6, '0', STR_PAD_LEFT)
- );
- } catch (Throwable $e) {
- throw new DateTimeException($e->getMessage(), (int) $e->getCode(), $e);
- }
- }
-
/**
* Converts this UUID into an instance of a version 1 UUID
*/
@@ -108,7 +78,7 @@ final class UuidV6 extends Uuid implements UuidInterface
. substr($hex, 16);
/** @var LazyUuidFromString $uuid */
- $uuid = Uuid::fromBytes((string) hex2bin($hex));
+ $uuid = BaseUuid::fromBytes((string) hex2bin($hex));
return $uuid->toUuidV1();
}
@@ -116,7 +86,7 @@ final class UuidV6 extends Uuid implements UuidInterface
/**
* Converts a version 1 UUID into an instance of a version 6 UUID
*/
- public static function fromUuidV1(UuidV1 $uuidV1): UuidV6
+ public static function fromUuidV1(UuidV1 $uuidV1): \Ramsey\Uuid\Rfc4122\UuidV6
{
$hex = $uuidV1->getHex()->toString();
$hex = substr($hex, 13, 3)
@@ -126,7 +96,7 @@ final class UuidV6 extends Uuid implements UuidInterface
. substr($hex, 16);
/** @var LazyUuidFromString $uuid */
- $uuid = Uuid::fromBytes((string) hex2bin($hex));
+ $uuid = BaseUuid::fromBytes((string) hex2bin($hex));
return $uuid->toUuidV6();
}
diff --git a/vendor/ramsey/uuid/src/Provider/Dce/SystemDceSecurityProvider.php b/vendor/ramsey/uuid/src/Provider/Dce/SystemDceSecurityProvider.php
index 6d6240b..830ffdd 100644
--- a/vendor/ramsey/uuid/src/Provider/Dce/SystemDceSecurityProvider.php
+++ b/vendor/ramsey/uuid/src/Provider/Dce/SystemDceSecurityProvider.php
@@ -21,7 +21,6 @@ use Ramsey\Uuid\Type\Integer as IntegerObject;
use function escapeshellarg;
use function preg_split;
use function str_getcsv;
-use function strpos;
use function strrpos;
use function strtolower;
use function strtoupper;
@@ -42,6 +41,7 @@ class SystemDceSecurityProvider implements DceSecurityProviderInterface
*/
public function getUid(): IntegerObject
{
+ /** @var IntegerObject | int | float | string | null $uid */
static $uid = null;
if ($uid instanceof IntegerObject) {
@@ -54,9 +54,8 @@ class SystemDceSecurityProvider implements DceSecurityProviderInterface
if ($uid === '') {
throw new DceSecurityException(
- 'Unable to get a user identifier using the system DCE '
- . 'Security provider; please provide a custom identifier or '
- . 'use a different provider'
+ 'Unable to get a user identifier using the system DCE Security provider; please provide a custom '
+ . 'identifier or use a different provider',
);
}
@@ -72,6 +71,7 @@ class SystemDceSecurityProvider implements DceSecurityProviderInterface
*/
public function getGid(): IntegerObject
{
+ /** @var IntegerObject | int | float | string | null $gid */
static $gid = null;
if ($gid instanceof IntegerObject) {
@@ -84,9 +84,8 @@ class SystemDceSecurityProvider implements DceSecurityProviderInterface
if ($gid === '') {
throw new DceSecurityException(
- 'Unable to get a group identifier using the system DCE '
- . 'Security provider; please provide a custom identifier or '
- . 'use a different provider'
+ 'Unable to get a group identifier using the system DCE Security provider; please provide a custom '
+ . 'identifier or use a different provider',
);
}
@@ -104,15 +103,10 @@ class SystemDceSecurityProvider implements DceSecurityProviderInterface
return '';
}
- switch ($this->getOs()) {
- case 'WIN':
- return $this->getWindowsUid();
- case 'DAR':
- case 'FRE':
- case 'LIN':
- default:
- return trim((string) shell_exec('id -u'));
- }
+ return match ($this->getOs()) {
+ 'WIN' => $this->getWindowsUid(),
+ default => trim((string) shell_exec('id -u')),
+ };
}
/**
@@ -124,15 +118,10 @@ class SystemDceSecurityProvider implements DceSecurityProviderInterface
return '';
}
- switch ($this->getOs()) {
- case 'WIN':
- return $this->getWindowsGid();
- case 'DAR':
- case 'FRE':
- case 'LIN':
- default:
- return trim((string) shell_exec('id -g'));
- }
+ return match ($this->getOs()) {
+ 'WIN' => $this->getWindowsGid(),
+ default => trim((string) shell_exec('id -g')),
+ };
}
/**
@@ -140,9 +129,7 @@ class SystemDceSecurityProvider implements DceSecurityProviderInterface
*/
private function hasShellExec(): bool
{
- $disabledFunctions = strtolower((string) ini_get('disable_functions'));
-
- return strpos($disabledFunctions, 'shell_exec') === false;
+ return !str_contains(strtolower((string) ini_get('disable_functions')), 'shell_exec');
}
/**
@@ -150,23 +137,23 @@ class SystemDceSecurityProvider implements DceSecurityProviderInterface
*/
private function getOs(): string
{
- return strtoupper(substr(constant('PHP_OS'), 0, 3));
+ /** @var string $phpOs */
+ $phpOs = constant('PHP_OS');
+
+ return strtoupper(substr($phpOs, 0, 3));
}
/**
* Returns the user identifier for a user on a Windows system
*
- * Windows does not have the same concept as an effective POSIX UID for the
- * running script. Instead, each user is uniquely identified by an SID
- * (security identifier). The SID includes three 32-bit unsigned integers
- * that make up a unique domain identifier, followed by an RID (relative
- * identifier) that we will use as the UID. The primary caveat is that this
- * UID may not be unique to the system, since it is, instead, unique to the
- * domain.
+ * Windows does not have the same concept as an effective POSIX UID for the running script. Instead, each user is
+ * uniquely identified by an SID (security identifier). The SID includes three 32-bit unsigned integers that make up
+ * a unique domain identifier, followed by an RID (relative identifier) that we will use as the UID. The primary
+ * caveat is that this UID may not be unique to the system, since it is, instead, unique to the domain.
*
* @link https://www.lifewire.com/what-is-an-sid-number-2626005 What Is an SID Number?
- * @link https://bit.ly/30vE7NM Well-known SID Structures
- * @link https://bit.ly/2FWcYKJ Well-known security identifiers in Windows operating systems
+ * @link https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/81d92bba-d22b-4a8c-908a-554ab29148ab Well-known SID Structures
+ * @link https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/manage/understand-security-identifiers#well-known-sids Well-known SIDs
* @link https://www.windows-commandline.com/get-sid-of-user/ Get SID of user
*/
private function getWindowsUid(): string
@@ -177,7 +164,7 @@ class SystemDceSecurityProvider implements DceSecurityProviderInterface
return '';
}
- $sid = str_getcsv(trim((string) $response))[1] ?? '';
+ $sid = str_getcsv(trim((string) $response), escape: '\\')[1] ?? '';
if (($lastHyphen = strrpos($sid, '-')) === false) {
return '';
@@ -189,11 +176,10 @@ class SystemDceSecurityProvider implements DceSecurityProviderInterface
/**
* Returns a group identifier for a user on a Windows system
*
- * Since Windows does not have the same concept as an effective POSIX GID
- * for the running script, we will get the local group memberships for the
- * user running the script. Then, we will get the SID (security identifier)
- * for the first group that appears in that list. Finally, we will return
- * the RID (relative identifier) for the group and use that as the GID.
+ * Since Windows does not have the same concept as an effective POSIX GID for the running script, we will get the
+ * local group memberships for the user running the script. Then, we will get the SID (security identifier) for the
+ * first group that appears in that list. Finally, we will return the RID (relative identifier) for the group and
+ * use that as the GID.
*
* @link https://www.windows-commandline.com/list-of-user-groups-command-line/ List of user groups command line
*/
@@ -205,9 +191,7 @@ class SystemDceSecurityProvider implements DceSecurityProviderInterface
return '';
}
- /** @var string[] $userGroups */
$userGroups = preg_split('/\s{2,}/', (string) $response, -1, PREG_SPLIT_NO_EMPTY);
-
$firstGroup = trim($userGroups[1] ?? '', "* \t\n\r\0\x0B");
if ($firstGroup === '') {
@@ -220,15 +204,13 @@ class SystemDceSecurityProvider implements DceSecurityProviderInterface
return '';
}
- /** @var string[] $userGroup */
$userGroup = preg_split('/\s{2,}/', (string) $response, -1, PREG_SPLIT_NO_EMPTY);
-
$sid = $userGroup[1] ?? '';
if (($lastHyphen = strrpos($sid, '-')) === false) {
return '';
}
- return trim((string) substr($sid, $lastHyphen + 1));
+ return trim(substr($sid, $lastHyphen + 1));
}
}
diff --git a/vendor/ramsey/uuid/src/Provider/DceSecurityProviderInterface.php b/vendor/ramsey/uuid/src/Provider/DceSecurityProviderInterface.php
index 8325da6..f1c3e97 100644
--- a/vendor/ramsey/uuid/src/Provider/DceSecurityProviderInterface.php
+++ b/vendor/ramsey/uuid/src/Provider/DceSecurityProviderInterface.php
@@ -18,8 +18,7 @@ use Ramsey\Uuid\Rfc4122\UuidV2;
use Ramsey\Uuid\Type\Integer as IntegerObject;
/**
- * A DCE provider provides access to local domain identifiers for version 2,
- * DCE Security, UUIDs
+ * A DCE provider provides access to local domain identifiers for version 2, DCE Security, UUIDs
*
* @see UuidV2
*/
diff --git a/vendor/ramsey/uuid/src/Provider/Node/FallbackNodeProvider.php b/vendor/ramsey/uuid/src/Provider/Node/FallbackNodeProvider.php
index cad0104..267ea9b 100644
--- a/vendor/ramsey/uuid/src/Provider/Node/FallbackNodeProvider.php
+++ b/vendor/ramsey/uuid/src/Provider/Node/FallbackNodeProvider.php
@@ -19,29 +19,22 @@ use Ramsey\Uuid\Provider\NodeProviderInterface;
use Ramsey\Uuid\Type\Hexadecimal;
/**
- * FallbackNodeProvider retrieves the system node ID by stepping through a list
- * of providers until a node ID can be obtained
+ * FallbackNodeProvider retrieves the system node ID by stepping through a list of providers until a node ID can be obtained
*/
class FallbackNodeProvider implements NodeProviderInterface
{
/**
- * @var NodeProviderCollection
+ * @param iterable