diff --git a/brick/math/src/BigDecimal.php b/brick/math/src/BigDecimal.php index 31d22ab30..db8cf55e7 100644 --- a/brick/math/src/BigDecimal.php +++ b/brick/math/src/BigDecimal.php @@ -5,16 +5,43 @@ namespace Brick\Math; use Brick\Math\Exception\DivisionByZeroException; +use Brick\Math\Exception\InvalidArgumentException; use Brick\Math\Exception\MathException; use Brick\Math\Exception\NegativeNumberException; -use Brick\Math\Internal\Calculator; +use Brick\Math\Exception\RoundingNecessaryException; +use Brick\Math\Exception\UnsupportedPlatformException; +use Brick\Math\Internal\CalculatorRegistry; +use Brick\Math\Internal\DecimalHelper; +use Brick\Math\Internal\Safe; +use LogicException; +use Override; + +use function assert; +use function chr; +use function in_array; +use function ini_set; +use function intdiv; +use function is_infinite; +use function is_nan; +use function json_encode; +use function max; +use function pack; +use function rtrim; +use function str_repeat; +use function strlen; +use function substr; +use function unpack; + +use const PHP_INT_SIZE; /** - * Immutable, arbitrary-precision signed decimal numbers. + * An arbitrarily large decimal number. * - * @psalm-immutable + * This class is immutable. + * + * The scale of the number is the number of digits after the decimal point. It is always positive or zero. */ -final class BigDecimal extends BigNumber +final readonly class BigDecimal extends BigNumber { /** * The unscaled value of this decimal number. @@ -23,20 +50,24 @@ final class BigDecimal extends BigNumber * No leading zero must be present. * No leading minus sign must be present if the value is 0. */ - private readonly string $value; + private string $value; /** * The scale (number of digits after the decimal point) of this decimal number. * * This must be zero or more. + * + * @var non-negative-int */ - private readonly int $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. + * @param string $value The unscaled value, validated. + * @param non-negative-int $scale The scale, validated. + * + * @pure */ protected function __construct(string $value, int $scale = 0) { @@ -44,46 +75,45 @@ protected function __construct(string $value, int $scale = 0) $this->scale = $scale; } - /** - * @psalm-pure - */ - protected static function from(BigNumber $number): static - { - return $number->toBigDecimal(); - } - /** * Creates a BigDecimal from an unscaled value and a scale. * * 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. + * A negative scale is normalized to zero by appending zeros to the unscaled value. + * + * Example: `(12345, -3)` will result in the BigDecimal `12345000`. + * + * @param BigNumber|int|string $value The unscaled value. Must be convertible to a BigInteger. + * @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. * - * @throws \InvalidArgumentException If the scale is negative. + * @throws MathException If the value is not valid, or is not convertible to a BigInteger. * - * @psalm-pure + * @pure */ - public static function ofUnscaledValue(BigNumber|int|float|string $value, int $scale = 0) : BigDecimal + public static function ofUnscaledValue(BigNumber|int|string $value, int $scale = 0): BigDecimal { + $value = BigInteger::of($value)->toString(); + if ($scale < 0) { - throw new \InvalidArgumentException('The scale cannot be negative.'); + if ($value !== '0') { + $value .= str_repeat('0', Safe::neg($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. * - * @psalm-pure + * @pure */ - public static function zero() : BigDecimal + public static function zero(): BigDecimal { - /** - * @psalm-suppress ImpureStaticVariable - * @var BigDecimal|null $zero - */ + /** @var BigDecimal|null $zero */ static $zero; if ($zero === null) { @@ -96,14 +126,11 @@ public static function zero() : BigDecimal /** * Returns a BigDecimal representing one, with a scale of zero. * - * @psalm-pure + * @pure */ - public static function one() : BigDecimal + public static function one(): BigDecimal { - /** - * @psalm-suppress ImpureStaticVariable - * @var BigDecimal|null $one - */ + /** @var BigDecimal|null $one */ static $one; if ($one === null) { @@ -116,14 +143,11 @@ public static function one() : BigDecimal /** * Returns a BigDecimal representing ten, with a scale of zero. * - * @psalm-pure + * @pure */ - public static function ten() : BigDecimal + public static function ten(): BigDecimal { - /** - * @psalm-suppress ImpureStaticVariable - * @var BigDecimal|null $ten - */ + /** @var BigDecimal|null $ten */ static $ten; if ($ten === null) { @@ -133,31 +157,177 @@ public static function ten() : BigDecimal return $ten; } + /** + * Creates a BigDecimal from the exact IEEE-754 value of a float. + * + * Examples: + * - `fromFloatExact(0.1)` returns a BigDecimal with value '0.1000000000000000055511151231257827021181583404541015625' + * - `fromFloatExact(0.3)` returns a BigDecimal with value '0.299999999999999988897769753748434595763683319091796875' + * - `fromFloatExact(0.5)` returns a BigDecimal with value '0.5' + * - `fromFloatExact(1.0)` returns a BigDecimal with value '1' + * + * Note that BigDecimal has no concept of negative zero, so `-0.0` and `0.0` both convert to zero. + * + * @throws InvalidArgumentException If the value is NaN or infinite. + * @throws UnsupportedPlatformException If the platform uses a non-IEEE-754 double format. + * + * @pure + */ + public static function fromFloatExact(float $value): BigDecimal + { + if (is_nan($value)) { + throw InvalidArgumentException::cannotConvertFloat('NaN'); + } + if (is_infinite($value)) { + throw InvalidArgumentException::cannotConvertFloat($value > 0 ? 'INF' : '-INF'); + } + + if (pack('E', 1.0) !== "\x3f\xf0\x00\x00\x00\x00\x00\x00") { + throw UnsupportedPlatformException::unsupportedFloatFormat(); + } + + if (PHP_INT_SIZE >= 8) { + // 64-bit: extract the IEEE-754 bit pattern as a 64-bit integer. + /** @var array{1: int} $unpacked */ + $unpacked = unpack('J', pack('E', $value)); + $bits = $unpacked[1]; + + // Bits: [sign(1)|exp(11)|mantissa(52)] + $signBit = ($bits >> 63) & 1; + $expBits = ($bits >> 52) & 0x7FF; + $mantissa = $bits & 0xFFFFFFFFFFFFF; + + // Zero (covers both 0.0 and -0.0). + if ($expBits === 0 && $mantissa === 0) { + return BigDecimal::zero(); + } + + if ($expBits === 0) { + $significand = BigInteger::of($mantissa); + } else { + $significand = BigInteger::of(0x10000000000000 | $mantissa); + } + } else { + // 32-bit: extract the IEEE-754 bit pattern as 8 bytes. + $packed = pack('E', $value); + + // Get the first 16 bits as an integer. + /** @var array{1: int} $unpacked */ + $unpacked = unpack('n', $packed); + $high16 = $unpacked[1]; + + // Bits: [sign(1)|exp(11)|mantissa(4)] in header (bytes 0-1) + 48 bits of mantissa in bytes 2-7 + $signBit = ($high16 >> 15) & 1; + $expBits = ($high16 >> 4) & 0x7FF; + $mantissaBytes = chr($high16 & 0x0F) . substr($packed, 2); + + // Zero (covers both 0.0 and -0.0). + if ($expBits === 0 && $mantissaBytes === "\x00\x00\x00\x00\x00\x00\x00") { + return BigDecimal::zero(); + } + + $mantissa = BigInteger::fromBytes($mantissaBytes, false); + + if ($expBits === 0) { + $significand = $mantissa; + } else { + $significand = $mantissa->plus(BigInteger::of(1)->shiftedLeft(52)); + } + } + + if ($expBits === 0) { + // Subnormal: no implicit leading 1-bit; effective exponent = -1074. + $baseExp = -1074; + } else { + // Normal: biased exp - 1023 (bias) - 52 (mantissa shift) + $baseExp = $expBits - 1075; + } + + if ($baseExp >= 0) { + // Result is an integer: significand × 2^baseExp. + $unscaled = $significand->multipliedBy(BigInteger::of(2)->power($baseExp)); + $scale = 0; + } else { + // Fraction: significand × 5^|baseExp| / 10^|baseExp|. + // Multiplying by 5^n eliminates the 2-based denominator while keeping scale = n. + $absExp = -$baseExp; + $unscaled = $significand->multipliedBy(BigInteger::of(5)->power($absExp)); + $scale = $absExp; + } + + if ($signBit === 1) { + $unscaled = $unscaled->negated(); + } + + return BigDecimal::ofUnscaledValue($unscaled, $scale)->strippedOfTrailingZeros(); + } + + /** + * Creates a BigDecimal from the shortest decimal representation of a float that round-trips back to the same value. + * + * The result is the shortest BigDecimal that passes `BigDecimal::fromFloatShortest($f)->toFloat() === $f`. + * + * Examples: + * - `fromFloatShortest(0.3)` returns a BigDecimal with value '0.3' + * - `fromFloatShortest(0.1 * 3.0)` returns a BigDecimal with value '0.30000000000000004' (`0.1 * 3.0 !== 0.3`) + * - `fromFloatShortest(1.0 / 3.0)` returns a BigDecimal with value '0.3333333333333333' + * + * Note that BigDecimal has no concept of negative zero, so `-0.0` and `0.0` both convert to zero. + * + * @throws InvalidArgumentException If the value is NaN or infinite. + */ + public static function fromFloatShortest(float $value): BigDecimal + { + if (is_nan($value)) { + throw InvalidArgumentException::cannotConvertFloat('NaN'); + } + if (is_infinite($value)) { + throw InvalidArgumentException::cannotConvertFloat($value > 0 ? 'INF' : '-INF'); + } + + // json_encode() uses serialize_precision; precision -1 uses the shortest round-trip algorithm + $previousPrecision = ini_set('serialize_precision', '-1'); + + try { + $str = json_encode($value); + } finally { + if ($previousPrecision !== false) { + ini_set('serialize_precision', $previousPrecision); + } + } + + assert($str !== false); + + return BigDecimal::of($str)->strippedOfTrailingZeros(); + } + /** * Returns the sum of this number and the given one. * * The result has a scale of `max($this->scale, $that->scale)`. * - * @param BigNumber|int|float|string $that The number to add. Must be convertible to a BigDecimal. + * @param BigNumber|int|string $that The number to add. Must be convertible to a BigDecimal. * * @throws MathException If the number is not valid, or is not convertible to a BigDecimal. + * + * @pure */ - public function plus(BigNumber|int|float|string $that) : BigDecimal + public function plus(BigNumber|int|string $that): BigDecimal { $that = BigDecimal::of($that); - if ($that->value === '0' && $that->scale <= $this->scale) { + if ($that->isZero() && $that->scale <= $this->scale) { return $this; } - if ($this->value === '0' && $this->scale <= $that->scale) { + if ($this->isZero() && $this->scale <= $that->scale) { return $that; } [$a, $b] = $this->scaleValues($this, $that); - $value = Calculator::get()->add($a, $b); - $scale = $this->scale > $that->scale ? $this->scale : $that->scale; + $value = CalculatorRegistry::get()->add($a, $b); + $scale = max($this->scale, $that->scale); return new BigDecimal($value, $scale); } @@ -167,22 +337,28 @@ public function plus(BigNumber|int|float|string $that) : BigDecimal * * The result has a scale of `max($this->scale, $that->scale)`. * - * @param BigNumber|int|float|string $that The number to subtract. Must be convertible to a BigDecimal. + * @param BigNumber|int|string $that The number to subtract. Must be convertible to a BigDecimal. * * @throws MathException If the number is not valid, or is not convertible to a BigDecimal. + * + * @pure */ - public function minus(BigNumber|int|float|string $that) : BigDecimal + public function minus(BigNumber|int|string $that): BigDecimal { $that = BigDecimal::of($that); - if ($that->value === '0' && $that->scale <= $this->scale) { + if ($that->isZero() && $that->scale <= $this->scale) { return $this; } + if ($this->isZero() && $this->scale <= $that->scale) { + return $that->negated(); + } + [$a, $b] = $this->scaleValues($this, $that); - $value = Calculator::get()->sub($a, $b); - $scale = $this->scale > $that->scale ? $this->scale : $that->scale; + $value = CalculatorRegistry::get()->sub($a, $b); + $scale = max($this->scale, $that->scale); return new BigDecimal($value, $scale); } @@ -192,24 +368,32 @@ public function minus(BigNumber|int|float|string $that) : BigDecimal * * The result has a scale of `$this->scale + $that->scale`. * - * @param BigNumber|int|float|string $that The multiplier. Must be convertible to a BigDecimal. + * @param BigNumber|int|string $that The multiplier. Must be convertible to a BigDecimal. * - * @throws MathException If the multiplier is not a valid number, or is not convertible to a BigDecimal. + * @throws MathException If the multiplier is not valid, or is not convertible to a BigDecimal. + * + * @pure */ - public function multipliedBy(BigNumber|int|float|string $that) : BigDecimal + public function multipliedBy(BigNumber|int|string $that): BigDecimal { $that = BigDecimal::of($that); - if ($that->value === '1' && $that->scale === 0) { + if ($that->isOneScaleZero()) { return $this; } - if ($this->value === '1' && $this->scale === 0) { + if ($this->isOneScaleZero()) { return $that; } - $value = Calculator::get()->mul($this->value, $that->value); - $scale = $this->scale + $that->scale; + /** @var non-negative-int $scale */ + $scale = Safe::add($this->scale, $that->scale); + + if ($this->isZero() || $that->isZero()) { + return new BigDecimal('0', $scale); + } + + $value = CalculatorRegistry::get()->mul($this->value, $that->value); return new BigDecimal($value, $scale); } @@ -217,35 +401,52 @@ public function multipliedBy(BigNumber|int|float|string $that) : BigDecimal /** * Returns the result of the division of this number by the given one, at the given scale. * - * @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 RoundingMode $roundingMode An optional rounding mode, defaults to UNNECESSARY. + * @param BigNumber|int|string $that The divisor. Must be convertible to a BigDecimal. + * @param non-negative-int $scale The desired scale. Must be non-negative. + * @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. + * @throws MathException If the divisor is not valid, or is not convertible to a BigDecimal. + * @throws InvalidArgumentException If the scale is negative. + * @throws DivisionByZeroException If the divisor is zero. + * @throws RoundingNecessaryException If RoundingMode::Unnecessary is used and the result cannot be represented + * exactly at the given scale. + * + * @pure */ - public function dividedBy(BigNumber|int|float|string $that, ?int $scale = null, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal + public function dividedBy(BigNumber|int|string $that, int $scale, RoundingMode $roundingMode = RoundingMode::Unnecessary): BigDecimal { + if ($scale < 0) { // @phpstan-ignore smaller.alwaysFalse + throw InvalidArgumentException::negativeScale(); + } + $that = BigDecimal::of($that); if ($that->isZero()) { throw DivisionByZeroException::divisionByZero(); } - if ($scale === null) { - $scale = $this->scale; - } elseif ($scale < 0) { - throw new \InvalidArgumentException('Scale cannot be negative.'); - } - - if ($that->value === '1' && $that->scale === 0 && $scale === $this->scale) { + if ($that->isOneScaleZero() && $scale === $this->scale) { return $this; } - $p = $this->valueWithMinScale($that->scale + $scale); - $q = $that->valueWithMinScale($this->scale - $scale); + $p = $this->valueWithMinScale(Safe::add($that->scale, $scale)); + $q = $that->valueWithMinScale(Safe::sub($this->scale, $scale)); + + $calculator = CalculatorRegistry::get(); + $result = $calculator->divRound($p, $q, $roundingMode); + + if ($result === null) { + [$a, $b] = $this->scaleValues($this->abs(), $that->abs()); - $result = Calculator::get()->divRound($p, $q, $roundingMode); + $denominator = $calculator->divQ($b, $calculator->gcd($a, $b)); + $requiredScale = DecimalHelper::computeScaleFromReducedFractionDenominator($denominator); + + if ($requiredScale === null) { + throw RoundingNecessaryException::decimalDivisionNotExact(); + } + + throw RoundingNecessaryException::decimalDivisionScaleTooSmall(); + } return new BigDecimal($result, $scale); } @@ -255,40 +456,34 @@ public function dividedBy(BigNumber|int|float|string $that, ?int $scale = null, * * The scale of the result is automatically calculated to fit all the fraction digits. * - * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal. + * @param BigNumber|int|string $that The divisor. Must be convertible to a BigDecimal. * - * @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. + * @throws MathException If the divisor is not valid, or is not convertible to a BigDecimal. + * @throws DivisionByZeroException If the divisor is zero. + * @throws RoundingNecessaryException If the result yields an infinite number of digits. + * + * @pure */ - public function exactlyDividedBy(BigNumber|int|float|string $that) : BigDecimal + public function dividedByExact(BigNumber|int|string $that): BigDecimal { $that = BigDecimal::of($that); - if ($that->value === '0') { + if ($that->isZero()) { throw DivisionByZeroException::divisionByZero(); } - [, $b] = $this->scaleValues($this, $that); - - $d = \rtrim($b, '0'); - $scale = \strlen($b) - \strlen($d); + [$a, $b] = $this->scaleValues($this->abs(), $that->abs()); - $calculator = Calculator::get(); + $calculator = CalculatorRegistry::get(); - foreach ([5, 2] as $prime) { - for (;;) { - $lastDigit = (int) $d[-1]; + $denominator = $calculator->divQ($b, $calculator->gcd($a, $b)); + $scale = DecimalHelper::computeScaleFromReducedFractionDenominator($denominator); - if ($lastDigit % $prime !== 0) { - break; - } - - $d = $calculator->divQ($d, (string) $prime); - $scale++; - } + if ($scale === null) { + throw RoundingNecessaryException::decimalDivisionNotExact(); } - return $this->dividedBy($that, $scale)->stripTrailingZeros(); + return $this->dividedBy($that, $scale)->strippedOfTrailingZeros(); } /** @@ -296,9 +491,13 @@ public function exactlyDividedBy(BigNumber|int|float|string $that) : BigDecimal * * The result has a scale of `$this->scale * $exponent`. * - * @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000. + * @param non-negative-int $exponent + * + * @throws InvalidArgumentException If the exponent is negative. + * + * @pure */ - public function power(int $exponent) : BigDecimal + public function power(int $exponent): BigDecimal { if ($exponent === 0) { return BigDecimal::one(); @@ -308,15 +507,14 @@ public function power(int $exponent) : BigDecimal return $this; } - if ($exponent < 0 || $exponent > Calculator::MAX_POWER) { - throw new \InvalidArgumentException(\sprintf( - 'The exponent %d is not in the range 0 to %d.', - $exponent, - Calculator::MAX_POWER - )); + if ($exponent < 0) { // @phpstan-ignore smaller.alwaysFalse + throw InvalidArgumentException::negativeExponent(); } - return new BigDecimal(Calculator::get()->pow($this->value, $exponent), $this->scale * $exponent); + /** @var non-negative-int $scale */ + $scale = Safe::mul($this->scale, $exponent); + + return new BigDecimal(CalculatorRegistry::get()->pow($this->value, $exponent), $scale); } /** @@ -324,11 +522,21 @@ public function power(int $exponent) : BigDecimal * * The quotient has a scale of `0`. * - * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal. + * Examples: + * + * - `7.5` quotient `3` returns `2` + * - `7.5` quotient `-3` returns `-2` + * - `-7.5` quotient `3` returns `-2` + * - `-7.5` quotient `-3` returns `2` + * + * @param BigNumber|int|string $that The divisor. Must be convertible to a BigDecimal. * - * @throws MathException If the divisor is not a valid decimal number, or is zero. + * @throws MathException If the divisor is not valid, or is not convertible to a BigDecimal. + * @throws DivisionByZeroException If the divisor is zero. + * + * @pure */ - public function quotient(BigNumber|int|float|string $that) : BigDecimal + public function quotient(BigNumber|int|string $that): BigDecimal { $that = BigDecimal::of($that); @@ -339,7 +547,7 @@ public function quotient(BigNumber|int|float|string $that) : BigDecimal $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); } @@ -348,12 +556,23 @@ public function quotient(BigNumber|int|float|string $that) : BigDecimal * Returns the remainder of the division of this number by the given one. * * The remainder has a scale of `max($this->scale, $that->scale)`. + * The remainder, when non-zero, has the same sign as the dividend. + * + * Examples: + * + * - `7.5` remainder `3` returns `1.5` + * - `7.5` remainder `-3` returns `1.5` + * - `-7.5` remainder `3` returns `-1.5` + * - `-7.5` remainder `-3` returns `-1.5` + * + * @param BigNumber|int|string $that The divisor. Must be convertible to a BigDecimal. * - * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal. + * @throws MathException If the divisor is not valid, or is not convertible to a BigDecimal. + * @throws DivisionByZeroException If the divisor is zero. * - * @throws MathException If the divisor is not a valid decimal number, or is zero. + * @pure */ - public function remainder(BigNumber|int|float|string $that) : BigDecimal + public function remainder(BigNumber|int|string $that): BigDecimal { $that = BigDecimal::of($that); @@ -364,9 +583,9 @@ public function remainder(BigNumber|int|float|string $that) : BigDecimal $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; + $scale = max($this->scale, $that->scale); return new BigDecimal($remainder, $scale); } @@ -376,15 +595,23 @@ public function remainder(BigNumber|int|float|string $that) : BigDecimal * * The quotient has a scale of `0`, and 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. + * Examples: * - * @return BigDecimal[] An array containing the quotient and the remainder. + * - `7.5` quotientAndRemainder `3` returns [`2`, `1.5`] + * - `7.5` quotientAndRemainder `-3` returns [`-2`, `1.5`] + * - `-7.5` quotientAndRemainder `3` returns [`-2`, `-1.5`] + * - `-7.5` quotientAndRemainder `-3` returns [`2`, `-1.5`] * - * @psalm-return array{BigDecimal, BigDecimal} + * @param BigNumber|int|string $that The divisor. Must be convertible to a BigDecimal. * - * @throws MathException If the divisor is not a valid decimal number, or is zero. + * @return array{BigDecimal, BigDecimal} An array containing the quotient and the remainder. + * + * @throws MathException If the divisor is not valid, or is not convertible to a BigDecimal. + * @throws DivisionByZeroException If the divisor is zero. + * + * @pure */ - public function quotientAndRemainder(BigNumber|int|float|string $that) : array + public function quotientAndRemainder(BigNumber|int|string $that): array { $that = BigDecimal::of($that); @@ -395,9 +622,9 @@ public function quotientAndRemainder(BigNumber|int|float|string $that) : array $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; + $scale = max($this->scale, $that->scale); $quotient = new BigDecimal($quotient, 0); $remainder = new BigDecimal($remainder, $scale); @@ -406,81 +633,232 @@ public function quotientAndRemainder(BigNumber|int|float|string $that) : array } /** - * Returns the square root of this number, rounded down to the given number of decimals. + * Returns the square root of this number, rounded to the given scale according to the given rounding mode. + * + * @param non-negative-int $scale The target scale. Must be non-negative. + * @param RoundingMode $roundingMode An optional rounding mode, defaults to Unnecessary. * - * @throws \InvalidArgumentException If the scale is negative. - * @throws NegativeNumberException If this number is negative. + * @throws InvalidArgumentException If the scale is negative. + * @throws NegativeNumberException If this number is negative. + * @throws RoundingNecessaryException If RoundingMode::Unnecessary is used and the result cannot be represented + * exactly at the given scale. + * + * @pure */ - public function sqrt(int $scale) : BigDecimal + public function sqrt(int $scale, RoundingMode $roundingMode = RoundingMode::Unnecessary): BigDecimal { - if ($scale < 0) { - throw new \InvalidArgumentException('Scale cannot be negative.'); + if ($scale < 0) { // @phpstan-ignore smaller.alwaysFalse + throw InvalidArgumentException::negativeScale(); } - if ($this->value === '0') { + if ($this->isZero()) { return new BigDecimal('0', $scale); } - if ($this->value[0] === '-') { - throw new NegativeNumberException('Cannot calculate the square root of a negative number.'); + if ($this->isNegative()) { + throw NegativeNumberException::squareRootOfNegativeNumber(); } $value = $this->value; - $addDigits = 2 * $scale - $this->scale; - - if ($addDigits > 0) { - // add zeros - $value .= \str_repeat('0', $addDigits); - } elseif ($addDigits < 0) { - // trim digits - if (-$addDigits >= \strlen($this->value)) { - // requesting a scale too low, will always yield a zero result - return new BigDecimal('0', $scale); + $inputScale = $this->scale; + + if ($inputScale % 2 !== 0) { + $value .= '0'; + $inputScale = Safe::add($inputScale, 1); + } + + $calculator = CalculatorRegistry::get(); + + // Keep one extra digit for rounding. + $intermediateScale = Safe::add(max($scale, intdiv($inputScale, 2)), 1); + $value .= str_repeat('0', Safe::sub(Safe::mul(2, $intermediateScale), $inputScale)); + + $sqrt = $calculator->sqrt($value); + $isExact = $calculator->mul($sqrt, $sqrt) === $value; + + if (! $isExact) { + if ($roundingMode === RoundingMode::Unnecessary) { + throw RoundingNecessaryException::decimalSquareRootNotExact(); + } + + // Non-perfect-square sqrt is irrational, so the true value is strictly above this sqrt floor. + // Add one at the intermediate scale to guarantee Up/Ceiling round up at the target scale. + if (in_array($roundingMode, [RoundingMode::Up, RoundingMode::Ceiling], true)) { + $sqrt = $calculator->add($sqrt, '1'); } - $value = \substr($value, 0, $addDigits); + // Irrational sqrt cannot land exactly on a midpoint; treat tie-to-down modes as HalfUp. + elseif (in_array($roundingMode, [RoundingMode::HalfDown, RoundingMode::HalfEven, RoundingMode::HalfFloor], true)) { + $roundingMode = RoundingMode::HalfUp; + } } - $value = Calculator::get()->sqrt($value); + $scaled = DecimalHelper::scale($sqrt, $intermediateScale, $scale, $roundingMode); - return new BigDecimal($value, $scale); + if ($scaled === null) { + throw RoundingNecessaryException::decimalSquareRootScaleTooSmall(); + } + + return new BigDecimal($scaled, $scale); } /** - * Returns a copy of this BigDecimal with the decimal point moved $n places to the left. + * Returns the nth root of this number, rounded to the given scale according to the given rounding mode. + * + * For odd $n, the operation is defined for negative inputs: the sign is preserved and the + * magnitude of the root is |$this|^(1/$n). + * + * @param positive-int $n The root degree. Must be a strictly positive integer. + * @param non-negative-int $scale The target scale. Must be non-negative. + * @param RoundingMode $roundingMode An optional rounding mode, defaults to Unnecessary. + * + * @throws InvalidArgumentException If $n is less than 1 or $scale is negative. + * @throws NegativeNumberException If this number is negative and $n is even. + * @throws RoundingNecessaryException If RoundingMode::Unnecessary is used and the result cannot be represented + * exactly at the given scale. + * + * @pure */ - public function withPointMovedLeft(int $n) : BigDecimal + public function nthRoot(int $n, int $scale, RoundingMode $roundingMode = RoundingMode::Unnecessary): BigDecimal { - if ($n === 0) { + if ($n < 1) { // @phpstan-ignore smaller.alwaysFalse + throw InvalidArgumentException::nonPositiveNthRootDegree(); + } + + if ($scale < 0) { // @phpstan-ignore smaller.alwaysFalse + throw InvalidArgumentException::negativeScale(); + } + + $isNegative = $this->isNegative(); + + if ($isNegative && $n % 2 === 0) { + throw NegativeNumberException::nthRootOfNegativeNumber(); + } + + if ($n === 1) { + $scaled = DecimalHelper::scale($this->value, $this->scale, $scale, $roundingMode); + + if ($scaled === null) { + throw RoundingNecessaryException::decimalNthRootScaleTooSmall(); + } + + return new BigDecimal($scaled, $scale); + } + + if ($this->isZero()) { + return new BigDecimal('0', $scale); + } + + $value = $this->value; + $inputScale = $this->scale; + + // Pad inputScale up to a multiple of $n so the shift by n*intermediateScale lands cleanly. + $remainder = $inputScale % $n; + + if ($remainder !== 0) { + $padding = $n - $remainder; + $value .= str_repeat('0', $padding); + $inputScale = Safe::add($inputScale, $padding); + } + + $calculator = CalculatorRegistry::get(); + + // Keep one extra digit beyond the target scale for rounding. + $intermediateScale = Safe::add(max($scale, intdiv($inputScale, $n)), 1); + $value .= str_repeat('0', Safe::sub(Safe::mul($n, $intermediateScale), $inputScale)); + + $root = $calculator->nthRoot($value, $n); + $isExact = $calculator->pow($root, $n) === $value; + + if (! $isExact) { + if ($roundingMode === RoundingMode::Unnecessary) { + throw RoundingNecessaryException::decimalNthRootNotExact(); + } + + $isPositive = ! $isNegative; + + // Non-perfect-nth-power root is irrational, so the true value has strictly greater + // magnitude than this truncated root. For "round away from zero" modes, bump the + // integer root one step further from zero so the subsequent rescale rounds up. + if ( + $roundingMode === RoundingMode::Up + || ($roundingMode === RoundingMode::Ceiling && $isPositive) + || ($roundingMode === RoundingMode::Floor && ! $isPositive) + ) { + $root = $isPositive + ? $calculator->add($root, '1') + : $calculator->sub($root, '1'); + } + + // Irrational nth root cannot land on a midpoint. For any Half* mode, the "tie" case + // never occurs, so rewrite them all to HalfUp (round half away from zero), which is + // the mode whose away-from-zero direction matches the sign of the (strictly larger + // in magnitude) true value for both positive and negative inputs. + elseif (in_array($roundingMode, [ + RoundingMode::HalfDown, + RoundingMode::HalfEven, + RoundingMode::HalfFloor, + RoundingMode::HalfCeiling, + ], true)) { + $roundingMode = RoundingMode::HalfUp; + } + } + + $scaled = DecimalHelper::scale($root, $intermediateScale, $scale, $roundingMode); + + if ($scaled === null) { + throw RoundingNecessaryException::decimalNthRootScaleTooSmall(); + } + + return new BigDecimal($scaled, $scale); + } + + /** + * Returns a copy of this BigDecimal with the decimal point moved to the left by the given number of places. + * + * If $places is negative, the decimal point is moved to the right by the absolute value instead. + * + * @pure + */ + public function withPointMovedLeft(int $places): BigDecimal + { + if ($places === 0) { return $this; } - if ($n < 0) { - return $this->withPointMovedRight(-$n); + if ($places < 0) { + return $this->withPointMovedRight(Safe::neg($places)); } - return new BigDecimal($this->value, $this->scale + $n); + /** @var non-negative-int $scale */ + $scale = Safe::add($this->scale, $places); + + return new BigDecimal($this->value, $scale); } /** - * Returns a copy of this BigDecimal with the decimal point moved $n places to the right. + * Returns a copy of this BigDecimal with the decimal point moved to the right by the given number of places. + * + * If $places is negative, the decimal point is moved to the left by the absolute value instead. + * + * @pure */ - public function withPointMovedRight(int $n) : BigDecimal + public function withPointMovedRight(int $places): BigDecimal { - if ($n === 0) { + if ($places === 0) { return $this; } - if ($n < 0) { - return $this->withPointMovedLeft(-$n); + if ($places < 0) { + return $this->withPointMovedLeft(Safe::neg($places)); } $value = $this->value; - $scale = $this->scale - $n; + $scale = Safe::sub($this->scale, $places); if ($scale < 0) { if ($value !== '0') { - $value .= \str_repeat('0', -$scale); + $value .= str_repeat('0', Safe::neg($scale)); } $scale = 0; } @@ -490,20 +868,28 @@ public function withPointMovedRight(int $n) : BigDecimal /** * Returns a copy of this BigDecimal with any trailing zeros removed from the fractional part. + * + * Examples: + * + * - `1.200` returns `1.2` + * - `1.000` returns `1` + * - `100` returns `100` + * + * @pure */ - public function stripTrailingZeros() : BigDecimal + public function strippedOfTrailingZeros(): BigDecimal { if ($this->scale === 0) { return $this; } - $trimmedValue = \rtrim($this->value, '0'); + $trimmedValue = rtrim($this->value, '0'); if ($trimmedValue === '') { return BigDecimal::zero(); } - $trimmableZeros = \strlen($this->value) - \strlen($trimmedValue); + $trimmableZeros = strlen($this->value) - strlen($trimmedValue); if ($trimmableZeros === 0) { return $this; @@ -513,29 +899,22 @@ public function stripTrailingZeros() : BigDecimal $trimmableZeros = $this->scale; } - $value = \substr($this->value, 0, -$trimmableZeros); + $value = substr($this->value, 0, -$trimmableZeros); + + /** @var non-negative-int $scale */ $scale = $this->scale - $trimmableZeros; return new BigDecimal($value, $scale); } - /** - * Returns the absolute value of this number. - */ - public function abs() : BigDecimal - { - return $this->isNegative() ? $this->negated() : $this; - } - - /** - * Returns the negated value of this number. - */ - public function negated() : BigDecimal + #[Override] + public function negated(): static { - return new BigDecimal(Calculator::get()->neg($this->value), $this->scale); + return new BigDecimal(CalculatorRegistry::get()->neg($this->value), $this->scale); } - public function compareTo(BigNumber|int|float|string $that) : int + #[Override] + public function compareTo(BigNumber|int|string $that): int { $that = BigNumber::of($that); @@ -546,117 +925,202 @@ public function compareTo(BigNumber|int|float|string $that) : int 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); + return -$that->compareTo($this); } - public function getSign() : int + #[Override] + public function getSign(): int { return ($this->value === '0') ? 0 : (($this->value[0] === '-') ? -1 : 1); } - public function getUnscaledValue() : BigInteger + /** + * Returns the unscaled value of this decimal number. + * + * For example, the unscaled value of `123.456` is `123456`. + * + * @pure + */ + public function getUnscaledValue(): BigInteger { return self::newBigInteger($this->value); } - public function getScale() : int + /** + * Returns the scale of this decimal number. + * + * The scale is the number of digits after the decimal point. For example, the scale of `123.456` is `3`. + * + * @return non-negative-int + * + * @pure + */ + public function getScale(): int { return $this->scale; } /** - * Returns a string representing the integral part of this decimal number. + * Returns the number of significant digits in the number. * - * Example: `-123.456` => `-123`. + * This is the number of digits in the unscaled value of the number. + * The sign has no impact on the result. + * + * Examples: + * 0 => 1 + * 0.0 => 1 + * 123 => 3 + * 123.456 => 6 + * 0.00123 => 3 + * 0.0012300 => 5 + * + * @return positive-int + * + * @pure */ - public function getIntegralPart() : string + public function getPrecision(): int { - if ($this->scale === 0) { - return $this->value; - } - - $value = $this->getUnscaledValueWithLeadingZeros(); + $length = strlen($this->value); - return \substr($value, 0, -$this->scale); + /** @var positive-int */ + return ($this->value[0] === '-') ? $length - 1 : $length; } /** - * Returns a string representing the fractional part of this decimal number. + * Returns the integral part of this decimal number. * - * If the scale is zero, an empty string is returned. + * Examples: * - * Examples: `-123.456` => '456', `123` => ''. + * - `123.456` returns `123` + * - `-123.456` returns `-123` + * - `0.123` returns `0` + * - `-0.123` returns `0` + * + * The following identity holds: `$d->isEqualTo($d->getFractionalPart()->plus($d->getIntegralPart()))`. Note that in + * this identity, the operand order is significant: the reversed form throws when the fractional part is non-zero. + * + * @pure */ - public function getFractionalPart() : string + public function getIntegralPart(): BigInteger { if ($this->scale === 0) { - return ''; + return self::newBigInteger($this->value); } - $value = $this->getUnscaledValueWithLeadingZeros(); + $value = DecimalHelper::padUnscaledValue($this->value, $this->scale); + $integerPart = substr($value, 0, -$this->scale); + + if ($integerPart === '-0') { + $integerPart = '0'; + } - return \substr($value, -$this->scale); + return self::newBigInteger($integerPart); } /** - * Returns whether this decimal number has a non-zero fractional part. + * Returns the fractional part of this decimal number. + * + * Examples: + * + * - `123.456` returns `0.456` + * - `-123.456` returns `-0.456` + * - `123` returns `0` + * - `-123` returns `0` + * - `123.000` returns `0.000` + * + * The result always has the same scale as `$this`. + * + * The following identity holds: `$d->isEqualTo($d->getFractionalPart()->plus($d->getIntegralPart()))`. Note that in + * this identity, the operand order is significant: the reversed form throws when the fractional part is non-zero. + * + * @pure */ - public function hasNonZeroFractionalPart() : bool + public function getFractionalPart(): BigDecimal { - return $this->getFractionalPart() !== \str_repeat('0', $this->scale); + if ($this->scale === 0) { + return BigDecimal::zero(); + } + + return $this->minus($this->getIntegralPart()); } - public function toBigInteger() : BigInteger + #[Override] + public function toBigInteger(): BigInteger { - $zeroScaleDecimal = $this->scale === 0 ? $this : $this->dividedBy(1, 0); + $value = DecimalHelper::tryScaleExactly($this->value, $this->scale, 0); + + if ($value !== null) { + return self::newBigInteger($value); + } - return self::newBigInteger($zeroScaleDecimal->value); + throw RoundingNecessaryException::decimalNotConvertibleToInteger(); } - public function toBigDecimal() : BigDecimal + #[Override] + public function toBigDecimal(): BigDecimal { return $this; } - public function toBigRational() : BigRational + #[Override] + public function toBigRational(): BigRational { $numerator = self::newBigInteger($this->value); - $denominator = self::newBigInteger('1' . \str_repeat('0', $this->scale)); + $denominator = self::newBigInteger('1' . str_repeat('0', $this->scale)); - return self::newBigRational($numerator, $denominator, false); + return self::newBigRational($numerator, $denominator, false, true); } - public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal + #[Override] + public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::Unnecessary): BigDecimal { + if ($scale < 0) { // @phpstan-ignore smaller.alwaysFalse + throw InvalidArgumentException::negativeScale(); + } + if ($scale === $this->scale) { return $this; } - return $this->dividedBy(BigDecimal::one(), $scale, $roundingMode); + $value = DecimalHelper::scale($this->value, $this->scale, $scale, $roundingMode); + + if ($value === null) { + throw RoundingNecessaryException::decimalScaleTooSmall(); + } + + return new BigDecimal($value, $scale); } - public function toInt() : int + #[Override] + public function toInt(): int { return $this->toBigInteger()->toInt(); } - public function toFloat() : float + #[Override] + public function toFloat(): float { - return (float) (string) $this; + return (float) $this->toString(); } - public function __toString() : string + /** + * @return numeric-string + */ + #[Override] + public function toString(): string { if ($this->scale === 0) { + /** @var numeric-string */ return $this->value; } - $value = $this->getUnscaledValueWithLeadingZeros(); + $value = DecimalHelper::padUnscaledValue($this->value, $this->scale); - return \substr($value, 0, -$this->scale) . '.' . \substr($value, -$this->scale); + /** @phpstan-ignore return.type */ + return substr($value, 0, -$this->scale) . '.' . substr($value, -$this->scale); } /** @@ -664,7 +1128,7 @@ public function __toString() : string * * @internal * - * @return array{value: string, scale: int} + * @return array{value: string, scale: non-negative-int} */ public function __serialize(): array { @@ -675,80 +1139,69 @@ public function __serialize(): array * 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 + * @param array{value: string, scale: non-negative-int} $data * - * @throws \LogicException + * @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.'); + 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']; } + #[Override] + protected static function from(BigNumber $number): static + { + return $number->toBigDecimal(); + } + /** * Puts the internal values of the given decimal numbers on the same scale. * * @return array{string, string} The scaled integer values of $x and $y. + * + * @pure */ - private function scaleValues(BigDecimal $x, BigDecimal $y) : array + private function scaleValues(BigDecimal $x, BigDecimal $y): array { $a = $x->value; $b = $y->value; if ($b !== '0' && $x->scale > $y->scale) { - $b .= \str_repeat('0', $x->scale - $y->scale); + $b .= str_repeat('0', $x->scale - $y->scale); } elseif ($a !== '0' && $x->scale < $y->scale) { - $a .= \str_repeat('0', $y->scale - $x->scale); + $a .= str_repeat('0', $y->scale - $x->scale); } return [$a, $b]; } - private function valueWithMinScale(int $scale) : string + /** + * @pure + */ + private function valueWithMinScale(int $scale): string { $value = $this->value; if ($this->value !== '0' && $scale > $this->scale) { - $value .= \str_repeat('0', $scale - $this->scale); + $value .= str_repeat('0', $scale - $this->scale); } return $value; } /** - * Adds leading zeros if necessary to the unscaled value to represent the full decimal number. + * @pure */ - private function getUnscaledValueWithLeadingZeros() : string + private function isOneScaleZero(): bool { - $value = $this->value; - $targetLength = $this->scale + 1; - $negative = ($value[0] === '-'); - $length = \strlen($value); - - if ($negative) { - $length--; - } - - if ($length >= $targetLength) { - return $this->value; - } - - if ($negative) { - $value = \substr($value, 1); - } - - $value = \str_pad($value, $targetLength, '0', STR_PAD_LEFT); - - if ($negative) { - $value = '-' . $value; - } - - return $value; + return $this->value === '1' && $this->scale === 0; } } diff --git a/brick/math/src/BigInteger.php b/brick/math/src/BigInteger.php index 73dcc89a2..d70fc1ad8 100644 --- a/brick/math/src/BigInteger.php +++ b/brick/math/src/BigInteger.php @@ -6,20 +6,47 @@ use Brick\Math\Exception\DivisionByZeroException; use Brick\Math\Exception\IntegerOverflowException; +use Brick\Math\Exception\InvalidArgumentException; use Brick\Math\Exception\MathException; use Brick\Math\Exception\NegativeNumberException; +use Brick\Math\Exception\NoInverseException; use Brick\Math\Exception\NumberFormatException; +use Brick\Math\Exception\RandomSourceException; +use Brick\Math\Exception\RoundingNecessaryException; use Brick\Math\Internal\Calculator; +use Brick\Math\Internal\CalculatorRegistry; +use Brick\Math\Internal\Safe; +use LogicException; +use Override; +use Throwable; + +use function array_map; +use function assert; +use function bin2hex; +use function chr; +use function count_chars; +use function filter_var; +use function hex2bin; +use function in_array; +use function intdiv; +use function is_string; +use function ltrim; +use function ord; +use function preg_match; +use function preg_quote; +use function random_bytes; +use function str_repeat; +use function strlen; +use function substr; + +use const FILTER_VALIDATE_INT; /** - * An arbitrary-size integer. + * An arbitrarily large integer number. * - * 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 + * This class is immutable. */ -final class BigInteger extends BigNumber +final readonly class BigInteger extends BigNumber { /** * The value, as a string of digits with optional leading minus sign. @@ -27,26 +54,20 @@ final class BigInteger extends BigNumber * No leading zeros must be present. * No leading minus sign must be present if the number is zero. */ - private readonly string $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; } - /** - * @psalm-pure - */ - protected static function from(BigNumber $number): static - { - return $number->toBigInteger(); - } - /** * Creates a number from a string in a given base. * @@ -58,39 +79,41 @@ protected static function from(BigNumber $number): static * * For bases greater than 36, and/or custom alphabets, use the fromArbitraryBase() method. * - * @param string $number The number to convert, in the given base. - * @param int $base The base of the number, between 2 and 36. + * @param non-empty-string $number The number to convert, in the given base. + * @param int<2, 36> $base The base of the number, between 2 and 36. * - * @throws NumberFormatException If the number is empty, or contains invalid chars for the given base. - * @throws \InvalidArgumentException If the base is out of range. + * @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 + public static function fromBase(string $number, int $base): BigInteger { - if ($number === '') { - throw new NumberFormatException('The number cannot be empty.'); + if ($base < 2 || $base > 36) { // @phpstan-ignore smaller.alwaysFalse, greater.alwaysFalse, booleanOr.alwaysFalse + throw InvalidArgumentException::baseOutOfRange($base); } - if ($base < 2 || $base > 36) { - throw new \InvalidArgumentException(\sprintf('Base %d is not in range 2 to 36.', $base)); + if ($number === '') { // @phpstan-ignore identical.alwaysFalse + throw NumberFormatException::emptyNumber(); } + $originalNumber = $number; + if ($number[0] === '-') { $sign = '-'; - $number = \substr($number, 1); + $number = substr($number, 1); } elseif ($number[0] === '+') { $sign = ''; - $number = \substr($number, 1); + $number = substr($number, 1); } else { $sign = ''; } if ($number === '') { - throw new NumberFormatException('The number cannot be empty.'); + throw NumberFormatException::invalidFormat($originalNumber); } - $number = \ltrim($number, '0'); + $number = ltrim($number, '0'); if ($number === '') { // The result will be the same in any base, avoid further calculation. @@ -102,10 +125,10 @@ public static function fromBase(string $number, int $base) : BigInteger return new BigInteger($sign . '1'); } - $pattern = '/[^' . \substr(Calculator::ALPHABET, 0, $base) . ']/'; + $pattern = '/[^' . substr(Calculator::ALPHABET, 0, $base) . ']/i'; - if (\preg_match($pattern, \strtolower($number), $matches) === 1) { - throw new NumberFormatException(\sprintf('"%s" is not a valid character in base %d.', $matches[0], $base)); + if (preg_match($pattern, $number, $matches) === 1) { + throw NumberFormatException::charNotValidInBase($matches[0], $base); } if ($base === 10) { @@ -113,7 +136,7 @@ public static function fromBase(string $number, int $base) : BigInteger return new BigInteger($sign . $number); } - $result = Calculator::get()->fromBase($number, $base); + $result = CalculatorRegistry::get()->fromBase($number, $base); return new BigInteger($sign . $result); } @@ -121,35 +144,42 @@ public static function fromBase(string $number, int $base) : BigInteger /** * Parses a string containing an integer in an arbitrary base, using a custom alphabet. * - * Because this method accepts an alphabet with any character, including dash, it does not handle negative numbers. + * This method is byte-oriented: the alphabet is interpreted as a sequence of single-byte characters. + * Multibyte UTF-8 characters are not supported. + * + * Because this method accepts any single-byte character, including dash, it does not handle negative numbers. * - * @param string $number The number to parse. - * @param string $alphabet The alphabet, for example '01' for base 2, or '01234567' for base 8. + * @param non-empty-string $number The number to parse. + * @param non-empty-string $alphabet The alphabet, for example '01' for base 2, or '01234567' for base 8. * - * @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. + * @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, or contains duplicates. * - * @psalm-pure + * @pure */ - public static function fromArbitraryBase(string $number, string $alphabet) : BigInteger + public static function fromArbitraryBase(string $number, string $alphabet): BigInteger { - if ($number === '') { - throw new NumberFormatException('The number cannot be empty.'); + $base = strlen($alphabet); + + if ($base < 2) { + throw InvalidArgumentException::alphabetTooShort(); } - $base = \strlen($alphabet); + if (strlen(count_chars($alphabet, 3)) !== $base) { + throw InvalidArgumentException::duplicateCharsInAlphabet(); + } - if ($base < 2) { - throw new \InvalidArgumentException('The alphabet must contain at least 2 chars.'); + if ($number === '') { // @phpstan-ignore identical.alwaysFalse + throw NumberFormatException::emptyNumber(); } - $pattern = '/[^' . \preg_quote($alphabet, '/') . ']/'; + $pattern = '/[^' . preg_quote($alphabet, '/') . ']/'; - if (\preg_match($pattern, $number, $matches) === 1) { + if (preg_match($pattern, $number, $matches) === 1) { throw NumberFormatException::charNotInAlphabet($matches[0]); } - $number = Calculator::get()->fromArbitraryBase($number, $alphabet, $base); + $number = CalculatorRegistry::get()->fromArbitraryBase($number, $alphabet, $base); return new BigInteger($number); } @@ -165,29 +195,31 @@ public static function fromArbitraryBase(string $number, string $alphabet) : Big * * This method can be used to retrieve a number exported by `toBytes()`, as long as the `$signed` flags match. * - * @param string $value The byte string. - * @param bool $signed Whether to interpret as a signed number in two's-complement representation with a leading - * sign bit. + * @param non-empty-string $bytes The byte string. + * @param bool $signed Whether to interpret as a signed number in two's-complement representation with a leading + * sign bit. * * @throws NumberFormatException If the string is empty. + * + * @pure */ - public static function fromBytes(string $value, bool $signed = true) : BigInteger + public static function fromBytes(string $bytes, bool $signed = true): BigInteger { - if ($value === '') { - throw new NumberFormatException('The byte string must not be empty.'); + if ($bytes === '') { // @phpstan-ignore identical.alwaysFalse + throw NumberFormatException::emptyByteString(); } $twosComplement = false; if ($signed) { - $x = \ord($value[0]); + $x = ord($bytes[0]); if (($twosComplement = ($x >= 0x80))) { - $value = ~$value; + $bytes = ~$bytes; } } - $number = self::fromBase(\bin2hex($value), 16); + $number = self::fromBase(bin2hex($bytes), 16); if ($twosComplement) { return $number->plus(1)->negated(); @@ -197,78 +229,72 @@ public static function fromBytes(string $value, bool $signed = true) : BigIntege } /** - * Generates a pseudo-random number in the range 0 to 2^numBits - 1. + * Generates a pseudo-random number in the range 0 to 2^bitCount - 1. * * Using the default random bytes generator, this method is suitable for cryptographic use. * - * @psalm-param (callable(int): string)|null $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. + * @param non-negative-int $bitCount 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. + * @throws InvalidArgumentException If $bitCount is negative. + * @throws RandomSourceException If random byte generation fails. */ - public static function randomBits(int $numBits, ?callable $randomBytesGenerator = null) : BigInteger + public static function randomBits(int $bitCount, ?callable $randomBytesGenerator = null): BigInteger { - if ($numBits < 0) { - throw new \InvalidArgumentException('The number of bits cannot be negative.'); + if ($bitCount < 0) { // @phpstan-ignore smaller.alwaysFalse + throw InvalidArgumentException::negativeBitCount(); } - if ($numBits === 0) { + if ($bitCount === 0) { return BigInteger::zero(); } - if ($randomBytesGenerator === null) { - $randomBytesGenerator = random_bytes(...); - } - /** @var int<1, max> $byteLength */ - $byteLength = \intdiv($numBits - 1, 8) + 1; + $byteLength = intdiv($bitCount - 1, 8) + 1; - $extraBits = ($byteLength * 8 - $numBits); - $bitmask = \chr(0xFF >> $extraBits); + $extraBits = ($byteLength * 8 - $bitCount); + $bitmask = chr(0xFF >> $extraBits); - $randomBytes = $randomBytesGenerator($byteLength); + $randomBytes = self::randomBytes($byteLength, $randomBytesGenerator); $randomBytes[0] = $randomBytes[0] & $bitmask; return self::fromBytes($randomBytes, false); } /** - * Generates a pseudo-random number between `$min` and `$max`. + * Generates a pseudo-random number between `$min` and `$max`, inclusive. * * 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. + * @param BigNumber|int|string $min The lower bound. Must be convertible to a BigInteger. + * @param BigNumber|int|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`. + * @throws MathException If one of the parameters cannot be converted to a BigInteger. + * @throws InvalidArgumentException If `$min` is greater than `$max`. + * @throws RandomSourceException If random byte generation fails. */ public static function randomRange( - BigNumber|int|float|string $min, - BigNumber|int|float|string $max, - ?callable $randomBytesGenerator = null - ) : BigInteger { + BigNumber|int|string $min, + BigNumber|int|string $max, + ?callable $randomBytesGenerator = null, + ): BigInteger { $min = BigInteger::of($min); $max = BigInteger::of($max); if ($min->isGreaterThan($max)) { - throw new MathException('$min cannot be greater than $max.'); + throw InvalidArgumentException::minGreaterThanMax(); } if ($min->isEqualTo($max)) { return $min; } - $diff = $max->minus($min); + $diff = $max->minus($min); $bitLength = $diff->getBitLength(); // try until the number is in range (50% to 100% chance of success) @@ -282,14 +308,11 @@ public static function randomRange( /** * Returns a BigInteger representing zero. * - * @psalm-pure + * @pure */ - public static function zero() : BigInteger + public static function zero(): BigInteger { - /** - * @psalm-suppress ImpureStaticVariable - * @var BigInteger|null $zero - */ + /** @var BigInteger|null $zero */ static $zero; if ($zero === null) { @@ -302,14 +325,11 @@ public static function zero() : BigInteger /** * Returns a BigInteger representing one. * - * @psalm-pure + * @pure */ - public static function one() : BigInteger + public static function one(): BigInteger { - /** - * @psalm-suppress ImpureStaticVariable - * @var BigInteger|null $one - */ + /** @var BigInteger|null $one */ static $one; if ($one === null) { @@ -322,14 +342,11 @@ public static function one() : BigInteger /** * Returns a BigInteger representing ten. * - * @psalm-pure + * @pure */ - public static function ten() : BigInteger + public static function ten(): BigInteger { - /** - * @psalm-suppress ImpureStaticVariable - * @var BigInteger|null $ten - */ + /** @var BigInteger|null $ten */ static $ten; if ($ten === null) { @@ -339,9 +356,23 @@ public static function ten() : BigInteger return $ten; } - public static function gcdMultiple(BigInteger $a, BigInteger ...$n): BigInteger + /** + * Returns the greatest common divisor of the given numbers. + * + * The GCD is always positive, unless all numbers are zero, in which case it is zero. + * + * @param BigNumber|int|string $a The first number. Must be convertible to a BigInteger. + * @param BigNumber|int|string ...$n The additional numbers. Each number must be convertible to a BigInteger. + * + * @throws MathException If one of the parameters cannot be converted to a BigInteger. + * + * @pure + */ + public static function gcdAll(BigNumber|int|string $a, BigNumber|int|string ...$n): BigInteger { - $result = $a; + $result = BigInteger::of($a)->abs(); + + $n = array_map(BigInteger::of(...), $n); // @phpstan-ignore possiblyImpure.functionCall foreach ($n as $next) { $result = $result->gcd($next); @@ -354,26 +385,57 @@ public static function gcdMultiple(BigInteger $a, BigInteger ...$n): BigInteger return $result; } + /** + * Returns the least common multiple of the given numbers. + * + * The LCM is always positive, unless one of the numbers is zero, in which case it is zero. + * + * @param BigNumber|int|string $a The first number. Must be convertible to a BigInteger. + * @param BigNumber|int|string ...$n The additional numbers. Each number must be convertible to a BigInteger. + * + * @throws MathException If one of the parameters cannot be converted to a BigInteger. + * + * @pure + */ + public static function lcmAll(BigNumber|int|string $a, BigNumber|int|string ...$n): BigInteger + { + $result = BigInteger::of($a)->abs(); + + $n = array_map(BigInteger::of(...), $n); // @phpstan-ignore possiblyImpure.functionCall + + foreach ($n as $next) { + $result = $result->lcm($next); + + if ($result->isZero()) { + 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. + * @param BigNumber|int|string $that The number to add. Must be convertible to a BigInteger. * * @throws MathException If the number is not valid, or is not convertible to a BigInteger. + * + * @pure */ - public function plus(BigNumber|int|float|string $that) : BigInteger + public function plus(BigNumber|int|string $that): BigInteger { $that = BigInteger::of($that); - if ($that->value === '0') { + if ($that->isZero()) { return $this; } - if ($this->value === '0') { + if ($this->isZero()) { return $that; } - $value = Calculator::get()->add($this->value, $that->value); + $value = CalculatorRegistry::get()->add($this->value, $that->value); return new BigInteger($value); } @@ -381,19 +443,25 @@ public function plus(BigNumber|int|float|string $that) : BigInteger /** * Returns the difference of this number and the given one. * - * @param BigNumber|int|float|string $that The number to subtract. Must be convertible to a BigInteger. + * @param BigNumber|int|string $that The number to subtract. Must be convertible to a BigInteger. * * @throws MathException If the number is not valid, or is not convertible to a BigInteger. + * + * @pure */ - public function minus(BigNumber|int|float|string $that) : BigInteger + public function minus(BigNumber|int|string $that): BigInteger { $that = BigInteger::of($that); - if ($that->value === '0') { + if ($that->isZero()) { return $this; } - $value = Calculator::get()->sub($this->value, $that->value); + if ($this->isZero()) { + return $that->negated(); + } + + $value = CalculatorRegistry::get()->sub($this->value, $that->value); return new BigInteger($value); } @@ -401,23 +469,25 @@ public function minus(BigNumber|int|float|string $that) : BigInteger /** * Returns the product of this number and the given one. * - * @param BigNumber|int|float|string $that The multiplier. Must be convertible to a BigInteger. + * @param BigNumber|int|string $that The multiplier. Must be convertible to a BigInteger. * - * @throws MathException If the multiplier is not a valid number, or is not convertible to a BigInteger. + * @throws MathException If the multiplier is not valid, or is not convertible to a BigInteger. + * + * @pure */ - public function multipliedBy(BigNumber|int|float|string $that) : BigInteger + public function multipliedBy(BigNumber|int|string $that): BigInteger { $that = BigInteger::of($that); - if ($that->value === '1') { + if ($that->isOne()) { return $this; } - if ($this->value === '1') { + if ($this->isOne()) { return $that; } - $value = Calculator::get()->mul($this->value, $that->value); + $value = CalculatorRegistry::get()->mul($this->value, $that->value); return new BigInteger($value); } @@ -425,25 +495,36 @@ public function multipliedBy(BigNumber|int|float|string $that) : BigInteger /** * 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 RoundingMode $roundingMode An optional rounding mode, defaults to UNNECESSARY. + * @param BigNumber|int|string $that The divisor. Must be convertible to a BigInteger. + * @param RoundingMode $roundingMode An optional rounding mode, defaults to Unnecessary. + * + * @throws MathException If the divisor is not valid, or is not convertible to a BigInteger. + * @throws DivisionByZeroException If the divisor is zero. + * @throws RoundingNecessaryException If RoundingMode::Unnecessary is used and the remainder is not zero. * - * @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(BigNumber|int|float|string $that, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigInteger + public function dividedBy(BigNumber|int|string $that, RoundingMode $roundingMode = RoundingMode::Unnecessary): BigInteger { $that = BigInteger::of($that); - if ($that->value === '1') { + if ($that->isZero()) { + throw DivisionByZeroException::divisionByZero(); + } + + if ($that->isOne()) { return $this; } - if ($that->value === '0') { - throw DivisionByZeroException::divisionByZero(); + if ($that->isMinusOne()) { + return $this->negated(); } - $result = Calculator::get()->divRound($this->value, $that->value, $roundingMode); + $result = CalculatorRegistry::get()->divRound($this->value, $that->value, $roundingMode); + + if ($result === null) { + throw RoundingNecessaryException::integerDivisionNotExact(); + } return new BigInteger($result); } @@ -451,9 +532,13 @@ public function dividedBy(BigNumber|int|float|string $that, RoundingMode $roundi /** * Returns this number exponentiated to the given value. * - * @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000. + * @param non-negative-int $exponent + * + * @throws InvalidArgumentException If the exponent is negative. + * + * @pure */ - public function power(int $exponent) : BigInteger + public function power(int $exponent): BigInteger { if ($exponent === 0) { return BigInteger::one(); @@ -463,37 +548,47 @@ public function power(int $exponent) : BigInteger return $this; } - if ($exponent < 0 || $exponent > Calculator::MAX_POWER) { - throw new \InvalidArgumentException(\sprintf( - 'The exponent %d is not in the range 0 to %d.', - $exponent, - Calculator::MAX_POWER - )); + if ($exponent < 0) { // @phpstan-ignore smaller.alwaysFalse + throw InvalidArgumentException::negativeExponent(); } - return new BigInteger(Calculator::get()->pow($this->value, $exponent)); + return new BigInteger(CalculatorRegistry::get()->pow($this->value, $exponent)); } /** * Returns the quotient of the division of this number by the given one. * - * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger. + * Examples: + * + * - `7` quotient `3` returns `2` + * - `7` quotient `-3` returns `-2` + * - `-7` quotient `3` returns `-2` + * - `-7` quotient `-3` returns `2` * + * @param BigNumber|int|string $that The divisor. Must be convertible to a BigInteger. + * + * @throws MathException If the divisor is not valid, or is not convertible to a BigInteger. * @throws DivisionByZeroException If the divisor is zero. + * + * @pure */ - public function quotient(BigNumber|int|float|string $that) : BigInteger + public function quotient(BigNumber|int|string $that): BigInteger { $that = BigInteger::of($that); - if ($that->value === '1') { + if ($that->isZero()) { + throw DivisionByZeroException::divisionByZero(); + } + + if ($that->isOne()) { return $this; } - if ($that->value === '0') { - throw DivisionByZeroException::divisionByZero(); + if ($that->isMinusOne()) { + return $this->negated(); } - $quotient = Calculator::get()->divQ($this->value, $that->value); + $quotient = CalculatorRegistry::get()->divQ($this->value, $that->value); return new BigInteger($quotient); } @@ -503,23 +598,33 @@ public function quotient(BigNumber|int|float|string $that) : BigInteger * * The remainder, when non-zero, has the same sign as the dividend. * - * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger. + * Examples: * + * - `7` remainder `3` returns `1` + * - `7` remainder `-3` returns `1` + * - `-7` remainder `3` returns `-1` + * - `-7` remainder `-3` returns `-1` + * + * @param BigNumber|int|string $that The divisor. Must be convertible to a BigInteger. + * + * @throws MathException If the divisor is not valid, or is not convertible to a BigInteger. * @throws DivisionByZeroException If the divisor is zero. + * + * @pure */ - public function remainder(BigNumber|int|float|string $that) : BigInteger + public function remainder(BigNumber|int|string $that): BigInteger { $that = BigInteger::of($that); - if ($that->value === '1') { - return BigInteger::zero(); + if ($that->isZero()) { + throw DivisionByZeroException::divisionByZero(); } - if ($that->value === '0') { - throw DivisionByZeroException::divisionByZero(); + if ($that->isOne() || $that->isMinusOne()) { + return BigInteger::zero(); } - $remainder = Calculator::get()->divR($this->value, $that->value); + $remainder = CalculatorRegistry::get()->divR($this->value, $that->value); return new BigInteger($remainder); } @@ -527,81 +632,118 @@ public function remainder(BigNumber|int|float|string $that) : BigInteger /** * Returns the quotient and remainder of the division of this number by the given one. * - * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger. + * Examples: * - * @return BigInteger[] An array containing the quotient and the remainder. + * - `7` quotientAndRemainder `3` returns [`2`, `1`] + * - `7` quotientAndRemainder `-3` returns [`-2`, `1`] + * - `-7` quotientAndRemainder `3` returns [`-2`, `-1`] + * - `-7` quotientAndRemainder `-3` returns [`2`, `-1`] * - * @psalm-return array{BigInteger, BigInteger} + * @param BigNumber|int|string $that The divisor. Must be convertible to a BigInteger. * + * @return array{BigInteger, BigInteger} An array containing the quotient and the remainder. + * + * @throws MathException If the divisor is not valid, or is not convertible to a BigInteger. * @throws DivisionByZeroException If the divisor is zero. + * + * @pure */ - public function quotientAndRemainder(BigNumber|int|float|string $that) : array + public function quotientAndRemainder(BigNumber|int|string $that): array { $that = BigInteger::of($that); - if ($that->value === '0') { + if ($that->isZero()) { throw DivisionByZeroException::divisionByZero(); } - [$quotient, $remainder] = Calculator::get()->divQR($this->value, $that->value); + if ($that->isOne()) { + return [$this, BigInteger::zero()]; + } + + if ($that->isMinusOne()) { + return [$this->negated(), BigInteger::zero()]; + } + + [$quotient, $remainder] = CalculatorRegistry::get()->divQR($this->value, $that->value); return [ new BigInteger($quotient), - new BigInteger($remainder) + new BigInteger($remainder), ]; } /** - * Returns the modulo of this number and the given one. + * Returns this number modulo the given one. * - * The modulo operation yields the same result as the remainder operation when both operands are of the same sign, - * and may differ when signs are different. + * The result is always non-negative, and is the unique value `r` such that `0 <= r < m` + * and `this - r` is a multiple of `m`. * - * The result of the modulo operation, when non-zero, has the same sign as the divisor. + * This is also known as Euclidean modulo. Unlike `remainder()`, which can return negative values + * when the dividend is negative, `mod()` always returns a non-negative result. * - * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger. + * Examples: * - * @throws DivisionByZeroException If the divisor is zero. + * - `7` mod `3` returns `1` + * - `-7` mod `3` returns `2` + * + * @param BigNumber|int|string $modulus The modulus. Must be convertible to a BigInteger. + * + * @throws MathException If the modulus is not valid, or is not convertible to a BigInteger. + * @throws InvalidArgumentException If the modulus is negative. + * @throws DivisionByZeroException If the modulus is zero. + * + * @pure */ - public function mod(BigNumber|int|float|string $that) : BigInteger + public function mod(BigNumber|int|string $modulus): BigInteger { - $that = BigInteger::of($that); + $modulus = BigInteger::of($modulus); + + if ($modulus->isZero()) { + throw DivisionByZeroException::zeroModulus(); + } - if ($that->value === '0') { - throw DivisionByZeroException::modulusMustNotBeZero(); + if ($modulus->isNegative()) { + throw InvalidArgumentException::negativeModulus(); } - $value = Calculator::get()->mod($this->value, $that->value); + $value = CalculatorRegistry::get()->mod($this->value, $modulus->value); return new BigInteger($value); } /** - * Returns the modular multiplicative inverse of this BigInteger modulo $m. + * Returns the modular multiplicative inverse of this BigInteger modulo $modulus. + * + * @param BigNumber|int|string $modulus The modulus. Must be convertible to a 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). + * @throws MathException If the modulus is not valid, or is not convertible to a BigInteger. + * @throws InvalidArgumentException If the modulus is negative. + * @throws DivisionByZeroException If the modulus is zero. + * @throws NoInverseException 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 + public function modInverse(BigNumber|int|string $modulus): BigInteger { - if ($m->value === '0') { - throw DivisionByZeroException::modulusMustNotBeZero(); + $modulus = BigInteger::of($modulus); + + if ($modulus->isZero()) { + throw DivisionByZeroException::zeroModulus(); } - if ($m->isNegative()) { - throw new NegativeNumberException('Modulus must not be negative.'); + if ($modulus->isNegative()) { + throw InvalidArgumentException::negativeModulus(); } - if ($m->value === '1') { + if ($modulus->isOne()) { return BigInteger::zero(); } - $value = Calculator::get()->modInverse($this->value, $m->value); + $value = CalculatorRegistry::get()->modInverse($this->value, $modulus->value); if ($value === null) { - throw new MathException('Unable to compute the modInverse for the given modulus.'); + throw NoInverseException::noModularInverse(); } return new BigInteger($value); @@ -610,28 +752,35 @@ public function modInverse(BigInteger $m) : BigInteger /** * Returns this number raised into power with modulo. * - * This operation only works on positive numbers. + * This operation requires a non-negative exponent and a strictly positive modulus. * - * @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. + * @param BigNumber|int|string $exponent The exponent. Must be convertible to a BigInteger. + * @param BigNumber|int|string $modulus The modulus. Must be convertible to a BigInteger. * - * @throws NegativeNumberException If any of the operands is negative. - * @throws DivisionByZeroException If the modulus is zero. + * @throws MathException If the exponent or modulus is not valid, or is not convertible to a BigInteger. + * @throws InvalidArgumentException If the exponent or modulus is negative. + * @throws DivisionByZeroException If the modulus is zero. + * + * @pure */ - public function modPow(BigNumber|int|float|string $exp, BigNumber|int|float|string $mod) : BigInteger + public function modPow(BigNumber|int|string $exponent, BigNumber|int|string $modulus): BigInteger { - $exp = BigInteger::of($exp); - $mod = BigInteger::of($mod); + $exponent = BigInteger::of($exponent); + $modulus = BigInteger::of($modulus); - if ($this->isNegative() || $exp->isNegative() || $mod->isNegative()) { - throw new NegativeNumberException('The operands cannot be negative.'); + if ($modulus->isZero()) { + throw DivisionByZeroException::zeroModulus(); } - if ($mod->isZero()) { - throw DivisionByZeroException::modulusMustNotBeZero(); + if ($modulus->isNegative()) { + throw InvalidArgumentException::negativeModulus(); } - $result = Calculator::get()->modPow($this->value, $exp->value, $mod->value); + if ($exponent->isNegative()) { + throw InvalidArgumentException::negativeExponent(); + } + + $result = CalculatorRegistry::get()->modPow($this->value, $exponent->value, $modulus->value); return new BigInteger($result); } @@ -641,57 +790,200 @@ public function modPow(BigNumber|int|float|string $exp, BigNumber|int|float|stri * * The GCD is always positive, unless both operands are zero, in which case it is zero. * - * @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number. + * @param BigNumber|int|string $that The operand. Must be convertible to a BigInteger. + * + * @throws MathException If the operand is not valid, or is not convertible to a BigInteger. + * + * @pure */ - public function gcd(BigNumber|int|float|string $that) : BigInteger + public function gcd(BigNumber|int|string $that): BigInteger { $that = BigInteger::of($that); - if ($that->value === '0' && $this->value[0] !== '-') { - return $this; + if ($that->isZero()) { + return $this->abs(); } - if ($this->value === '0' && $that->value[0] !== '-') { - return $that; + if ($this->isZero()) { + return $that->abs(); } - $value = Calculator::get()->gcd($this->value, $that->value); + $value = CalculatorRegistry::get()->gcd($this->value, $that->value); return new BigInteger($value); } /** - * Returns the integer square root number of this number, rounded down. + * Returns the least common multiple of this number and the given one. + * + * The LCM is always positive, unless at least one operand is zero, in which case it is zero. + * + * @param BigNumber|int|string $that The operand. Must be convertible to a BigInteger. * - * The result is the largest x such that x² ≤ n. + * @throws MathException If the operand is not valid, or is not convertible to a BigInteger. * - * @throws NegativeNumberException If this number is negative. + * @pure */ - public function sqrt() : BigInteger + public function lcm(BigNumber|int|string $that): BigInteger { - if ($this->value[0] === '-') { - throw new NegativeNumberException('Cannot calculate the square root of a negative number.'); + $that = BigInteger::of($that); + + if ($this->isZero() || $that->isZero()) { + return BigInteger::zero(); } - $value = Calculator::get()->sqrt($this->value); + $value = CalculatorRegistry::get()->lcm($this->value, $that->value); return new BigInteger($value); } /** - * Returns the absolute value of this number. + * Returns the integer square root of this number, rounded according to the given rounding mode. + * + * @param RoundingMode $roundingMode An optional rounding mode, defaults to Unnecessary. + * + * @throws NegativeNumberException If this number is negative. + * @throws RoundingNecessaryException If RoundingMode::Unnecessary is used, and the number is not a perfect square. + * + * @pure */ - public function abs() : BigInteger + public function sqrt(RoundingMode $roundingMode = RoundingMode::Unnecessary): BigInteger { - return $this->isNegative() ? $this->negated() : $this; + if ($this->isNegative()) { + throw NegativeNumberException::squareRootOfNegativeNumber(); + } + + $calculator = CalculatorRegistry::get(); + + $sqrt = $calculator->sqrt($this->value); + + // For Down and Floor (equivalent for non-negative numbers), return floor sqrt + if ($roundingMode === RoundingMode::Down || $roundingMode === RoundingMode::Floor) { + return new BigInteger($sqrt); + } + + // Check if the sqrt is exact + $s2 = $calculator->mul($sqrt, $sqrt); + $remainder = $calculator->sub($this->value, $s2); + + if ($remainder === '0') { + // sqrt is exact + return new BigInteger($sqrt); + } + + // sqrt is not exact + if ($roundingMode === RoundingMode::Unnecessary) { + throw RoundingNecessaryException::integerSquareRootNotExact(); + } + + // For Up and Ceiling (equivalent for non-negative numbers), round up + if ($roundingMode === RoundingMode::Up || $roundingMode === RoundingMode::Ceiling) { + return new BigInteger($calculator->add($sqrt, '1')); + } + + // For Half* modes, compare our number to the midpoint of the interval [s², (s+1)²[. + // The midpoint is s² + s + 0.5. Comparing n >= s² + s + 0.5 with remainder = n − s² + // is equivalent to comparing 2*remainder >= 2*s + 1. + $twoRemainder = $calculator->mul($remainder, '2'); + $threshold = $calculator->add($calculator->mul($sqrt, '2'), '1'); + $cmp = $calculator->cmp($twoRemainder, $threshold); + + // We're supposed to increment (round up) when: + // - HalfUp, HalfCeiling => $cmp >= 0 + // - HalfDown, HalfFloor => $cmp > 0 + // - HalfEven => $cmp > 0 || ($cmp === 0 && $sqrt % 2 === 1) + // But 2*remainder is always even and 2*s + 1 is always odd, so $cmp is never zero. + // Therefore, all Half* modes simplify to: + if ($cmp > 0) { + $sqrt = $calculator->add($sqrt, '1'); + } + + return new BigInteger($sqrt); } /** - * Returns the inverse of this number. + * Returns the integer nth root of this number, rounded according to the given rounding mode. + * + * For odd $n, the operation is defined for negative inputs: the sign is preserved and the + * magnitude of the root is |$this|^(1/$n). + * + * @param positive-int $n The root degree. Must be a strictly positive integer. + * @param RoundingMode $roundingMode An optional rounding mode, defaults to Unnecessary. + * + * @throws InvalidArgumentException If $n is less than 1. + * @throws NegativeNumberException If this number is negative and $n is even. + * @throws RoundingNecessaryException If RoundingMode::Unnecessary is used, and this number is not a perfect nth power. + * + * @pure */ - public function negated() : BigInteger + public function nthRoot(int $n, RoundingMode $roundingMode = RoundingMode::Unnecessary): BigInteger + { + if ($n < 1) { // @phpstan-ignore smaller.alwaysFalse + throw InvalidArgumentException::nonPositiveNthRootDegree(); + } + + if ($n === 1) { + return $this; + } + + $isNegative = $this->isNegative(); + + if ($isNegative && $n % 2 === 0) { + throw NegativeNumberException::nthRootOfNegativeNumber(); + } + + $calculator = CalculatorRegistry::get(); + + // Truncation toward zero: for positive $this this is the floor root, for negative $this + // with odd $n this is the ceiling of the true root (i.e., the root of smaller magnitude). + $truncatedRoot = $calculator->nthRoot($this->value, $n); + $rootPow = $calculator->pow($truncatedRoot, $n); + + if ($rootPow === $this->value) { + return new BigInteger($truncatedRoot); + } + + if ($roundingMode === RoundingMode::Unnecessary) { + throw RoundingNecessaryException::integerNthRootNotExact(); + } + + $isPositive = ! $isNegative; + + // The next-step root is one unit further from zero than the truncated root. + $nextStep = $isPositive + ? $calculator->add($truncatedRoot, '1') + : $calculator->sub($truncatedRoot, '1'); + + if ($roundingMode === RoundingMode::Up) { + $increment = true; + } elseif ($roundingMode === RoundingMode::Down) { + $increment = false; + } elseif ($roundingMode === RoundingMode::Ceiling) { + $increment = $isPositive; + } elseif ($roundingMode === RoundingMode::Floor) { + $increment = ! $isPositive; + } else { + // Half* modes: increment iff |$this| > (|truncated| + 0.5)^n, equivalently + // 2^n * |$this| > (2*|truncated| + 1)^n. The rhs is odd while the lhs is even + // (n ≥ 2 here, so 2^n is even), so a midpoint tie is impossible and all five + // Half* modes collapse to the same comparison. + $absValue = $calculator->abs($this->value); + $absTruncated = $calculator->abs($truncatedRoot); + $twoAbsRootPlus1 = $calculator->add($calculator->mul($absTruncated, '2'), '1'); + + $lhs = $calculator->mul($calculator->pow('2', $n), $absValue); + $rhs = $calculator->pow($twoAbsRootPlus1, $n); + + $increment = $calculator->cmp($lhs, $rhs) > 0; + } + + return new BigInteger($increment ? $nextStep : $truncatedRoot); + } + + #[Override] + public function negated(): static { - return new BigInteger(Calculator::get()->neg($this->value)); + return new BigInteger(CalculatorRegistry::get()->neg($this->value)); } /** @@ -699,13 +991,17 @@ public function negated() : BigInteger * * This method returns a negative BigInteger if and only if both operands are negative. * - * @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number. + * @param BigNumber|int|string $that The operand. Must be convertible to a BigInteger. + * + * @throws MathException If the operand is not valid, or is not convertible to a BigInteger. + * + * @pure */ - public function and(BigNumber|int|float|string $that) : BigInteger + public function and(BigNumber|int|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)); } /** @@ -713,13 +1009,17 @@ public function and(BigNumber|int|float|string $that) : BigInteger * * This method returns a negative BigInteger if and only if either of the operands is negative. * - * @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number. + * @param BigNumber|int|string $that The operand. Must be convertible to a BigInteger. + * + * @throws MathException If the operand is not valid, or is not convertible to a BigInteger. + * + * @pure */ - public function or(BigNumber|int|float|string $that) : BigInteger + public function or(BigNumber|int|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)); } /** @@ -727,59 +1027,73 @@ public function or(BigNumber|int|float|string $that) : BigInteger * * This method returns a negative BigInteger if and only if exactly one of the operands is negative. * - * @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number. + * @param BigNumber|int|string $that The operand. Must be convertible to a BigInteger. + * + * @throws MathException If the operand is not valid, or is not convertible to a BigInteger. + * + * @pure */ - public function xor(BigNumber|int|float|string $that) : BigInteger + public function xor(BigNumber|int|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. + * + * @pure */ - public function not() : BigInteger + public function not(): BigInteger { return $this->negated()->minus(1); } /** * Returns the integer left shifted by a given number of bits. + * + * If $bits is negative, the integer is shifted right by the absolute value instead. + * + * @pure */ - public function shiftedLeft(int $distance) : BigInteger + public function shiftedLeft(int $bits): BigInteger { - if ($distance === 0) { + if ($bits === 0) { return $this; } - if ($distance < 0) { - return $this->shiftedRight(- $distance); + if ($bits < 0) { + return $this->shiftedRight(Safe::neg($bits)); } - return $this->multipliedBy(BigInteger::of(2)->power($distance)); + return $this->multipliedBy(BigInteger::of(2)->power($bits)); } /** * Returns the integer right shifted by a given number of bits. + * + * If $bits is negative, the integer is shifted left by the absolute value instead. + * + * @pure */ - public function shiftedRight(int $distance) : BigInteger + public function shiftedRight(int $bits): BigInteger { - if ($distance === 0) { + if ($bits === 0) { return $this; } - if ($distance < 0) { - return $this->shiftedLeft(- $distance); + if ($bits < 0) { + return $this->shiftedLeft(Safe::neg($bits)); } - $operand = BigInteger::of(2)->power($distance); + $operand = BigInteger::of(2)->power($bits); if ($this->isPositiveOrZero()) { return $this->quotient($operand); } - return $this->dividedBy($operand, RoundingMode::UP); + return $this->dividedBy($operand, RoundingMode::Up); } /** @@ -787,10 +1101,14 @@ public function shiftedRight(int $distance) : BigInteger * * 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 non-negative-int + * + * @pure */ - public function getBitLength() : int + public function getBitLength(): int { - if ($this->value === '0') { + if ($this->isZero()) { return 0; } @@ -798,15 +1116,19 @@ public function getBitLength() : int return $this->abs()->minus(1)->getBitLength(); } - return \strlen($this->toBase(2)); + return strlen($this->toBase(2)); } /** * Returns the index of the rightmost (lowest-order) one bit in this BigInteger. * - * Returns -1 if this BigInteger contains no one bits. + * Returns null if this BigInteger is zero. + * + * @return non-negative-int|null + * + * @pure */ - public function getLowestSetBit() : int + public function getLowestSetBit(): ?int { $n = $this; $bitLength = $this->getBitLength(); @@ -819,91 +1141,105 @@ public function getLowestSetBit() : int $n = $n->shiftedRight(1); } - return -1; + return null; } /** - * Returns whether this number is even. + * Returns true if and only if the designated bit is set. + * + * Computes ((this & (1<value[-1], ['0', '2', '4', '6', '8'], true); + if ($bitIndex < 0) { // @phpstan-ignore smaller.alwaysFalse + throw InvalidArgumentException::negativeBitIndex(); + } + + return $this->shiftedRight($bitIndex)->isOdd(); } /** - * Returns whether this number is odd. + * Returns whether this number is even. + * + * @pure */ - public function isOdd() : bool + public function isEven(): bool { - return \in_array($this->value[-1], ['1', '3', '5', '7', '9'], true); + return in_array($this->value[-1], ['0', '2', '4', '6', '8'], true); } /** - * Returns true if and only if the designated bit is set. - * - * Computes ((this & (1<shiftedRight($n)->isOdd(); + return in_array($this->value[-1], ['1', '3', '5', '7', '9'], true); } - public function compareTo(BigNumber|int|float|string $that) : int + #[Override] + public function compareTo(BigNumber|int|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); + return -$that->compareTo($this); } - public function getSign() : int + #[Override] + public function getSign(): int { return ($this->value === '0') ? 0 : (($this->value[0] === '-') ? -1 : 1); } - public function toBigInteger() : BigInteger + #[Override] + public function toBigInteger(): BigInteger { return $this; } - public function toBigDecimal() : BigDecimal + #[Override] + public function toBigDecimal(): BigDecimal { return self::newBigDecimal($this->value); } - public function toBigRational() : BigRational + #[Override] + public function toBigRational(): BigRational { - return self::newBigRational($this, BigInteger::one(), false); + return self::newBigRational($this, BigInteger::one(), false, false); } - public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal + #[Override] + public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::Unnecessary): BigDecimal { return $this->toBigDecimal()->toScale($scale, $roundingMode); } - public function toInt() : int + #[Override] + public function toInt(): int { - $intValue = (int) $this->value; + $intValue = filter_var($this->value, FILTER_VALIDATE_INT); - if ($this->value !== (string) $intValue) { - throw IntegerOverflowException::toIntOverflow($this); + if ($intValue === false) { + throw IntegerOverflowException::integerOutOfRange($this); } return $intValue; } - public function toFloat() : float + #[Override] + public function toFloat(): float { return (float) $this->value; } @@ -913,45 +1249,65 @@ public function toFloat() : float * * The output will always be lowercase for bases greater than 10. * - * @throws \InvalidArgumentException If the base is out of range. + * @param int<2, 36> $base + * + * @return non-empty-string + * + * @throws InvalidArgumentException If the base is out of range. + * + * @pure */ - public function toBase(int $base) : string + public function toBase(int $base): string { if ($base === 10) { + /** @var non-empty-string */ return $this->value; } - if ($base < 2 || $base > 36) { - throw new \InvalidArgumentException(\sprintf('Base %d is out of range [2, 36]', $base)); + if ($base < 2 || $base > 36) { // @phpstan-ignore smaller.alwaysFalse, greater.alwaysFalse, booleanOr.alwaysFalse + throw InvalidArgumentException::baseOutOfRange($base); } - return Calculator::get()->toBase($this->value, $base); + /** @var non-empty-string */ + return CalculatorRegistry::get()->toBase($this->value, $base); } /** * Returns a string representation of this number in an arbitrary base with a custom alphabet. * - * Because this method accepts an alphabet with any character, including dash, it does not handle negative numbers; + * This method is byte-oriented: the alphabet is interpreted as a sequence of single-byte characters. + * Multibyte UTF-8 characters are not supported. + * + * Because this method accepts any single-byte character, including dash, it does not handle negative numbers; * a NegativeNumberException will be thrown when attempting to call this method on a negative number. * - * @param string $alphabet The alphabet, for example '01' for base 2, or '01234567' for base 8. + * @param non-empty-string $alphabet The alphabet, for example '01' for base 2, or '01234567' for base 8. * - * @throws NegativeNumberException If this number is negative. - * @throws \InvalidArgumentException If the given alphabet does not contain at least 2 chars. + * @return non-empty-string + * + * @throws InvalidArgumentException If the alphabet does not contain at least 2 chars, or contains duplicates. + * @throws NegativeNumberException If this number is negative. + * + * @pure */ - public function toArbitraryBase(string $alphabet) : string + public function toArbitraryBase(string $alphabet): string { - $base = \strlen($alphabet); + $base = strlen($alphabet); if ($base < 2) { - throw new \InvalidArgumentException('The alphabet must contain at least 2 chars.'); + throw InvalidArgumentException::alphabetTooShort(); } - if ($this->value[0] === '-') { - throw new NegativeNumberException(__FUNCTION__ . '() does not support negative numbers.'); + if (strlen(count_chars($alphabet, 3)) !== $base) { + throw InvalidArgumentException::duplicateCharsInAlphabet(); } - return Calculator::get()->toArbitraryBase($this->value, $alphabet, $base); + if ($this->isNegative()) { + throw NegativeNumberException::toArbitraryBaseOfNegativeNumber(); + } + + /** @var non-empty-string */ + return CalculatorRegistry::get()->toArbitraryBase($this->value, $alphabet, $base); } /** @@ -970,34 +1326,39 @@ public function toArbitraryBase(string $alphabet) : string * * @param bool $signed Whether to output a signed number in two's-complement representation with a leading sign bit. * + * @return non-empty-string + * * @throws NegativeNumberException If $signed is false, and the number is negative. + * + * @pure */ - public function toBytes(bool $signed = true) : string + public function toBytes(bool $signed = true): string { if (! $signed && $this->isNegative()) { - throw new NegativeNumberException('Cannot convert a negative number to a byte string when $signed is false.'); + throw NegativeNumberException::unsignedBytesOfNegativeNumber(); } $hex = $this->abs()->toBase(16); - if (\strlen($hex) % 2 !== 0) { + if (strlen($hex) % 2 !== 0) { $hex = '0' . $hex; } - $baseHexLength = \strlen($hex); + $baseHexLength = strlen($hex); if ($signed) { if ($this->isNegative()) { - $bin = \hex2bin($hex); + $bin = hex2bin($hex); assert($bin !== false); - $hex = \bin2hex(~$bin); + /** @var non-empty-string $hex */ + $hex = bin2hex(~$bin); $hex = self::fromBase($hex, 16)->plus(1)->toBase(16); - $hexLength = \strlen($hex); + $hexLength = strlen($hex); if ($hexLength < $baseHexLength) { - $hex = \str_repeat('0', $baseHexLength - $hexLength) . $hex; + $hex = str_repeat('0', $baseHexLength - $hexLength) . $hex; } if ($hex[0] < '8') { @@ -1010,11 +1371,20 @@ public function toBytes(bool $signed = true) : string } } - return \hex2bin($hex); + $result = hex2bin($hex); + assert($result !== false); + + /** @var non-empty-string */ + return $result; } - public function __toString() : string + /** + * @return numeric-string + */ + #[Override] + public function toString(): string { + /** @var numeric-string */ return $this->value; } @@ -1034,18 +1404,73 @@ public function __serialize(): array * This method is only here to allow unserializing the object and cannot be accessed directly. * * @internal - * @psalm-suppress RedundantPropertyInitializationCheck * * @param array{value: string} $data * - * @throws \LogicException + * @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.'); + throw new LogicException('__unserialize() is an internal function, it must not be called directly.'); } + /** @phpstan-ignore deadCode.unreachable */ $this->value = $data['value']; } + + #[Override] + protected static function from(BigNumber $number): static + { + return $number->toBigInteger(); + } + + /** + * Returns random bytes from the provided generator or from random_bytes(). + * + * @param int $byteLength The number of requested bytes. + * @param (callable(int): string)|null $randomBytesGenerator The random bytes generator, or null to use random_bytes(). + * + * @throws RandomSourceException If random byte generation fails. + */ + private static function randomBytes(int $byteLength, ?callable $randomBytesGenerator): string + { + if ($randomBytesGenerator === null) { + $randomBytesGenerator = random_bytes(...); + } + + try { + $randomBytes = $randomBytesGenerator($byteLength); + } catch (Throwable $e) { + throw RandomSourceException::randomSourceFailure($e); + } + + /** @phpstan-ignore function.alreadyNarrowedType (Defensive runtime check for user-provided callbacks) */ + if (! is_string($randomBytes)) { + throw RandomSourceException::invalidRandomBytesType($randomBytes); + } + + if (strlen($randomBytes) !== $byteLength) { + throw RandomSourceException::invalidRandomBytesLength($byteLength, strlen($randomBytes)); + } + + return $randomBytes; + } + + /** + * @pure + */ + private function isOne(): bool + { + return $this->value === '1'; + } + + /** + * @pure + */ + private function isMinusOne(): bool + { + return $this->value === '-1'; + } } diff --git a/brick/math/src/BigNumber.php b/brick/math/src/BigNumber.php index 5a0df7837..9e472daed 100644 --- a/brick/math/src/BigNumber.php +++ b/brick/math/src/BigNumber.php @@ -5,63 +5,93 @@ namespace Brick\Math; use Brick\Math\Exception\DivisionByZeroException; +use Brick\Math\Exception\IntegerOverflowException; +use Brick\Math\Exception\InvalidArgumentException; use Brick\Math\Exception\MathException; use Brick\Math\Exception\NumberFormatException; use Brick\Math\Exception\RoundingNecessaryException; +use Brick\Math\Internal\Safe; +use JsonSerializable; +use Override; +use Stringable; + +use function assert; +use function filter_var; +use function is_int; +use function is_null; +use function ltrim; +use function preg_match; +use function str_contains; +use function str_repeat; +use function strlen; +use function substr; + +use const FILTER_VALIDATE_INT; +use const PREG_UNMATCHED_AS_NULL; /** - * 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 \JsonSerializable +abstract readonly class BigNumber implements JsonSerializable, Stringable { /** * The regular expression used to parse integer or decimal numbers. + * + * The end anchor must be \z, not $: the latter would also match before a trailing newline. */ private const PARSE_REGEXP_NUMERICAL = '/^' . - '(?[\-\+])?' . - '(?[0-9]+)?' . - '(?\.)?' . - '(?[0-9]+)?' . - '(?:[eE](?[\-\+]?[0-9]+))?' . - '$/'; + '(?[\-\+])?' . + '(?[0-9]+)?' . + '(?\.)?' . + '(?[0-9]+)?' . + '(?:[eE](?[\-\+]?[0-9]+))?' . + '\z/'; /** * The regular expression used to parse rational numbers. + * + * The end anchor must be \z, not $: the latter would also match before a trailing newline. */ private const PARSE_REGEXP_RATIONAL = '/^' . - '(?[\-\+])?' . - '(?[0-9]+)' . - '\/?' . - '(?[0-9]+)' . - '$/'; + '(?[\-\+])?' . + '(?[0-9]+)' . + '\/' . + '(?[0-9]+)' . + '\z/'; /** * 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 - * - floating point numbers are converted to a string then parsed as such * - strings containing a `/` character are returned as BigRational * - 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 * - * @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. + * 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. + * + * @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. * - * @psalm-pure + * @pure */ - final public static function of(BigNumber|int|float|string $value) : static + final public static function of(BigNumber|int|string $value): static { $value = self::_of($value); if (static::class === BigNumber::class) { - // https://github.com/vimeo/psalm/issues/10309 assert($value instanceof static); return $value; @@ -71,407 +101,345 @@ final public static function of(BigNumber|int|float|string $value) : static } /** - * @psalm-pure - */ - private static function _of(BigNumber|int|float|string $value) : BigNumber - { - if ($value instanceof BigNumber) { - return $value; - } - - if (\is_int($value)) { - return new BigInteger((string) $value); - } - - if (is_float($value)) { - $value = (string) $value; - } - - if (str_contains($value, '/')) { - // Rational number - if (\preg_match(self::PARSE_REGEXP_RATIONAL, $value, $matches, PREG_UNMATCHED_AS_NULL) !== 1) { - throw NumberFormatException::invalidFormat($value); - } - - $sign = $matches['sign']; - $numerator = $matches['numerator']; - $denominator = $matches['denominator']; - - assert($numerator !== null); - assert($denominator !== null); - - $numerator = self::cleanUp($sign, $numerator); - $denominator = self::cleanUp(null, $denominator); - - if ($denominator === '0') { - throw DivisionByZeroException::denominatorMustNotBeZero(); - } - - return new BigRational( - new BigInteger($numerator), - new BigInteger($denominator), - false - ); - } else { - // Integer or decimal number - if (\preg_match(self::PARSE_REGEXP_NUMERICAL, $value, $matches, PREG_UNMATCHED_AS_NULL) !== 1) { - throw NumberFormatException::invalidFormat($value); - } - - $sign = $matches['sign']; - $point = $matches['point']; - $integral = $matches['integral']; - $fractional = $matches['fractional']; - $exponent = $matches['exponent']; - - if ($integral === null && $fractional === null) { - throw NumberFormatException::invalidFormat($value); - } - - 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.'); - } - - $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); - } - - $integral = self::cleanUp($sign, $integral); - - return new BigInteger($integral); - } - } - - /** - * Overridden by subclasses to convert a BigNumber to an instance of the subclass. + * Creates a BigNumber of the given value, or returns null if the input is null. * - * @throws MathException If the value cannot be converted. + * Behaves like of() for non-null values. * - * @psalm-pure - */ - abstract protected static function from(BigNumber $number): static; - - /** - * Proxy method to access BigInteger's protected constructor from sibling classes. + * @see BigNumber::of() * - * @internal - * @psalm-pure - */ - final protected function newBigInteger(string $value) : BigInteger - { - return new BigInteger($value); - } - - /** - * Proxy method to access BigDecimal's protected constructor from sibling classes. + * @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. * - * @internal - * @psalm-pure + * @pure */ - final protected function newBigDecimal(string $value, int $scale = 0) : BigDecimal + final public static function ofNullable(BigNumber|int|string|null $value): ?static { - return new BigDecimal($value, $scale); - } + if (is_null($value)) { + return null; + } - /** - * Proxy method to access BigRational's protected constructor from sibling classes. - * - * @internal - * @psalm-pure - */ - final protected function newBigRational(BigInteger $numerator, BigInteger $denominator, bool $checkDenominator) : BigRational - { - return new BigRational($numerator, $denominator, $checkDenominator); + return static::of($value); } /** * Returns the minimum of the given values. * - * @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. + * If several values are equal and minimal, the first one is returned. + * This can affect the concrete return type when calling this method on BigNumber. + * + * @param BigNumber|int|string $a The first number. Must be convertible to an instance of the class this method + * is called on. + * @param BigNumber|int|string ...$n The additional numbers. Each number must be convertible to an instance of the + * class this method is called on. * - * @throws \InvalidArgumentException If no values are given. - * @throws MathException If an argument is not valid. + * @throws MathException If a number is not valid, or is not convertible to an instance of the class this method is + * called on. * - * @psalm-pure + * @pure */ - final public static function min(BigNumber|int|float|string ...$values) : static + final public static function min(BigNumber|int|string $a, BigNumber|int|string ...$n): static { - $min = null; + $min = static::of($a); - foreach ($values as $value) { + foreach ($n as $value) { $value = static::of($value); - if ($min === null || $value->isLessThan($min)) { + if ($value->isLessThan($min)) { $min = $value; } } - if ($min === null) { - throw new \InvalidArgumentException(__METHOD__ . '() expects at least one value.'); - } - return $min; } /** * Returns the maximum of the given values. * - * @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. + * If several values are equal and maximal, the first one is returned. + * This can affect the concrete return type when calling this method on BigNumber. + * + * @param BigNumber|int|string $a The first number. Must be convertible to an instance of the class this method + * is called on. + * @param BigNumber|int|string ...$n The additional numbers. Each number must be convertible to an instance of the + * class this method is called on. * - * @throws \InvalidArgumentException If no values are given. - * @throws MathException If an argument is not valid. + * @throws MathException If a number is not valid, or is not convertible to an instance of the class this method is + * called on. * - * @psalm-pure + * @pure */ - final public static function max(BigNumber|int|float|string ...$values) : static + final public static function max(BigNumber|int|string $a, BigNumber|int|string ...$n): static { - $max = null; + $max = static::of($a); - foreach ($values as $value) { + foreach ($n as $value) { $value = static::of($value); - if ($max === null || $value->isGreaterThan($max)) { + if ($value->isGreaterThan($max)) { $max = $value; } } - if ($max === null) { - throw new \InvalidArgumentException(__METHOD__ . '() expects at least one value.'); - } - return $max; } /** * 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). * - * @throws \InvalidArgumentException If no values are given. - * @throws MathException If an argument is not valid. + * 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. * - * @psalm-pure - */ - final public static function sum(BigNumber|int|float|string ...$values) : static - { - /** @var static|null $sum */ - $sum = null; - - foreach ($values as $value) { - $value = static::of($value); - - $sum = $sum === null ? $value : self::add($sum, $value); - } - - if ($sum === null) { - throw new \InvalidArgumentException(__METHOD__ . '() expects at least one value.'); - } - - return $sum; - } - - /** - * Adds two BigNumber instances in the correct order to avoid a RoundingNecessaryException. + * @param BigNumber|int|string $a The first number. Must be convertible to an instance of the class this method + * is called on. + * @param BigNumber|int|string ...$n The additional numbers. Each number must be convertible to an instance of the + * class this method is called on. * - * @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...) + * @throws MathException If a number is not valid, or is not convertible to an instance of the class this method is + * called on. * - * @psalm-pure + * @pure */ - private static function add(BigNumber $a, BigNumber $b) : BigNumber + final public static function sum(BigNumber|int|string $a, BigNumber|int|string ...$n): static { - if ($a instanceof BigRational) { - return $a->plus($b); - } - - if ($b instanceof BigRational) { - return $b->plus($a); - } - - if ($a instanceof BigDecimal) { - return $a->plus($b); - } + $sum = static::of($a); - if ($b instanceof BigDecimal) { - return $b->plus($a); + foreach ($n as $value) { + $sum = self::add($sum, static::of($value)); } - /** @var BigInteger $a */ + assert($sum instanceof static); - return $a->plus($b); + return $sum; } /** - * Removes optional leading zeros and applies sign. + * Checks if this number is equal to the given one. * - * @param string|null $sign The sign, '+' or '-', optional. Null is allowed for convenience and treated as '+'. - * @param string $number The number, validated as a non-empty string of digits. + * @throws MathException If the given number is not valid. * - * @psalm-pure + * @pure */ - private static function cleanUp(string|null $sign, string $number) : string - { - $number = \ltrim($number, '0'); - - if ($number === '') { - return '0'; - } - - return $sign === '-' ? '-' . $number : $number; - } - - /** - * Checks if this number is equal to the given one. - */ - final public function isEqualTo(BigNumber|int|float|string $that) : bool + final public function isEqualTo(BigNumber|int|string $that): bool { return $this->compareTo($that) === 0; } /** - * Checks if this number is strictly lower than the given one. + * Checks if this number is strictly less than the given one. + * + * @throws MathException If the given number is not valid. + * + * @pure */ - final public function isLessThan(BigNumber|int|float|string $that) : bool + final public function isLessThan(BigNumber|int|string $that): bool { return $this->compareTo($that) < 0; } /** - * Checks if this number is lower than or equal to the given one. + * Checks if this number is less than or equal to the given one. + * + * @throws MathException If the given number is not valid. + * + * @pure */ - final public function isLessThanOrEqualTo(BigNumber|int|float|string $that) : bool + final public function isLessThanOrEqualTo(BigNumber|int|string $that): bool { return $this->compareTo($that) <= 0; } /** * Checks if this number is strictly greater than the given one. + * + * @throws MathException If the given number is not valid. + * + * @pure */ - final public function isGreaterThan(BigNumber|int|float|string $that) : bool + final public function isGreaterThan(BigNumber|int|string $that): bool { return $this->compareTo($that) > 0; } /** * Checks if this number is greater than or equal to the given one. + * + * @throws MathException If the given number is not valid. + * + * @pure */ - final public function isGreaterThanOrEqualTo(BigNumber|int|float|string $that) : bool + final public function isGreaterThanOrEqualTo(BigNumber|int|string $that): bool { return $this->compareTo($that) >= 0; } /** * Checks if this number equals zero. + * + * @pure */ - final public function isZero() : bool + final public function isZero(): bool { return $this->getSign() === 0; } /** * Checks if this number is strictly negative. + * + * @pure */ - final public function isNegative() : bool + final public function isNegative(): bool { return $this->getSign() < 0; } /** * Checks if this number is negative or zero. + * + * @pure */ - final public function isNegativeOrZero() : bool + final public function isNegativeOrZero(): bool { return $this->getSign() <= 0; } /** * Checks if this number is strictly positive. + * + * @pure */ - final public function isPositive() : bool + final public function isPositive(): bool { return $this->getSign() > 0; } /** * Checks if this number is positive or zero. + * + * @pure */ - final public function isPositiveOrZero() : bool + final public function isPositiveOrZero(): bool { return $this->getSign() >= 0; } + /** + * Returns the absolute value of this number. + * + * @pure + */ + final public function abs(): static + { + return $this->isNegative() ? $this->negated() : $this; + } + + /** + * Returns the negated value of this number. + * + * @pure + */ + abstract public function negated(): static; + /** * Returns the sign of this number. * - * @psalm-return -1|0|1 + * Returns -1 if the number is negative, 0 if zero, 1 if positive. + * + * @return -1|0|1 * - * @return int -1 if the number is negative, 0 if zero, 1 if positive. + * @pure */ - abstract public function getSign() : int; + abstract public function getSign(): int; /** * Compares this number to the given one. * - * @psalm-return -1|0|1 + * Returns -1 if `$this` is lower than, 0 if equal to, 1 if greater than `$that`. * - * @return int -1 if `$this` is lower than, 0 if equal to, 1 if greater than `$that`. + * @return -1|0|1 * * @throws MathException If the number is not valid. + * + * @pure */ - abstract public function compareTo(BigNumber|int|float|string $that) : int; + abstract public function compareTo(BigNumber|int|string $that): int; + + /** + * Limits (clamps) this number between the given minimum and maximum values. + * + * If the number is lower than $min, returns $min. + * If the number is greater than $max, returns $max. + * Otherwise, returns this number unchanged. + * + * @param BigNumber|int|string $min The minimum. Must be convertible to an instance of the class this method is called on. + * @param BigNumber|int|string $max The maximum. Must be convertible to an instance of the class this method is called on. + * + * @throws MathException If min/max are not convertible to an instance of the class this method is called on. + * @throws InvalidArgumentException If min is greater than max. + * + * @pure + */ + final public function clamp(BigNumber|int|string $min, BigNumber|int|string $max): static + { + $min = static::of($min); + $max = static::of($max); + + if ($min->isGreaterThan($max)) { + throw InvalidArgumentException::minGreaterThanMax(); + } + + if ($this->isLessThan($min)) { + return $min; + } + + if ($this->isGreaterThan($max)) { + return $max; + } + + return $this; + } /** * Converts this number to a BigInteger. * * @throws RoundingNecessaryException If this number cannot be converted to a BigInteger without rounding. + * + * @pure */ - abstract public function toBigInteger() : BigInteger; + abstract public function toBigInteger(): BigInteger; /** * Converts this number to a BigDecimal. * * @throws RoundingNecessaryException If this number cannot be converted to a BigDecimal without rounding. + * + * @pure */ - abstract public function toBigDecimal() : BigDecimal; + abstract public function toBigDecimal(): BigDecimal; /** * Converts this number to a BigRational. + * + * @pure */ - abstract public function toBigRational() : BigRational; + 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 RoundingMode $roundingMode An optional rounding mode, defaults to UNNECESSARY. + * @param non-negative-int $scale The scale of the resulting `BigDecimal`. Must be non-negative. + * @param RoundingMode $roundingMode An optional rounding mode, defaults to Unnecessary. + * + * @throws InvalidArgumentException If the scale is negative. + * @throws RoundingNecessaryException If RoundingMode::Unnecessary is used, and this number cannot be converted to + * the given scale without rounding. * - * @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, RoundingMode $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. @@ -479,9 +447,12 @@ abstract public function toScale(int $scale, RoundingMode $roundingMode = Roundi * 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. * - * @throws MathException If this number cannot be exactly converted to a native integer. + * @throws RoundingNecessaryException If this number cannot be converted to an integer without rounding. + * @throws IntegerOverflowException If this number is too large to fit in a native integer. + * + * @pure */ - abstract public function toInt() : int; + abstract public function toInt(): int; /** * Returns an approximation of this number as a floating-point value. @@ -491,19 +462,246 @@ abstract public function toInt() : int; * * 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. + * This method never returns NaN. + * + * @pure */ - abstract public function toFloat() : float; + abstract public function toFloat(): float; /** * Returns a string representation of this number. * - * 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. + * The output of this method can be parsed by the `of()` factory method; this will yield an object equal to this + * one, but possibly of a different type if instantiated through `BigNumber::of()`. + * + * @return non-empty-string + * + * @pure + */ + abstract public function toString(): string; + + /** + * @return non-empty-string + */ + #[Override] + final public function jsonSerialize(): string + { + return $this->toString(); + } + + /** + * @return non-empty-string + * + * @pure + */ + #[Override] + final public function __toString(): string + { + return $this->toString(); + } + + /** + * Overridden by subclasses to convert a BigNumber to an instance of the subclass. + * + * @throws RoundingNecessaryException If the value cannot be converted. + * + * @pure + */ + abstract protected static function from(BigNumber $number): static; + + /** + * Proxy method to access BigInteger's protected constructor from sibling classes. + * + * @internal + * + * @pure + */ + final protected function newBigInteger(string $value): BigInteger + { + return new BigInteger($value); + } + + /** + * Proxy method to access BigDecimal's protected constructor from sibling classes. + * + * @internal + * + * @param non-negative-int $scale + * + * @pure + */ + 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. + * + * @internal + * + * @pure + */ + final protected function newBigRational(BigInteger $numerator, BigInteger $denominator, bool $checkDenominator, bool $simplify): BigRational + { + return new BigRational($numerator, $denominator, $checkDenominator, $simplify); + } + + /** + * @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. + * + * @pure + */ + private static function _of(BigNumber|int|string $value): BigNumber + { + if ($value instanceof BigNumber) { + return $value; + } + + if (is_int($value)) { + return new BigInteger((string) $value); + } + + if ($value === '') { + throw NumberFormatException::emptyNumber(); + } + + if (str_contains($value, '/')) { + // Rational number + if (preg_match(self::PARSE_REGEXP_RATIONAL, $value, $matches, PREG_UNMATCHED_AS_NULL) !== 1) { + throw NumberFormatException::invalidFormat($value); + } + + $sign = $matches['sign']; + $numerator = $matches['numerator']; + $denominator = $matches['denominator']; + + $numerator = self::cleanUp($sign, $numerator); + $denominator = self::cleanUp(null, $denominator); + + if ($denominator === '0') { + throw DivisionByZeroException::zeroDenominator(); + } + + return new BigRational( + new BigInteger($numerator), + new BigInteger($denominator), + false, + true, + ); + } + + // Integer or decimal number + if (preg_match(self::PARSE_REGEXP_NUMERICAL, $value, $matches, PREG_UNMATCHED_AS_NULL) !== 1) { + throw NumberFormatException::invalidFormat($value); + } + + $sign = $matches['sign']; + $point = $matches['point']; + $integral = $matches['integral']; + $fractional = $matches['fractional']; + $exponent = $matches['exponent']; + + if ($integral === null && $fractional === null) { + throw NumberFormatException::invalidFormat($value); + } + + if ($integral === null) { + $integral = '0'; + } + + if ($point !== null || $exponent !== null) { + $fractional ??= ''; + + if ($exponent !== null) { + if ($exponent[0] === '-') { + $exponent = ltrim(substr($exponent, 1), '0') ?: '0'; + $exponent = filter_var($exponent, FILTER_VALIDATE_INT); + if ($exponent !== false) { + $exponent = -$exponent; + } + } else { + if ($exponent[0] === '+') { + $exponent = substr($exponent, 1); + } + $exponent = ltrim($exponent, '0') ?: '0'; + $exponent = filter_var($exponent, FILTER_VALIDATE_INT); + } + } else { + $exponent = 0; + } + + if ($exponent === false) { + throw NumberFormatException::exponentTooLarge(); + } + + $unscaledValue = self::cleanUp($sign, $integral . $fractional); + + $scale = strlen($fractional) - $exponent; + + // @phpstan-ignore function.alreadyNarrowedType + if (! is_int($scale)) { + throw NumberFormatException::exponentTooLarge(); + } + + if ($scale < 0) { + if ($unscaledValue !== '0') { + $unscaledValue .= str_repeat('0', Safe::neg($scale)); + } + $scale = 0; + } + + return new BigDecimal($unscaledValue, $scale); + } + + $integral = self::cleanUp($sign, $integral); + + return new BigInteger($integral); + } + + /** + * Removes optional leading zeros and applies sign. + * + * @param '+'|'-'|null $sign The sign, optional. Null is allowed for convenience and treated as '+'. + * @param non-empty-string $number The number, validated as a string of digits. + * + * @pure */ - abstract public function __toString() : string; + private static function cleanUp(string|null $sign, string $number): string + { + $number = ltrim($number, '0'); + + if ($number === '') { + return '0'; + } - final public function jsonSerialize() : string + return $sign === '-' ? '-' . $number : $number; + } + + /** + * Adds two BigNumber instances in the correct order to avoid a RoundingNecessaryException. + * + * @pure + */ + private static function add(BigNumber $a, BigNumber $b): BigNumber { - return $this->__toString(); + if ($a instanceof BigRational) { + return $a->plus($b); + } + + if ($b instanceof BigRational) { + return $b->plus($a); + } + + if ($a instanceof BigDecimal) { + return $a->plus($b); + } + + if ($b instanceof BigDecimal) { + return $b->plus($a); + } + + return $a->plus($b); } } diff --git a/brick/math/src/BigRational.php b/brick/math/src/BigRational.php index fc3060ede..04adf86c8 100644 --- a/brick/math/src/BigRational.php +++ b/brick/math/src/BigRational.php @@ -5,28 +5,38 @@ namespace Brick\Math; use Brick\Math\Exception\DivisionByZeroException; +use Brick\Math\Exception\InvalidArgumentException; use Brick\Math\Exception\MathException; -use Brick\Math\Exception\NumberFormatException; use Brick\Math\Exception\RoundingNecessaryException; +use Brick\Math\Internal\DecimalHelper; +use Brick\Math\Internal\Safe; +use LogicException; +use Override; + +use function max; +use function min; +use function strlen; +use function substr; /** * An arbitrarily large rational number. * * This class is immutable. * - * @psalm-immutable + * Fractions are automatically simplified to lowest terms. For example, `2/4` becomes `1/2`. + * The denominator is always strictly positive; the sign is carried by the numerator. */ -final class BigRational extends BigNumber +final readonly class BigRational extends BigNumber { /** * The numerator. */ - private readonly BigInteger $numerator; + private BigInteger $numerator; /** * The denominator. Always strictly positive. */ - private readonly BigInteger $denominator; + private BigInteger $denominator; /** * Protected constructor. Use a factory method to obtain an instance. @@ -34,32 +44,34 @@ final class BigRational extends BigNumber * @param BigInteger $numerator The numerator. * @param BigInteger $denominator The denominator. * @param bool $checkDenominator Whether to check the denominator for negative and zero. + * @param bool $simplify Whether to simplify the fraction to lowest terms. * * @throws DivisionByZeroException If the denominator is zero. + * + * @pure */ - protected function __construct(BigInteger $numerator, BigInteger $denominator, bool $checkDenominator) + protected function __construct(BigInteger $numerator, BigInteger $denominator, bool $checkDenominator, bool $simplify) { if ($checkDenominator) { if ($denominator->isZero()) { - throw DivisionByZeroException::denominatorMustNotBeZero(); + throw DivisionByZeroException::zeroDenominator(); } if ($denominator->isNegative()) { - $numerator = $numerator->negated(); + $numerator = $numerator->negated(); $denominator = $denominator->negated(); } } - $this->numerator = $numerator; - $this->denominator = $denominator; - } + if ($simplify) { + $gcd = $numerator->gcd($denominator); - /** - * @psalm-pure - */ - protected static function from(BigNumber $number): static - { - return $number->toBigRational(); + $numerator = $numerator->quotient($gcd); + $denominator = $denominator->quotient($gcd); + } + + $this->numerator = $numerator; + $this->denominator = $denominator; } /** @@ -68,40 +80,36 @@ protected static function from(BigNumber $number): static * If the denominator is negative, the signs of both the numerator and the denominator * will be inverted to ensure that the denominator is always positive. * - * @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. + * @param BigNumber|int|string $numerator The numerator. Must be convertible to a BigInteger. + * @param BigNumber|int|string $denominator The denominator. Must be convertible to a BigInteger. * - * @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. + * @throws MathException If an argument is not valid, or is not convertible to a BigInteger. + * @throws DivisionByZeroException If the denominator is zero. * - * @psalm-pure + * @pure */ - public static function nd( - BigNumber|int|float|string $numerator, - BigNumber|int|float|string $denominator, - ) : BigRational { - $numerator = BigInteger::of($numerator); + public static function ofFraction( + BigNumber|int|string $numerator, + BigNumber|int|string $denominator, + ): BigRational { + $numerator = BigInteger::of($numerator); $denominator = BigInteger::of($denominator); - return new BigRational($numerator, $denominator, true); + return new BigRational($numerator, $denominator, true, true); } /** * Returns a BigRational representing zero. * - * @psalm-pure + * @pure */ - public static function zero() : BigRational + public static function zero(): BigRational { - /** - * @psalm-suppress ImpureStaticVariable - * @var BigRational|null $zero - */ + /** @var BigRational|null $zero */ static $zero; if ($zero === null) { - $zero = new BigRational(BigInteger::zero(), BigInteger::one(), false); + $zero = new BigRational(BigInteger::zero(), BigInteger::one(), false, false); } return $zero; @@ -110,18 +118,15 @@ public static function zero() : BigRational /** * Returns a BigRational representing one. * - * @psalm-pure + * @pure */ - public static function one() : BigRational + public static function one(): BigRational { - /** - * @psalm-suppress ImpureStaticVariable - * @var BigRational|null $one - */ + /** @var BigRational|null $one */ static $one; if ($one === null) { - $one = new BigRational(BigInteger::one(), BigInteger::one(), false); + $one = new BigRational(BigInteger::one(), BigInteger::one(), false, false); } return $one; @@ -130,152 +135,214 @@ public static function one() : BigRational /** * Returns a BigRational representing ten. * - * @psalm-pure + * @pure */ - public static function ten() : BigRational + public static function ten(): BigRational { - /** - * @psalm-suppress ImpureStaticVariable - * @var BigRational|null $ten - */ + /** @var BigRational|null $ten */ static $ten; if ($ten === null) { - $ten = new BigRational(BigInteger::ten(), BigInteger::one(), false); + $ten = new BigRational(BigInteger::ten(), BigInteger::one(), false, false); } return $ten; } - public function getNumerator() : BigInteger + /** + * Returns the numerator of this rational number. + * + * @pure + */ + public function getNumerator(): BigInteger { return $this->numerator; } - public function getDenominator() : BigInteger - { - return $this->denominator; - } - /** - * Returns the quotient of the division of the numerator by the denominator. + * Returns the denominator of this rational number. + * + * The denominator is always strictly positive. + * + * @pure */ - public function quotient() : BigInteger + public function getDenominator(): BigInteger { - return $this->numerator->quotient($this->denominator); + return $this->denominator; } /** - * Returns the remainder of the division of the numerator by the denominator. + * Returns the integral part of this rational number. + * + * Examples: + * + * - `7/3` returns `2` (since 7/3 = 2 + 1/3) + * - `-7/3` returns `-2` (since -7/3 = -2 + (-1/3)) + * + * The following identity holds: `$r->isEqualTo($r->getFractionalPart()->plus($r->getIntegralPart()))`. Note that in + * this identity, the operand order is significant: the reversed form throws when the fractional part is non-zero. + * + * @pure */ - public function remainder() : BigInteger + public function getIntegralPart(): BigInteger { - return $this->numerator->remainder($this->denominator); + return $this->numerator->quotient($this->denominator); } /** - * Returns the quotient and remainder of the division of the numerator by the denominator. + * Returns the fractional part of this rational number. + * + * Examples: * - * @return BigInteger[] + * - `7/3` returns `1/3` (since 7/3 = 2 + 1/3) + * - `-7/3` returns `-1/3` (since -7/3 = -2 + (-1/3)) * - * @psalm-return array{BigInteger, BigInteger} + * The following identity holds: `$r->isEqualTo($r->getFractionalPart()->plus($r->getIntegralPart()))`. Note that in + * this identity, the operand order is significant: the reversed form throws when the fractional part is non-zero. + * + * @pure */ - public function quotientAndRemainder() : array + public function getFractionalPart(): BigRational { - return $this->numerator->quotientAndRemainder($this->denominator); + return new BigRational($this->numerator->remainder($this->denominator), $this->denominator, false, false); } /** * Returns the sum of this number and the given one. * - * @param BigNumber|int|float|string $that The number to add. + * @param BigNumber|int|string $that The number to add. * * @throws MathException If the number is not valid. + * + * @pure */ - public function plus(BigNumber|int|float|string $that) : BigRational + public function plus(BigNumber|int|string $that): BigRational { $that = BigRational::of($that); - $numerator = $this->numerator->multipliedBy($that->denominator); - $numerator = $numerator->plus($that->numerator->multipliedBy($this->denominator)); + if ($that->isZero()) { + return $this; + } + + if ($this->isZero()) { + return $that; + } + + $numerator = $this->numerator->multipliedBy($that->denominator); + $numerator = $numerator->plus($that->numerator->multipliedBy($this->denominator)); $denominator = $this->denominator->multipliedBy($that->denominator); - return new BigRational($numerator, $denominator, false); + return new BigRational($numerator, $denominator, false, true); } /** * Returns the difference of this number and the given one. * - * @param BigNumber|int|float|string $that The number to subtract. + * @param BigNumber|int|string $that The number to subtract. * * @throws MathException If the number is not valid. + * + * @pure */ - public function minus(BigNumber|int|float|string $that) : BigRational + public function minus(BigNumber|int|string $that): BigRational { $that = BigRational::of($that); - $numerator = $this->numerator->multipliedBy($that->denominator); - $numerator = $numerator->minus($that->numerator->multipliedBy($this->denominator)); + if ($that->isZero()) { + return $this; + } + + if ($this->isZero()) { + return $that->negated(); + } + + $numerator = $this->numerator->multipliedBy($that->denominator); + $numerator = $numerator->minus($that->numerator->multipliedBy($this->denominator)); $denominator = $this->denominator->multipliedBy($that->denominator); - return new BigRational($numerator, $denominator, false); + return new BigRational($numerator, $denominator, false, true); } /** * Returns the product of this number and the given one. * - * @param BigNumber|int|float|string $that The multiplier. + * @param BigNumber|int|string $that The multiplier. + * + * @throws MathException If the multiplier is not valid. * - * @throws MathException If the multiplier is not a valid number. + * @pure */ - public function multipliedBy(BigNumber|int|float|string $that) : BigRational + public function multipliedBy(BigNumber|int|string $that): BigRational { $that = BigRational::of($that); - $numerator = $this->numerator->multipliedBy($that->numerator); + if ($that->isZero() || $this->isZero()) { + return BigRational::zero(); + } + + $numerator = $this->numerator->multipliedBy($that->numerator); $denominator = $this->denominator->multipliedBy($that->denominator); - return new BigRational($numerator, $denominator, false); + return new BigRational($numerator, $denominator, false, true); } /** * Returns the result of the division of this number by the given one. * - * @param BigNumber|int|float|string $that The divisor. + * @param BigNumber|int|string $that The divisor. + * + * @throws MathException If the divisor is not valid. + * @throws DivisionByZeroException If the divisor is zero. * - * @throws MathException If the divisor is not a valid number, or is zero. + * @pure */ - public function dividedBy(BigNumber|int|float|string $that) : BigRational + public function dividedBy(BigNumber|int|string $that): BigRational { $that = BigRational::of($that); - $numerator = $this->numerator->multipliedBy($that->denominator); + if ($that->isZero()) { + throw DivisionByZeroException::divisionByZero(); + } + + $numerator = $this->numerator->multipliedBy($that->denominator); $denominator = $this->denominator->multipliedBy($that->numerator); - return new BigRational($numerator, $denominator, true); + return new BigRational($numerator, $denominator, true, true); } /** * Returns this number exponentiated to the given value. * - * @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000. + * Unlike BigInteger and BigDecimal, BigRational supports negative exponents: + * the result is the reciprocal raised to the absolute value of the exponent. + * + * @throws DivisionByZeroException If the exponent is negative and this number is zero. + * + * @pure */ - public function power(int $exponent) : BigRational + public function power(int $exponent): BigRational { if ($exponent === 0) { - $one = BigInteger::one(); - - return new BigRational($one, $one, false); + return BigRational::one(); } if ($exponent === 1) { return $this; } + if ($exponent < 0) { + if ($this->isZero()) { + throw DivisionByZeroException::zeroToNegativePower(); + } + + return $this->reciprocal()->power(Safe::neg($exponent)); + } + return new BigRational( $this->numerator->power($exponent), $this->denominator->power($exponent), - false + false, + false, ); } @@ -284,99 +351,206 @@ public function power(int $exponent) : BigRational * * The reciprocal has the numerator and denominator swapped. * - * @throws DivisionByZeroException If the numerator is zero. + * @throws DivisionByZeroException If this number is zero. + * + * @pure */ - public function reciprocal() : BigRational + public function reciprocal(): BigRational { - return new BigRational($this->denominator, $this->numerator, true); - } + if ($this->isZero()) { + throw DivisionByZeroException::reciprocalOfZero(); + } - /** - * Returns the absolute value of this BigRational. - */ - public function abs() : BigRational - { - return new BigRational($this->numerator->abs(), $this->denominator, false); + return new BigRational($this->denominator, $this->numerator, true, false); } - /** - * Returns the negated value of this BigRational. - */ - public function negated() : BigRational + #[Override] + public function negated(): static { - return new BigRational($this->numerator->negated(), $this->denominator, false); + return new BigRational($this->numerator->negated(), $this->denominator, false, false); } - /** - * Returns the simplified value of this BigRational. - */ - public function simplified() : BigRational + #[Override] + public function compareTo(BigNumber|int|string $that): int { - $gcd = $this->numerator->gcd($this->denominator); - - $numerator = $this->numerator->quotient($gcd); - $denominator = $this->denominator->quotient($gcd); + $that = BigRational::of($that); - return new BigRational($numerator, $denominator, false); - } + if ($this->denominator->isEqualTo($that->denominator)) { + return $this->numerator->compareTo($that->numerator); + } - public function compareTo(BigNumber|int|float|string $that) : int - { - return $this->minus($that)->getSign(); + return $this->numerator + ->multipliedBy($that->denominator) + ->compareTo($that->numerator->multipliedBy($this->denominator)); } - public function getSign() : int + #[Override] + public function getSign(): int { return $this->numerator->getSign(); } - public function toBigInteger() : BigInteger + #[Override] + public function toBigInteger(): BigInteger { - $simplified = $this->simplified(); - - if (! $simplified->denominator->isEqualTo(1)) { - throw new RoundingNecessaryException('This rational number cannot be represented as an integer value without rounding.'); + if ($this->denominator->isEqualTo(1)) { + return $this->numerator; } - return $simplified->numerator; + throw RoundingNecessaryException::rationalNotConvertibleToInteger(); } - public function toBigDecimal() : BigDecimal + #[Override] + public function toBigDecimal(): BigDecimal { - return $this->numerator->toBigDecimal()->exactlyDividedBy($this->denominator); + $scale = DecimalHelper::computeScaleFromReducedFractionDenominator($this->denominator->toString()); + + if ($scale === null) { + throw RoundingNecessaryException::rationalNotConvertibleToDecimal(); + } + + return $this->numerator->toBigDecimal()->dividedBy($this->denominator, $scale)->strippedOfTrailingZeros(); } - public function toBigRational() : BigRational + #[Override] + public function toBigRational(): BigRational { return $this; } - public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal + #[Override] + public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::Unnecessary): BigDecimal { + if ($scale < 0) { // @phpstan-ignore smaller.alwaysFalse + throw InvalidArgumentException::negativeScale(); + } + + if ($roundingMode === RoundingMode::Unnecessary) { + $requiredScale = DecimalHelper::computeScaleFromReducedFractionDenominator($this->denominator->toString()); + + if ($requiredScale === null) { + throw RoundingNecessaryException::rationalNotConvertibleToDecimal(); + } + + if ($requiredScale > $scale) { + throw RoundingNecessaryException::rationalScaleTooSmall(); + } + } + return $this->numerator->toBigDecimal()->dividedBy($this->denominator, $scale, $roundingMode); } - public function toInt() : int + #[Override] + public function toInt(): int { return $this->toBigInteger()->toInt(); } - public function toFloat() : float + #[Override] + public function toFloat(): float { - $simplified = $this->simplified(); - return $simplified->numerator->toFloat() / $simplified->denominator->toFloat(); + if ($this->denominator->isEqualTo(1)) { + return $this->numerator->toFloat(); + } + + // Avoid $this->numerator->toFloat() / $this->denominator->toFloat(): converting both operands to float first + // adds an extra rounding step before the division and can change the final float. Instead, divide in decimal + // first and convert the resulting decimal approximation to float once. + + // We need ~17 significant digits for double precision (we use 20 for some margin). Since $scale controls + // decimal places (not significant digits), we subtract the estimated order of magnitude so that large results + // use fewer decimal places and small results use more (to look past leading zeros). Clamped to [0, 350] as + // doubles range from e-324 to e308 (350 ≈ 324 + 20 significant digits + margin). + $magnitude = strlen($this->numerator->abs()->toString()) - strlen($this->denominator->toString()); + $scale = min(350, max(0, 20 - $magnitude)); + + $result = $this->numerator + ->toBigDecimal() + ->dividedBy($this->denominator, $scale, RoundingMode::HalfEven) + ->toFloat(); + + // Preserve the sign when the decimal approximation underflows to zero. + if ($result === 0.0 && $this->numerator->isNegative()) { + return -0.0; + } + + return $result; } - public function __toString() : string + #[Override] + public function toString(): string { - $numerator = (string) $this->numerator; - $denominator = (string) $this->denominator; + $numerator = $this->numerator->toString(); + $denominator = $this->denominator->toString(); if ($denominator === '1') { return $numerator; } - return $this->numerator . '/' . $this->denominator; + return $numerator . '/' . $denominator; + } + + /** + * Returns the decimal representation of this rational number, with repeating decimals in parentheses. + * + * WARNING: This method is unbounded. + * The length of the repeating decimal period can be as large as `denominator - 1`. + * For fractions with large denominators, this method can use excessive memory and CPU time. + * For example, `1/100019` has a repeating period of 100,018 digits. + * + * Examples: + * + * - `10/3` returns `3.(3)` + * - `171/70` returns `2.4(428571)` + * - `1/2` returns `0.5` + * + * @return non-empty-string + * + * @pure + */ + public function toRepeatingDecimalString(): string + { + if ($this->isZero()) { + return '0'; + } + + $sign = $this->numerator->isNegative() ? '-' : ''; + $numerator = $this->numerator->abs(); + $denominator = $this->denominator; + + $integral = $numerator->quotient($denominator); + $remainder = $numerator->remainder($denominator); + + $integralString = $integral->toString(); + + if ($remainder->isZero()) { + return $sign . $integralString; + } + + $digits = ''; + $remainderPositions = []; + $index = 0; + + while (! $remainder->isZero()) { + $remainderString = $remainder->toString(); + + if (isset($remainderPositions[$remainderString])) { + $repeatIndex = $remainderPositions[$remainderString]; + $nonRepeating = substr($digits, 0, $repeatIndex); + $repeating = substr($digits, $repeatIndex); + + return $sign . $integralString . '.' . $nonRepeating . '(' . $repeating . ')'; + } + + $remainderPositions[$remainderString] = $index; + $remainder = $remainder->multipliedBy(10); + + $digits .= $remainder->quotient($denominator)->toString(); + $remainder = $remainder->remainder($denominator); + $index++; + } + + return $sign . $integralString . '.' . $digits; } /** @@ -395,19 +569,26 @@ public function __serialize(): array * 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 * - * @throws \LogicException + * @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.'); + 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']; } + + #[Override] + protected static function from(BigNumber $number): static + { + return $number->toBigRational(); + } } diff --git a/brick/math/src/Exception/DivisionByZeroException.php b/brick/math/src/Exception/DivisionByZeroException.php index ce7769ac2..ece1c289d 100644 --- a/brick/math/src/Exception/DivisionByZeroException.php +++ b/brick/math/src/Exception/DivisionByZeroException.php @@ -4,32 +4,70 @@ namespace Brick\Math\Exception; +use RuntimeException; + /** * Exception thrown when a division by zero occurs. */ -class DivisionByZeroException extends MathException +final class DivisionByZeroException extends RuntimeException implements MathException { /** - * @psalm-pure + * @internal + * + * @pure + */ + public function __construct(string $message) + { + parent::__construct($message); + } + + /** + * @internal + * + * @pure */ - public static function divisionByZero() : DivisionByZeroException + public static function divisionByZero(): self { return new self('Division by zero.'); } /** - * @psalm-pure + * @internal + * + * @pure */ - public static function modulusMustNotBeZero() : DivisionByZeroException + public static function zeroModulus(): self { return new self('The modulus must not be zero.'); } /** - * @psalm-pure + * @internal + * + * @pure + */ + public static function zeroDenominator(): self + { + return new self('The denominator of a rational number must not be zero.'); + } + + /** + * @internal + * + * @pure + */ + public static function reciprocalOfZero(): self + { + return new self('The reciprocal of zero is undefined.'); + } + + /** + * @internal + * + * @pure */ - public static function denominatorMustNotBeZero() : DivisionByZeroException + public static function zeroToNegativePower(): self { - return new self('The denominator of a rational number cannot be zero.'); + return new self('Cannot raise zero to a negative power.'); } } diff --git a/brick/math/src/Exception/IntegerOverflowException.php b/brick/math/src/Exception/IntegerOverflowException.php index c73b49097..12505083c 100644 --- a/brick/math/src/Exception/IntegerOverflowException.php +++ b/brick/math/src/Exception/IntegerOverflowException.php @@ -5,19 +5,52 @@ namespace Brick\Math\Exception; use Brick\Math\BigInteger; +use RuntimeException; + +use function sprintf; + +use const PHP_INT_MAX; +use const PHP_INT_MIN; /** - * Exception thrown when an integer overflow occurs. + * Exception thrown when a native integer overflow occurs. */ -class IntegerOverflowException extends MathException +final class IntegerOverflowException extends RuntimeException implements MathException { /** - * @psalm-pure + * @internal + * + * @pure + */ + public function __construct(string $message) + { + parent::__construct($message); + } + + /** + * @internal + * + * @pure */ - public static function toIntOverflow(BigInteger $value) : IntegerOverflowException + public static function integerOutOfRange(BigInteger $value): self { - $message = '%s is out of range %d to %d and cannot be represented as an integer.'; + $message = '%s is out of range [%d, %d] and cannot be represented as an integer.'; + + return new self(sprintf($message, $value->toString(), PHP_INT_MIN, PHP_INT_MAX)); + } - return new self(\sprintf($message, (string) $value, PHP_INT_MIN, PHP_INT_MAX)); + /** + * @internal + * + * @pure + */ + public static function nativeIntegerOverflow(string $expression): self + { + return new self(sprintf( + 'Cannot compute %s because the result is outside the native integer range [%d, %d].', + $expression, + PHP_INT_MIN, + PHP_INT_MAX, + )); } } diff --git a/brick/math/src/Exception/InvalidArgumentException.php b/brick/math/src/Exception/InvalidArgumentException.php new file mode 100644 index 000000000..f30ef31e3 --- /dev/null +++ b/brick/math/src/Exception/InvalidArgumentException.php @@ -0,0 +1,133 @@ + 126) { - $char = \strtoupper(\dechex($ord)); + $char = strtoupper(dechex($ord)); - if ($ord < 10) { + if ($ord < 16) { $char = '0' . $char; } - } else { - $char = '"' . $char . '"'; + + return '0x' . $char; } - return new self(\sprintf('Char %s is not a valid character in the given alphabet.', $char)); + return '"' . $char . '"'; } } diff --git a/brick/math/src/Exception/RandomSourceException.php b/brick/math/src/Exception/RandomSourceException.php new file mode 100644 index 000000000..0a9fa8864 --- /dev/null +++ b/brick/math/src/Exception/RandomSourceException.php @@ -0,0 +1,64 @@ +init($a, $b); @@ -144,8 +84,8 @@ final public function cmp(string $a, string $b) : int return 1; } - $aLen = \strlen($aDig); - $bLen = \strlen($bDig); + $aLen = strlen($aDig); + $bLen = strlen($bDig); if ($aLen < $bLen) { $result = -1; @@ -160,18 +100,24 @@ final public function cmp(string $a, string $b) : int /** * Adds two numbers. + * + * @pure */ - abstract public function add(string $a, string $b) : string; + abstract public function add(string $a, string $b): string; /** * Subtracts two numbers. + * + * @pure */ - abstract public function sub(string $a, string $b) : string; + abstract public function sub(string $a, string $b): string; /** * Multiplies two numbers. + * + * @pure */ - abstract public function mul(string $a, string $b) : string; + abstract public function mul(string $a, string $b): string; /** * Returns the quotient of the division of two numbers. @@ -180,8 +126,10 @@ abstract public function mul(string $a, string $b) : string; * @param string $b The divisor, must not be zero. * * @return string The quotient. + * + * @pure */ - abstract public function divQ(string $a, string $b) : string; + abstract public function divQ(string $a, string $b): string; /** * Returns the remainder of the division of two numbers. @@ -190,8 +138,10 @@ abstract public function divQ(string $a, string $b) : string; * @param string $b The divisor, must not be zero. * * @return string The remainder. + * + * @pure */ - abstract public function divR(string $a, string $b) : string; + abstract public function divR(string $a, string $b): string; /** * Returns the quotient and remainder of the division of two numbers. @@ -200,23 +150,29 @@ abstract public function divR(string $a, string $b) : string; * @param string $b The divisor, must not be zero. * * @return array{string, string} An array containing the quotient and remainder. + * + * @pure */ - abstract public function divQR(string $a, string $b) : array; + abstract public function divQR(string $a, string $b): array; /** * Exponentiates a number. * * @param string $a The base number. - * @param int $e The exponent, validated as an integer between 0 and MAX_POWER. + * @param int $e The exponent, validated as a non-negative integer. * * @return string The power. + * + * @pure */ - abstract public function pow(string $a, int $e) : string; + abstract public function pow(string $a, int $e): string; /** * @param string $b The modulus; must not be zero. + * + * @pure */ - public function mod(string $a, string $b) : string + public function mod(string $a, string $b): string { return $this->divR($this->add($this->divR($a, $b), $b), $b); } @@ -229,8 +185,10 @@ public function mod(string $a, string $b) : string * This method can be overridden by the concrete implementation if the underlying library has built-in support. * * @param string $m The modulus; must not be negative or zero. + * + * @pure */ - public function modInverse(string $x, string $m) : ?string + public function modInverse(string $x, string $m): ?string { if ($m === '1') { return '0'; @@ -254,11 +212,13 @@ public function modInverse(string $x, string $m) : ?string /** * Raises a number into power with modulo. * - * @param string $base The base number; must be positive or zero. + * @param string $base The base number. * @param string $exp The exponent; must be positive or zero. * @param string $mod The modulus; must be strictly positive. + * + * @pure */ - abstract public function modPow(string $base, string $exp, string $mod) : string; + abstract public function modPow(string $base, string $exp, string $mod): string; /** * Returns the greatest common divisor of the two numbers. @@ -267,35 +227,35 @@ abstract public function modPow(string $base, string $exp, string $mod) : string * has built-in support for GCD calculations. * * @return string The GCD, always positive, or zero if both arguments are zero. + * + * @pure */ - public function gcd(string $a, string $b) : string + public function gcd(string $a, string $b): string { - if ($a === '0') { - return $this->abs($b); - } - - if ($b === '0') { - return $this->abs($a); + while ($b !== '0') { + [$a, $b] = [$b, $this->divR($a, $b)]; } - return $this->gcd($b, $this->divR($a, $b)); + return $this->abs($a); } /** - * @return array{string, string, string} GCD, X, Y + * Returns the least common multiple of the two numbers. + * + * This method can be overridden by the concrete implementation if the underlying library + * has built-in support for LCM calculations. + * + * @return string The LCM, always positive, or zero if at least one argument is zero. + * + * @pure */ - private function gcdExtended(string $a, string $b) : array + public function lcm(string $a, string $b): string { - if ($a === '0') { - return [$b, '0', '1']; + if ($a === '0' || $b === '0') { + return '0'; } - [$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, $x, $y]; + return $this->divQ($this->abs($this->mul($a, $b)), $this->gcd($a, $b)); } /** @@ -303,8 +263,68 @@ private function gcdExtended(string $a, string $b) : array * * The result is the largest x such that x² ≤ n. * The input MUST NOT be negative. + * + * @pure */ - abstract public function sqrt(string $n) : string; + abstract public function sqrt(string $n): string; + + /** + * Returns the integer nth root of the given number, truncated toward zero. + * + * If $n is non-negative, the result is the largest x such that x^$k ≤ $n (floor). + * If $n is negative, $k MUST be odd, and the result is the negation of the floor root of |$n| + * (i.e., truncation toward zero: the smallest x such that x^$k ≥ $n). + * + * The caller MUST guarantee that $k ≥ 1 and that $n is non-negative when $k is even. + * + * This method can be overridden by the concrete implementation if the underlying library + * has built-in support for nth root calculations. + * + * @param string $n The number. May be negative only when $k is odd. + * @param int $k The root degree. Must be strictly positive. + * + * @pure + */ + public function nthRoot(string $n, int $k): string + { + if ($n === '0') { + return '0'; + } + + $negative = ($n[0] === '-'); + $m = $negative ? substr($n, 1) : $n; + + if ($m === '1') { + return $negative ? '-1' : '1'; + } + + // Initial overshoot: 10^ceil(strlen(m)/k) is strictly greater than the true root. + // Newton-Raphson requires starting above the true root to converge monotonically down. + $x = '1' . str_repeat('0', intdiv(strlen($m) - 1, $k) + 1); + + $kStr = (string) $k; + $kMinusOneStr = (string) ($k - 1); + + // Newton-Raphson recurrence for integer nth root: + // x_{i+1} = floor(((k-1) * x_i + floor(m / x_i^{k-1})) / k) + for (; ;) { + $nx = $this->divQ( + $this->add( + $this->mul($kMinusOneStr, $x), + $this->divQ($m, $this->pow($x, $k - 1)), + ), + $kStr, + ); + + if ($this->cmp($nx, $x) >= 0) { + break; + } + + $x = $nx; + } + + return $negative ? $this->neg($x) : $x; + } /** * Converts a number from an arbitrary base. @@ -316,10 +336,12 @@ abstract public function sqrt(string $n) : string; * @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 + public function fromBase(string $number, int $base): string { - return $this->fromArbitraryBase(\strtolower($number), self::ALPHABET, $base); + return $this->fromArbitraryBase(strtolower($number), self::ALPHABET, $base); } /** @@ -332,13 +354,15 @@ public function fromBase(string $number, int $base) : string * @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 + public function toBase(string $number, int $base): string { $negative = ($number[0] === '-'); if ($negative) { - $number = \substr($number, 1); + $number = substr($number, 1); } $number = $this->toArbitraryBase($number, self::ALPHABET, $base); @@ -359,11 +383,13 @@ public function toBase(string $number, int $base) : string * @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 + final public function fromArbitraryBase(string $number, string $alphabet, int $base): string { // remove leading "zeros" - $number = \ltrim($number, $alphabet[0]); + $number = ltrim($number, $alphabet[0]); if ($number === '') { return '0'; @@ -379,13 +405,13 @@ final public function fromArbitraryBase(string $number, string $alphabet, int $b $base = (string) $base; - for ($i = \strlen($number) - 1; $i >= 0; $i--) { - $index = \strpos($alphabet, $number[$i]); + for ($i = strlen($number) - 1; $i >= 0; $i--) { + $index = strpos($alphabet, $number[$i]); if ($index !== 0) { - $result = $this->add($result, ($index === 1) - ? $power - : $this->mul($power, (string) $index) + $result = $this->add( + $result, + ($index === 1) ? $power : $this->mul($power, (string) $index), ); } @@ -405,8 +431,10 @@ final public function fromArbitraryBase(string $number, string $alphabet, int $b * @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 + final public function toArbitraryBase(string $number, string $alphabet, int $base): string { if ($number === '0') { return $alphabet[0]; @@ -422,31 +450,29 @@ final public function toArbitraryBase(string $number, string $alphabet, int $bas $result .= $alphabet[$remainder]; } - return \strrev($result); + return strrev($result); } /** * Performs a rounded division. * - * Rounding is performed when the remainder of the division is not zero. + * When the remainder of the division is not zero, rounding is performed according to the rounding mode provided, + * unless RoundingMode::Unnecessary is used, in which case the method returns null. * * @param string $a The dividend. * @param string $b The divisor, must not be zero. * @param RoundingMode $roundingMode The rounding mode. * - * @throws \InvalidArgumentException If the rounding mode is invalid. - * @throws RoundingNecessaryException If RoundingMode::UNNECESSARY is provided but rounding is necessary. - * - * @psalm-suppress ImpureFunctionCall + * @pure */ - final public function divRound(string $a, string $b, RoundingMode $roundingMode) : string + final public function divRound(string $a, string $b, RoundingMode $roundingMode): ?string { [$quotient, $remainder] = $this->divQR($a, $b); $hasDiscardedFraction = ($remainder !== '0'); $isPositiveOrZero = ($a[0] === '-') === ($b[0] === '-'); - $discardedFractionSign = function() use ($remainder, $b) : int { + $discardedFractionSign = function () use ($remainder, $b): int { $r = $this->abs($this->mul($remainder, '2')); $b = $this->abs($b); @@ -456,51 +482,57 @@ final public function divRound(string $a, string $b, RoundingMode $roundingMode) $increment = false; switch ($roundingMode) { - case RoundingMode::UNNECESSARY: + case RoundingMode::Unnecessary: if ($hasDiscardedFraction) { - throw RoundingNecessaryException::roundingNecessary(); + return null; } + break; - case RoundingMode::UP: + case RoundingMode::Up: $increment = $hasDiscardedFraction; + break; - case RoundingMode::DOWN: + case RoundingMode::Down: break; - case RoundingMode::CEILING: + case RoundingMode::Ceiling: $increment = $hasDiscardedFraction && $isPositiveOrZero; + break; - case RoundingMode::FLOOR: + case RoundingMode::Floor: $increment = $hasDiscardedFraction && ! $isPositiveOrZero; + break; - case RoundingMode::HALF_UP: + case RoundingMode::HalfUp: $increment = $discardedFractionSign() >= 0; + break; - case RoundingMode::HALF_DOWN: + case RoundingMode::HalfDown: $increment = $discardedFractionSign() > 0; + break; - case RoundingMode::HALF_CEILING: + case RoundingMode::HalfCeiling: $increment = $isPositiveOrZero ? $discardedFractionSign() >= 0 : $discardedFractionSign() > 0; + break; - case RoundingMode::HALF_FLOOR: + case RoundingMode::HalfFloor: $increment = $isPositiveOrZero ? $discardedFractionSign() > 0 : $discardedFractionSign() >= 0; + break; - case RoundingMode::HALF_EVEN: + case RoundingMode::HalfEven: $lastDigit = (int) $quotient[-1]; $lastDigitIsEven = ($lastDigit % 2 === 0); $increment = $lastDigitIsEven ? $discardedFractionSign() > 0 : $discardedFractionSign() >= 0; - break; - default: - throw new \InvalidArgumentException('Invalid rounding mode.'); + break; } if ($increment) { @@ -515,8 +547,10 @@ final public function divRound(string $a, string $b, RoundingMode $roundingMode) * * This method can be overridden by the concrete implementation if the underlying library * has built-in support for bitwise operations. + * + * @pure */ - public function and(string $a, string $b) : string + public function and(string $a, string $b): string { return $this->bitwise('and', $a, $b); } @@ -526,8 +560,10 @@ public function and(string $a, string $b) : string * * This method can be overridden by the concrete implementation if the underlying library * has built-in support for bitwise operations. + * + * @pure */ - public function or(string $a, string $b) : string + public function or(string $a, string $b): string { return $this->bitwise('or', $a, $b); } @@ -537,33 +573,79 @@ public function or(string $a, string $b) : string * * This method can be overridden by the concrete implementation if the underlying library * has built-in support for bitwise operations. + * + * @pure */ - public function xor(string $a, string $b) : string + public function xor(string $a, string $b): string { return $this->bitwise('xor', $a, $b); } + /** + * Extracts the sign & digits of the operands. + * + * @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 + { + return [ + $aNeg = ($a[0] === '-'), + $bNeg = ($b[0] === '-'), + + $aNeg ? substr($a, 1) : $a, + $bNeg ? substr($b, 1) : $b, + ]; + } + + /** + * @param string $a Must be non-negative. + * @param string $b Must be non-negative. + * + * @return array{string, string} GCD, X + * + * @pure + */ + private function gcdExtended(string $a, string $b): array + { + // Iterative extended Euclidean algorithm; recursion would exhaust memory on large inputs. + [$r0, $r1] = [$a, $b]; + [$x0, $x1] = ['1', '0']; + + while ($r1 !== '0') { + [$q, $r] = $this->divQR($r0, $r1); + + [$r0, $r1] = [$r1, $r]; + [$x0, $x1] = [$x1, $this->sub($x0, $this->mul($q, $x1))]; + } + + return [$r0, $x0]; + } + /** * Performs a bitwise operation on a decimal number. * * @param 'and'|'or'|'xor' $operator The operator to use. * @param string $a The left operand. * @param string $b The right operand. + * + * @pure */ - private function bitwise(string $operator, string $a, string $b) : string + private function bitwise(string $operator, string $a, string $b): string { [$aNeg, $bNeg, $aDig, $bDig] = $this->init($a, $b); $aBin = $this->toBinary($aDig); $bBin = $this->toBinary($bDig); - $aLen = \strlen($aBin); - $bLen = \strlen($bBin); + $aLen = strlen($aBin); + $bLen = strlen($bBin); if ($aLen > $bLen) { - $bBin = \str_repeat("\x00", $aLen - $bLen) . $bBin; + $bBin = str_repeat("\x00", $aLen - $bLen) . $bBin; } elseif ($bLen > $aLen) { - $aBin = \str_repeat("\x00", $bLen - $aLen) . $aBin; + $aBin = str_repeat("\x00", $bLen - $aLen) . $aBin; } if ($aNeg) { @@ -596,18 +678,21 @@ private function bitwise(string $operator, string $a, string $b) : string /** * @param string $number A positive, binary number. + * + * @pure */ - private function twosComplement(string $number) : string + private function twosComplement(string $number): string { - $xor = \str_repeat("\xff", \strlen($number)); + $xor = str_repeat("\xff", strlen($number)); $number ^= $xor; - for ($i = \strlen($number) - 1; $i >= 0; $i--) { - $byte = \ord($number[$i]); + for ($i = strlen($number) - 1; $i >= 0; $i--) { + $byte = ord($number[$i]); if (++$byte !== 256) { - $number[$i] = \chr($byte); + $number[$i] = chr($byte); + break; } @@ -625,36 +710,40 @@ private function twosComplement(string $number) : string * Converts a decimal number to a binary string. * * @param string $number The number to convert, positive or zero, only digits. + * + * @pure */ - private function toBinary(string $number) : string + private function toBinary(string $number): string { $result = ''; while ($number !== '0') { [$number, $remainder] = $this->divQR($number, '256'); - $result .= \chr((int) $remainder); + $result .= chr((int) $remainder); } - return \strrev($result); + return strrev($result); } /** * Returns the positive decimal representation of a binary number. * * @param string $bytes The bytes representing the number. + * + * @pure */ - private function toDecimal(string $bytes) : string + private function toDecimal(string $bytes): string { $result = '0'; $power = '1'; - for ($i = \strlen($bytes) - 1; $i >= 0; $i--) { - $index = \ord($bytes[$i]); + for ($i = strlen($bytes) - 1; $i >= 0; $i--) { + $index = ord($bytes[$i]); if ($index !== 0) { - $result = $this->add($result, ($index === 1) - ? $power - : $this->mul($power, (string) $index) + $result = $this->add( + $result, + ($index === 1) ? $power : $this->mul($power, (string) $index), ); } diff --git a/brick/math/src/Internal/Calculator/BcMathCalculator.php b/brick/math/src/Internal/Calculator/BcMathCalculator.php index 067085e21..97e8168f3 100644 --- a/brick/math/src/Internal/Calculator/BcMathCalculator.php +++ b/brick/math/src/Internal/Calculator/BcMathCalculator.php @@ -5,61 +5,95 @@ namespace Brick\Math\Internal\Calculator; use Brick\Math\Internal\Calculator; +use Override; + +use function bcadd; +use function bcdiv; +use function bcmod; +use function bcmul; +use function bcpow; +use function bcpowmod; +use function bcsqrt; +use function bcsub; /** * Calculator implementation built around the bcmath library. * * @internal - * - * @psalm-immutable */ -class BcMathCalculator extends Calculator +final readonly class BcMathCalculator extends Calculator { - public function add(string $a, string $b) : string + #[Override] + public function add(string $a, string $b): string { - return \bcadd($a, $b, 0); + return bcadd($a, $b, 0); } - public function sub(string $a, string $b) : string + #[Override] + public function sub(string $a, string $b): string { - return \bcsub($a, $b, 0); + return bcsub($a, $b, 0); } - public function mul(string $a, string $b) : string + #[Override] + public function mul(string $a, string $b): string { - return \bcmul($a, $b, 0); + return bcmul($a, $b, 0); } - public function divQ(string $a, string $b) : string + #[Override] + public function divQ(string $a, string $b): string { - return \bcdiv($a, $b, 0); + return bcdiv($a, $b, 0); } - public function divR(string $a, string $b) : string + #[Override] + public function divR(string $a, string $b): string { - return \bcmod($a, $b, 0); + return bcmod($a, $b, 0); } - public function divQR(string $a, string $b) : array + #[Override] + public function divQR(string $a, string $b): array { - $q = \bcdiv($a, $b, 0); - $r = \bcmod($a, $b, 0); + $q = bcdiv($a, $b, 0); + $r = bcmod($a, $b, 0); return [$q, $r]; } - public function pow(string $a, int $e) : string + #[Override] + public function pow(string $a, int $e): string { - return \bcpow($a, (string) $e, 0); + if ($e === 0) { + return '1'; + } + + // bcpow() allocates memory proportional to the exponent even when the base is trivial, + // exhausting memory on 32-bit builds at large exponents. + if ($a === '0' || $a === '1') { + return $a; + } + + if ($a === '-1') { + return $e % 2 === 0 ? '1' : '-1'; + } + + return bcpow($a, (string) $e, 0); } - public function modPow(string $base, string $exp, string $mod) : string + #[Override] + public function modPow(string $base, string $exp, string $mod): string { - return \bcpowmod($base, $exp, $mod, 0); + // normalize to Euclidean representative so modPow() stays consistent with mod() + $base = $this->mod($base, $mod); + + return bcpowmod($base, $exp, $mod, 0); } - public function sqrt(string $n) : string + #[Override] + public function sqrt(string $n): string { - return \bcsqrt($n, 0); + return bcsqrt($n, 0); } } diff --git a/brick/math/src/Internal/Calculator/GmpCalculator.php b/brick/math/src/Internal/Calculator/GmpCalculator.php index 42d4c6927..4ee297694 100644 --- a/brick/math/src/Internal/Calculator/GmpCalculator.php +++ b/brick/math/src/Internal/Calculator/GmpCalculator.php @@ -5,104 +5,163 @@ namespace Brick\Math\Internal\Calculator; use Brick\Math\Internal\Calculator; +use GMP; +use Override; + +use function gmp_add; +use function gmp_and; +use function gmp_div_q; +use function gmp_div_qr; +use function gmp_div_r; +use function gmp_gcd; +use function gmp_init; +use function gmp_invert; +use function gmp_lcm; +use function gmp_mul; +use function gmp_or; +use function gmp_pow; +use function gmp_powm; +use function gmp_root; +use function gmp_sqrt; +use function gmp_strval; +use function gmp_sub; +use function gmp_xor; +use function substr; /** * Calculator implementation built around the GMP library. * * @internal - * - * @psalm-immutable */ -class GmpCalculator extends Calculator +final readonly class GmpCalculator extends Calculator { - public function add(string $a, string $b) : string + #[Override] + public function add(string $a, string $b): string { - return \gmp_strval(\gmp_add($a, $b)); + return gmp_strval(gmp_add($a, $b)); } - public function sub(string $a, string $b) : string + #[Override] + public function sub(string $a, string $b): string { - return \gmp_strval(\gmp_sub($a, $b)); + return gmp_strval(gmp_sub($a, $b)); } - public function mul(string $a, string $b) : string + #[Override] + public function mul(string $a, string $b): string { - return \gmp_strval(\gmp_mul($a, $b)); + return gmp_strval(gmp_mul($a, $b)); } - public function divQ(string $a, string $b) : string + #[Override] + public function divQ(string $a, string $b): string { - return \gmp_strval(\gmp_div_q($a, $b)); + return gmp_strval(gmp_div_q($a, $b)); } - public function divR(string $a, string $b) : string + #[Override] + public function divR(string $a, string $b): string { - return \gmp_strval(\gmp_div_r($a, $b)); + return gmp_strval(gmp_div_r($a, $b)); } - public function divQR(string $a, string $b) : array + #[Override] + public function divQR(string $a, string $b): array { - [$q, $r] = \gmp_div_qr($a, $b); + [$q, $r] = gmp_div_qr($a, $b); + /** + * @var GMP $q + * @var GMP $r + */ return [ - \gmp_strval($q), - \gmp_strval($r) + gmp_strval($q), + gmp_strval($r), ]; } - public function pow(string $a, int $e) : string + #[Override] + public function pow(string $a, int $e): string { - return \gmp_strval(\gmp_pow($a, $e)); + return gmp_strval(gmp_pow($a, $e)); } - public function modInverse(string $x, string $m) : ?string + #[Override] + public function modInverse(string $x, string $m): ?string { - $result = \gmp_invert($x, $m); + $result = gmp_invert($x, $m); if ($result === false) { return null; } - return \gmp_strval($result); + return gmp_strval($result); } - public function modPow(string $base, string $exp, string $mod) : string + #[Override] + public function modPow(string $base, string $exp, string $mod): string { - return \gmp_strval(\gmp_powm($base, $exp, $mod)); + return gmp_strval(gmp_powm($base, $exp, $mod)); } - public function gcd(string $a, string $b) : string + #[Override] + public function gcd(string $a, string $b): string { - return \gmp_strval(\gmp_gcd($a, $b)); + return gmp_strval(gmp_gcd($a, $b)); } - public function fromBase(string $number, int $base) : string + #[Override] + public function lcm(string $a, string $b): string { - return \gmp_strval(\gmp_init($number, $base)); + return gmp_strval(gmp_lcm($a, $b)); } - public function toBase(string $number, int $base) : string + #[Override] + public function fromBase(string $number, int $base): string { - return \gmp_strval($number, $base); + return gmp_strval(gmp_init($number, $base)); } - public function and(string $a, string $b) : string + #[Override] + public function toBase(string $number, int $base): string { - return \gmp_strval(\gmp_and($a, $b)); + return gmp_strval($number, $base); } - public function or(string $a, string $b) : string + #[Override] + public function and(string $a, string $b): string { - return \gmp_strval(\gmp_or($a, $b)); + return gmp_strval(gmp_and($a, $b)); } - public function xor(string $a, string $b) : string + #[Override] + public function or(string $a, string $b): string { - return \gmp_strval(\gmp_xor($a, $b)); + return gmp_strval(gmp_or($a, $b)); } - public function sqrt(string $n) : string + #[Override] + public function xor(string $a, string $b): string { - return \gmp_strval(\gmp_sqrt($n)); + return gmp_strval(gmp_xor($a, $b)); + } + + #[Override] + public function sqrt(string $n): string + { + return gmp_strval(gmp_sqrt($n)); + } + + #[Override] + public function nthRoot(string $n, int $k): string + { + // Delegate on the absolute value and re-apply the sign ourselves so the + // truncation-toward-zero convention matches the shared Newton-Raphson fallback + // bit-for-bit, regardless of any PHP/GMP behaviour changes for negative inputs. + if ($n[0] === '-') { + return '-' . gmp_strval(gmp_root(substr($n, 1), $k)); + } + + return gmp_strval(gmp_root($n, $k)); } } diff --git a/brick/math/src/Internal/Calculator/NativeCalculator.php b/brick/math/src/Internal/Calculator/NativeCalculator.php index 6acd06382..771f72d53 100644 --- a/brick/math/src/Internal/Calculator/NativeCalculator.php +++ b/brick/math/src/Internal/Calculator/NativeCalculator.php @@ -5,15 +5,28 @@ namespace Brick\Math\Internal\Calculator; use Brick\Math\Internal\Calculator; +use Override; + +use function assert; +use function in_array; +use function intdiv; +use function is_int; +use function ltrim; +use function str_pad; +use function str_repeat; +use function strcmp; +use function strlen; +use function substr; + +use const PHP_INT_SIZE; +use const STR_PAD_LEFT; /** * 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. @@ -23,9 +36,11 @@ class NativeCalculator extends Calculator * 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) */ - private readonly int $maxDigits; + private int $maxDigits; /** + * @pure + * * @codeCoverageIgnore */ public function __construct() @@ -33,15 +48,15 @@ public function __construct() $this->maxDigits = match (PHP_INT_SIZE) { 4 => 9, 8 => 18, - default => throw new \RuntimeException('The platform is not 32-bit or 64-bit as expected.') }; } - public function add(string $a, string $b) : string + #[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; @@ -68,16 +83,18 @@ public function add(string $a, string $b) : string return $result; } - public function sub(string $a, string $b) : string + #[Override] + public function sub(string $a, string $b): string { return $this->add($a, $this->neg($b)); } - public function mul(string $a, string $b) : string + #[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; @@ -116,17 +133,20 @@ public function mul(string $a, string $b) : string return $result; } - public function divQ(string $a, string $b) : string + #[Override] + public function divQ(string $a, string $b): string { return $this->divQR($a, $b)[0]; } + #[Override] public function divR(string $a, string $b): string { return $this->divQR($a, $b)[1]; } - public function divQR(string $a, string $b) : array + #[Override] + public function divQR(string $a, string $b): array { if ($a === '0') { return ['0', '0']; @@ -144,11 +164,11 @@ public function divQR(string $a, string $b) : array 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)) { @@ -159,7 +179,7 @@ public function divQR(string $a, string $b) : array return [ (string) $q, - (string) $r + (string) $r, ]; } } @@ -179,7 +199,8 @@ public function divQR(string $a, string $b) : array return [$q, $r]; } - public function pow(string $a, int $e) : string + #[Override] + public function pow(string $a, int $e): string { if ($e === 0) { return '1'; @@ -194,7 +215,6 @@ public function pow(string $a, int $e) : string $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) { @@ -205,14 +225,13 @@ public function pow(string $a, int $e) : string } /** - * Algorithm from: https://www.geeksforgeeks.org/modular-exponentiation-power-in-modular-arithmetic/ + * Algorithm from: https://www.geeksforgeeks.org/modular-exponentiation-power-in-modular-arithmetic/. */ - public function modPow(string $base, string $exp, string $mod) : string + #[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) - if ($base === '0' && $exp === '0' && $mod === '1') { - return '0'; - } + // normalize to Euclidean representative so modPow() stays consistent with mod() + $base = $this->mod($base, $mod); // special case: the algorithm below fails with power 0 mod 1 (returns 1 instead of 0) if ($exp === '0' && $mod === '1') { @@ -239,20 +258,21 @@ public function modPow(string $base, string $exp, string $mod) : string } /** - * Adapted from https://cp-algorithms.com/num_methods/roots_newton.html + * Adapted from https://cp-algorithms.com/num_methods/roots_newton.html. */ - public function sqrt(string $n) : string + #[Override] + public function sqrt(string $n): string { if ($n === '0') { return '0'; } // initial approximation - $x = \str_repeat('9', \intdiv(\strlen($n), 2) ?: 1); + $x = str_repeat('9', intdiv(strlen($n), 2) ?: 1); $decreased = false; - for (;;) { + for (; ;) { $nx = $this->divQ($this->add($x, $this->divQ($n, $x)), '2'); if ($x === $nx || $this->cmp($nx, $x) > 0 && $decreased) { @@ -268,38 +288,39 @@ public function sqrt(string $n) : string /** * Performs the addition of two non-signed large integers. + * + * @pure */ - private function doAdd(string $a, string $b) : string + private function doAdd(string $a, string $b): string { [$a, $b, $length] = $this->pad($a, $b); $carry = 0; $result = ''; - for ($i = $length - $this->maxDigits;; $i -= $this->maxDigits) { + for ($i = $length - $this->maxDigits; ; $i -= $this->maxDigits) { $blockLength = $this->maxDigits; if ($i < 0) { $blockLength += $i; - /** @psalm-suppress LoopInvalidation */ $i = 0; } - /** @psalm-var numeric-string $blockA */ - $blockA = \substr($a, $i, $blockLength); + /** @var numeric-string $blockA */ + $blockA = substr($a, $i, $blockLength); - /** @psalm-var numeric-string $blockB */ - $blockB = \substr($b, $i, $blockLength); + /** @var numeric-string $blockB */ + $blockB = substr($b, $i, $blockLength); $sum = (string) ($blockA + $blockB + $carry); - $sumLength = \strlen($sum); + $sumLength = strlen($sum); if ($sumLength > $blockLength) { - $sum = \substr($sum, 1); + $sum = substr($sum, 1); $carry = 1; } else { if ($sumLength < $blockLength) { - $sum = \str_repeat('0', $blockLength - $sumLength) . $sum; + $sum = str_repeat('0', $blockLength - $sumLength) . $sum; } $carry = 0; } @@ -320,8 +341,10 @@ private function doAdd(string $a, string $b) : string /** * Performs the subtraction of two non-signed large integers. + * + * @pure */ - private function doSub(string $a, string $b) : string + private function doSub(string $a, string $b): string { if ($a === $b) { return '0'; @@ -345,20 +368,19 @@ private function doSub(string $a, string $b) : string $complement = 10 ** $this->maxDigits; - for ($i = $length - $this->maxDigits;; $i -= $this->maxDigits) { + for ($i = $length - $this->maxDigits; ; $i -= $this->maxDigits) { $blockLength = $this->maxDigits; if ($i < 0) { $blockLength += $i; - /** @psalm-suppress LoopInvalidation */ $i = 0; } - /** @psalm-var numeric-string $blockA */ - $blockA = \substr($a, $i, $blockLength); + /** @var numeric-string $blockA */ + $blockA = substr($a, $i, $blockLength); - /** @psalm-var numeric-string $blockB */ - $blockB = \substr($b, $i, $blockLength); + /** @var numeric-string $blockB */ + $blockB = substr($b, $i, $blockLength); $sum = $blockA - $blockB - $carry; @@ -370,10 +392,10 @@ private function doSub(string $a, string $b) : string } $sum = (string) $sum; - $sumLength = \strlen($sum); + $sumLength = strlen($sum); if ($sumLength < $blockLength) { - $sum = \str_repeat('0', $blockLength - $sumLength) . $sum; + $sum = str_repeat('0', $blockLength - $sumLength) . $sum; } $result = $sum . $result; @@ -386,7 +408,7 @@ private function doSub(string $a, string $b) : string // Carry cannot be 1 when the loop ends, as a > b assert($carry === 0); - $result = \ltrim($result, '0'); + $result = ltrim($result, '0'); if ($invert) { $result = $this->neg($result); @@ -397,48 +419,48 @@ private function doSub(string $a, string $b) : string /** * Performs the multiplication of two non-signed large integers. + * + * @pure */ - private function doMul(string $a, string $b) : string + private function doMul(string $a, string $b): string { - $x = \strlen($a); - $y = \strlen($b); + $x = strlen($a); + $y = strlen($b); - $maxDigits = \intdiv($this->maxDigits, 2); + $maxDigits = intdiv($this->maxDigits, 2); $complement = 10 ** $maxDigits; $result = '0'; - for ($i = $x - $maxDigits;; $i -= $maxDigits) { + for ($i = $x - $maxDigits; ; $i -= $maxDigits) { $blockALength = $maxDigits; if ($i < 0) { $blockALength += $i; - /** @psalm-suppress LoopInvalidation */ $i = 0; } - $blockA = (int) \substr($a, $i, $blockALength); + $blockA = (int) substr($a, $i, $blockALength); $line = ''; $carry = 0; - for ($j = $y - $maxDigits;; $j -= $maxDigits) { + for ($j = $y - $maxDigits; ; $j -= $maxDigits) { $blockBLength = $maxDigits; if ($j < 0) { $blockBLength += $j; - /** @psalm-suppress LoopInvalidation */ $j = 0; } - $blockB = (int) \substr($b, $j, $blockBLength); + $blockB = (int) substr($b, $j, $blockBLength); $mul = $blockA * $blockB + $carry; $value = $mul % $complement; $carry = ($mul - $value) / $complement; $value = (string) $value; - $value = \str_pad($value, $maxDigits, '0', STR_PAD_LEFT); + $value = str_pad($value, $maxDigits, '0', STR_PAD_LEFT); $line = $value . $line; @@ -451,10 +473,10 @@ private function doMul(string $a, string $b) : string $line = $carry . $line; } - $line = \ltrim($line, '0'); + $line = ltrim($line, '0'); if ($line !== '') { - $line .= \str_repeat('0', $x - $blockALength - $i); + $line .= str_repeat('0', $x - $blockALength - $i); $result = $this->add($result, $line); } @@ -470,8 +492,10 @@ private function doMul(string $a, string $b) : string * Performs the division of two non-signed large integers. * * @return string[] The quotient and remainder. + * + * @pure */ - private function doDiv(string $a, string $b) : array + private function doDiv(string $a, string $b): array { $cmp = $this->doCmp($a, $b); @@ -479,8 +503,8 @@ private function doDiv(string $a, string $b) : array return ['0', $a]; } - $x = \strlen($a); - $y = \strlen($b); + $x = strlen($a); + $y = strlen($b); // we now know that a >= b && x >= y @@ -488,8 +512,24 @@ private function doDiv(string $a, string $b) : array $r = $a; // remainder $z = $y; // focus length, always $y or $y+1 - for (;;) { - $focus = \substr($a, 0, $z); + /** @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); $cmp = $this->doCmp($focus, $b); @@ -501,7 +541,7 @@ private function doDiv(string $a, string $b) : array $z++; } - $zeros = \str_repeat('0', $x - $z); + $zeros = str_repeat('0', $x - $z); $q = $this->add($q, '1' . $zeros); $a = $this->sub($a, $b . $zeros); @@ -512,7 +552,7 @@ private function doDiv(string $a, string $b) : array break; } - $x = \strlen($a); + $x = strlen($a); if ($x < $y) { // remainder < dividend break; @@ -527,12 +567,14 @@ private function doDiv(string $a, string $b) : array /** * Compares two non-signed large numbers. * - * @psalm-return -1|0|1 + * @return -1|0|1 + * + * @pure */ - private function doCmp(string $a, string $b) : int + private function doCmp(string $a, string $b): int { - $x = \strlen($a); - $y = \strlen($b); + $x = strlen($a); + $y = strlen($b); $cmp = $x <=> $y; @@ -540,7 +582,7 @@ private function doCmp(string $a, string $b) : int return $cmp; } - return \strcmp($a, $b) <=> 0; // enforce -1|0|1 + return strcmp($a, $b) <=> 0; // enforce -1|0|1 } /** @@ -549,20 +591,22 @@ private function doCmp(string $a, string $b) : int * The numbers must only consist of digits, without leading minus sign. * * @return array{string, string, int} + * + * @pure */ - private function pad(string $a, string $b) : array + private function pad(string $a, string $b): array { - $x = \strlen($a); - $y = \strlen($b); + $x = strlen($a); + $y = strlen($b); if ($x > $y) { - $b = \str_repeat('0', $x - $y) . $b; + $b = str_repeat('0', $x - $y) . $b; return [$a, $b, $x]; } if ($x < $y) { - $a = \str_repeat('0', $y - $x) . $a; + $a = str_repeat('0', $y - $x) . $a; return [$a, $b, $y]; } diff --git a/brick/math/src/Internal/CalculatorRegistry.php b/brick/math/src/Internal/CalculatorRegistry.php new file mode 100644 index 000000000..859d08a29 --- /dev/null +++ b/brick/math/src/Internal/CalculatorRegistry.php @@ -0,0 +1,74 @@ +divQ($d, (string) $prime); + $scale++; + } + } + + return $d === '1' ? $scale : null; + } + + /** + * Scales an unscaled decimal value to the requested scale. + * + * Returns null when rounding is necessary and the rounding mode is Unnecessary. + * + * @param string $value The unscaled value. + * @param int $currentScale The current scale. + * @param int $targetScale The target scale. + * @param RoundingMode $roundingMode The rounding mode. + * + * @return string|null The unscaled value at the target scale, or null if RoundingMode::Unnecessary is used and rounding is necessary. + * + * @pure + */ + public static function scale(string $value, int $currentScale, int $targetScale, RoundingMode $roundingMode): ?string + { + $scaled = self::tryScaleExactly($value, $currentScale, $targetScale); + + if ($scaled !== null) { + return $scaled; + } + + if ($roundingMode === RoundingMode::Unnecessary) { + return null; + } + + $divisor = '1' . str_repeat('0', $currentScale - $targetScale); + + return CalculatorRegistry::get()->divRound($value, $divisor, $roundingMode); + } + + /** + * Adds leading zeros if necessary to represent the full decimal number. + * + * @param string $value The unscaled value. + * @param int $scale The current scale. + * + * @pure + */ + public static function padUnscaledValue(string $value, int $scale): string + { + $targetLength = $scale + 1; + $negative = ($value[0] === '-'); + $length = strlen($value); + + if ($negative) { + $length--; + } + + if ($length >= $targetLength) { + return $value; + } + + if ($negative) { + $value = substr($value, 1); + } + + $value = str_pad($value, $targetLength, '0', STR_PAD_LEFT); + + if ($negative) { + $value = '-' . $value; + } + + return $value; + } + + /** + * Tries to scale exactly without rounding, returning null when rounding would be required. + * + * @param string $value The unscaled value. + * @param int $currentScale The current scale. + * @param int $targetScale The target scale. + * + * @return string|null The unscaled value at the target scale, or null if rounding would be required. + * + * @pure + */ + public static function tryScaleExactly(string $value, int $currentScale, int $targetScale): ?string + { + if ($value === '0' || $targetScale === $currentScale) { + return $value; + } + + if ($targetScale > $currentScale) { + return $value . str_repeat('0', $targetScale - $currentScale); + } + + $negative = ($value[0] === '-'); + if ($negative) { + $value = substr($value, 1); + } + + $value = self::padUnscaledValue($value, $currentScale); + $discardedDigits = $currentScale - $targetScale; + + if (substr($value, -$discardedDigits) !== str_repeat('0', $discardedDigits)) { + return null; + } + + $value = substr($value, 0, -$discardedDigits); + $value = ltrim($value, '0'); + + if ($value === '') { + return '0'; + } + + if ($negative) { + $value = '-' . $value; + } + + return $value; + } +} diff --git a/brick/math/src/Internal/Safe.php b/brick/math/src/Internal/Safe.php new file mode 100644 index 000000000..0966c5fcb --- /dev/null +++ b/brick/math/src/Internal/Safe.php @@ -0,0 +1,81 @@ += 0.5; otherwise, behaves as for DOWN. + * 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. */ - case HALF_UP; + case HalfUp; /** * 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. + * Behaves as for Up if the discarded fraction is > 0.5; otherwise, behaves as for Down. */ - case HALF_DOWN; + case HalfDown; /** * 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. + * If the result is positive, behaves as for HalfUp; if negative, behaves as for HalfDown. */ - case HALF_CEILING; + case HalfCeiling; /** * 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. + * If the result is positive, behaves as for HalfDown; if negative, behaves as for HalfUp. */ - case HALF_FLOOR; + case HalfFloor; /** * 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. + * Behaves as for HalfUp if the digit to the left of the discarded fraction is odd; + * behaves as for HalfDown 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. + * It is sometimes known as "Banker's rounding", and is the default rounding mode in IEEE 754. */ - case HALF_EVEN; + case HalfEven; } diff --git a/composer.json b/composer.json index 1e8c01e34..c56712dd4 100644 --- a/composer.json +++ b/composer.json @@ -71,7 +71,7 @@ "symfony/string": "^7.4.15", "symfony/translation": "^6.4.4", "wapmorgan/mp3info": "^0.1.1", - "web-auth/webauthn-lib": "^4.9.1" + "web-auth/webauthn-lib": "^5.3.5" }, "replace": { "paragonie/random_compat": "*", diff --git a/composer.lock b/composer.lock index 218ad28ff..548aaeeaa 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b47e22e2def372440b2f2044e1c016d2", + "content-hash": "0f29300a5e953ea7ef83eacc80806de1", "packages": [ { "name": "aws/aws-crt-php", @@ -193,25 +193,24 @@ }, { "name": "brick/math", - "version": "0.12.1", + "version": "0.18.0", "source": { "type": "git", "url": "https://github.com/brick/math.git", - "reference": "f510c0a40911935b77b86859eb5223d58d660df1" + "reference": "82944324d1c1bdb2c2618e89978d4e2ad78d69ad" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brick/math/zipball/f510c0a40911935b77b86859eb5223d58d660df1", - "reference": "f510c0a40911935b77b86859eb5223d58d660df1", + "url": "https://api.github.com/repos/brick/math/zipball/82944324d1c1bdb2c2618e89978d4e2ad78d69ad", + "reference": "82944324d1c1bdb2c2618e89978d4e2ad78d69ad", "shasum": "" }, "require": { - "php": "^8.1" + "php": "^8.2" }, "require-dev": { - "php-coveralls/php-coveralls": "^2.2", - "phpunit/phpunit": "^10.1", - "vimeo/psalm": "5.16.0" + "phpstan/phpstan": "2.1.22", + "phpunit/phpunit": "^11.5" }, "type": "library", "autoload": { @@ -241,7 +240,7 @@ ], "support": { "issues": "https://github.com/brick/math/issues", - "source": "https://github.com/brick/math/tree/0.12.1" + "source": "https://github.com/brick/math/tree/0.18.0" }, "funding": [ { @@ -249,7 +248,7 @@ "type": "github" } ], - "time": "2023-11-29T23:19:16+00:00" + "time": "2026-06-14T18:21:03+00:00" }, { "name": "cweagans/composer-patches", @@ -1836,70 +1835,6 @@ }, "time": "2025-03-19T13:51:03+00:00" }, - { - "name": "lcobucci/clock", - "version": "3.5.0", - "source": { - "type": "git", - "url": "https://github.com/lcobucci/clock.git", - "reference": "a3139d9e97d47826f27e6a17bb63f13621f86058" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/lcobucci/clock/zipball/a3139d9e97d47826f27e6a17bb63f13621f86058", - "reference": "a3139d9e97d47826f27e6a17bb63f13621f86058", - "shasum": "" - }, - "require": { - "php": "~8.3.0 || ~8.4.0 || ~8.5.0", - "psr/clock": "^1.0" - }, - "provide": { - "psr/clock-implementation": "1.0" - }, - "require-dev": { - "infection/infection": "^0.31", - "lcobucci/coding-standard": "^11.2.0", - "phpstan/extension-installer": "^1.3.1", - "phpstan/phpstan": "^2.0.0", - "phpstan/phpstan-deprecation-rules": "^2.0.0", - "phpstan/phpstan-phpunit": "^2.0.0", - "phpstan/phpstan-strict-rules": "^2.0.0", - "phpunit/phpunit": "^12.0.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Lcobucci\\Clock\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Luís Cobucci", - "email": "lcobucci@gmail.com" - } - ], - "description": "Yet another clock abstraction", - "support": { - "issues": "https://github.com/lcobucci/clock/issues", - "source": "https://github.com/lcobucci/clock/tree/3.5.0" - }, - "funding": [ - { - "url": "https://github.com/lcobucci", - "type": "github" - }, - { - "url": "https://www.patreon.com/lcobucci", - "type": "patreon" - } - ], - "time": "2025-10-27T09:03:17+00:00" - }, { "name": "marc-mabe/php-enum", "version": "v4.7.1", @@ -2932,6 +2867,182 @@ }, "time": "2025-05-30T09:26:42+00:00" }, + { + "name": "phpdocumentor/reflection-common", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-2.x": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" + }, + "time": "2020-06-27T09:03:43+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "6.0.3", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "7bae67520aa9f5ecc506d646810bd40d9da54582" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/7bae67520aa9f5ecc506d646810bd40d9da54582", + "reference": "7bae67520aa9f5ecc506d646810bd40d9da54582", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.1", + "ext-filter": "*", + "php": "^7.4 || ^8.0", + "phpdocumentor/reflection-common": "^2.2", + "phpdocumentor/type-resolver": "^2.0", + "phpstan/phpdoc-parser": "^2.0", + "webmozart/assert": "^1.9.1 || ^2" + }, + "require-dev": { + "mockery/mockery": "~1.3.5 || ~1.6.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-webmozart-assert": "^1.2", + "phpunit/phpunit": "^9.5", + "psalm/phar": "^5.26", + "shipmonk/dead-code-detector": "^0.5.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/6.0.3" + }, + "time": "2026-03-18T20:49:53+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "327a05bbee54120d4786a0dc67aad30226ad4cf9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/327a05bbee54120d4786a0dc67aad30226ad4cf9", + "reference": "327a05bbee54120d4786a0dc67aad30226ad4cf9", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.0", + "php": "^7.4 || ^8.0", + "phpdocumentor/reflection-common": "^2.0", + "phpstan/phpdoc-parser": "^2.0" + }, + "require-dev": { + "ext-tokenizer": "*", + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^9.5", + "psalm/phar": "^4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-1.x": "1.x-dev", + "dev-2.x": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "support": { + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/2.0.0" + }, + "time": "2026-01-06T21:53:42+00:00" + }, { "name": "phpseclib/phpseclib", "version": "3.0.55", @@ -3042,6 +3153,53 @@ ], "time": "2026-06-14T23:24:10+00:00" }, + { + "name": "phpstan/phpdoc-parser", + "version": "2.3.3", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "fb19eedd2bb67ff8cf7a5502ad329e701d6398a3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/fb19eedd2bb67ff8cf7a5502ad329e701d6398a3", + "reference": "fb19eedd2bb67ff8cf7a5502ad329e701d6398a3", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "doctrine/annotations": "^2.0", + "nikic/php-parser": "^5.3.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.6", + "symfony/process": "^5.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPDoc parser with support for nullable, intersection and generic types", + "support": { + "issues": "https://github.com/phpstan/phpdoc-parser/issues", + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.3" + }, + "time": "2026-07-08T07:01:06+00:00" + }, { "name": "pimple/pimple", "version": "v3.6.0", @@ -4146,40 +4304,28 @@ }, { "name": "spomky-labs/cbor-php", - "version": "3.0.4", + "version": "3.3.0", "source": { "type": "git", "url": "https://github.com/Spomky-Labs/cbor-php.git", - "reference": "658ed12a85a6b31fa312b89cd92f3a4ce6df4c6b" + "reference": "013d13da69cf28b1ae501887daceccc850ca1c76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Spomky-Labs/cbor-php/zipball/658ed12a85a6b31fa312b89cd92f3a4ce6df4c6b", - "reference": "658ed12a85a6b31fa312b89cd92f3a4ce6df4c6b", + "url": "https://api.github.com/repos/Spomky-Labs/cbor-php/zipball/013d13da69cf28b1ae501887daceccc850ca1c76", + "reference": "013d13da69cf28b1ae501887daceccc850ca1c76", "shasum": "" }, "require": { - "brick/math": "^0.9|^0.10|^0.11|^0.12", + "brick/math": "^0.9|^0.10|^0.11|^0.12|^0.13|^0.14|^0.15|^0.16|^0.17|^0.18", "ext-mbstring": "*", "php": ">=8.0" }, "require-dev": { - "ekino/phpstan-banned-code": "^1.0", "ext-json": "*", - "infection/infection": "^0.27", - "php-parallel-lint/php-parallel-lint": "^1.3", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.0", - "phpstan/phpstan-beberlei-assert": "^1.0", - "phpstan/phpstan-deprecation-rules": "^1.0", - "phpstan/phpstan-phpunit": "^1.0", - "phpstan/phpstan-strict-rules": "^1.0", - "phpunit/phpunit": "^10.1", - "qossmic/deptrac-shim": "^1.0", - "rector/rector": "^0.19", "roave/security-advisories": "dev-latest", - "symfony/var-dumper": "^6.0|^7.0", - "symplify/easy-coding-standard": "^12.0" + "symfony/error-handler": "^6.4|^7.1|^8.0", + "symfony/var-dumper": "^6.4|^7.1|^8.0" }, "suggest": { "ext-bcmath": "GMP or BCMath extensions will drastically improve the library performance. BCMath extension needed to handle the Big Float and Decimal Fraction Tags", @@ -4213,7 +4359,7 @@ ], "support": { "issues": "https://github.com/Spomky-Labs/cbor-php/issues", - "source": "https://github.com/Spomky-Labs/cbor-php/tree/3.0.4" + "source": "https://github.com/Spomky-Labs/cbor-php/tree/3.3.0" }, "funding": [ { @@ -4225,46 +4371,44 @@ "type": "patreon" } ], - "time": "2024-01-29T20:33:48+00:00" + "time": "2026-07-15T18:56:27+00:00" }, { "name": "spomky-labs/pki-framework", - "version": "1.2.1", + "version": "1.6.0", "source": { "type": "git", "url": "https://github.com/Spomky-Labs/pki-framework.git", - "reference": "0b10c8b53366729417d6226ae89a665f9e2d61b6" + "reference": "80778a25426288acd2e3a7cde2def41a3d59cddf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Spomky-Labs/pki-framework/zipball/0b10c8b53366729417d6226ae89a665f9e2d61b6", - "reference": "0b10c8b53366729417d6226ae89a665f9e2d61b6", + "url": "https://api.github.com/repos/Spomky-Labs/pki-framework/zipball/80778a25426288acd2e3a7cde2def41a3d59cddf", + "reference": "80778a25426288acd2e3a7cde2def41a3d59cddf", "shasum": "" }, "require": { - "brick/math": "^0.10|^0.11|^0.12", + "brick/math": "^0.10|^0.11|^0.12|^0.13|^0.14|^0.15|^0.16|^0.17|^0.18|^0.19", "ext-mbstring": "*", "php": ">=8.1" }, "require-dev": { - "ekino/phpstan-banned-code": "^1.0", + "ekino/phpstan-banned-code": "^1.0|^2.0|^3.0", "ext-gmp": "*", "ext-openssl": "*", - "infection/infection": "^0.28", + "infection/infection": "^0.28|^0.29|^0.31", "php-parallel-lint/php-parallel-lint": "^1.3", - "phpstan/extension-installer": "^1.3", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-beberlei-assert": "^1.0", - "phpstan/phpstan-deprecation-rules": "^1.0", - "phpstan/phpstan-phpunit": "^1.1", - "phpstan/phpstan-strict-rules": "^1.3", - "phpunit/phpunit": "^10.1|^11.0", - "rector/rector": "^1.0", + "phpstan/extension-installer": "^1.3|^2.0", + "phpstan/phpstan": "^1.8|^2.0", + "phpstan/phpstan-deprecation-rules": "^1.0|^2.0", + "phpstan/phpstan-phpunit": "^1.1|^2.0", + "phpstan/phpstan-strict-rules": "^1.3|^2.0", + "phpunit/phpunit": "^10.1|^11.0|^12.0", + "rector/rector": "^1.0|^2.0", "roave/security-advisories": "dev-latest", - "symfony/phpunit-bridge": "^6.4|^7.0", - "symfony/string": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0", - "symplify/easy-coding-standard": "^12.0" + "symfony/string": "^6.4|^7.0|^8.0", + "symfony/var-dumper": "^6.4|^7.0|^8.0", + "symplify/easy-coding-standard": "^12.0 || ^13.0" }, "suggest": { "ext-bcmath": "For better performance (or GMP)", @@ -4324,7 +4468,7 @@ ], "support": { "issues": "https://github.com/Spomky-Labs/pki-framework/issues", - "source": "https://github.com/Spomky-Labs/pki-framework/tree/1.2.1" + "source": "https://github.com/Spomky-Labs/pki-framework/tree/1.6.0" }, "funding": [ { @@ -4336,7 +4480,7 @@ "type": "patreon" } ], - "time": "2024-03-30T18:03:49+00:00" + "time": "2026-08-06T16:21:11+00:00" }, { "name": "stecman/symfony-console-completion", @@ -4388,6 +4532,84 @@ }, "time": "2025-11-30T08:20:15+00:00" }, + { + "name": "symfony/clock", + "version": "v7.4.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/clock.git", + "reference": "674fa3b98e21531dd040e613479f5f6fa8f32111" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/clock/zipball/674fa3b98e21531dd040e613479f5f6fa8f32111", + "reference": "674fa3b98e21531dd040e613479f5f6fa8f32111", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/clock": "^1.0", + "symfony/polyfill-php83": "^1.28" + }, + "provide": { + "psr/clock-implementation": "1.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/now.php" + ], + "psr-4": { + "Symfony\\Component\\Clock\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Decouples applications from the system clock", + "homepage": "https://symfony.com", + "keywords": [ + "clock", + "psr20", + "time" + ], + "support": { + "source": "https://github.com/symfony/clock/tree/v7.4.8" + }, + "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": "2026-03-24T13:12:05+00:00" + }, { "name": "symfony/console", "version": "v7.4.15", @@ -5684,20 +5906,20 @@ }, { "name": "symfony/polyfill-uuid", - "version": "v1.29.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-uuid.git", - "reference": "3abdd21b0ceaa3000ee950097bc3cf9efc137853" + "reference": "26dfec253c4cf3e51b541b52ddf7e42cb0908e94" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/3abdd21b0ceaa3000ee950097bc3cf9efc137853", - "reference": "3abdd21b0ceaa3000ee950097bc3cf9efc137853", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/26dfec253c4cf3e51b541b52ddf7e42cb0908e94", + "reference": "26dfec253c4cf3e51b541b52ddf7e42cb0908e94", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-uuid": "*" @@ -5743,7 +5965,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/polyfill-uuid/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.37.0" }, "funding": [ { @@ -5754,12 +5976,16 @@ "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-01-29T20:11:03+00:00" + "time": "2026-04-10T16:19:22+00:00" }, { "name": "symfony/process", @@ -5827,8 +6053,179 @@ "time": "2026-01-23T16:02:12+00:00" }, { - "name": "symfony/routing", - "version": "v6.4.41", + "name": "symfony/property-access", + "version": "v7.4.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/property-access.git", + "reference": "b7dad9dae8b8a47ef7ecc76c8569e7d8c7d90cfc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/property-access/zipball/b7dad9dae8b8a47ef7ecc76c8569e7d8c7d90cfc", + "reference": "b7dad9dae8b8a47ef7ecc76c8569e7d8c7d90cfc", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/property-info": "^6.4.32|~7.3.10|^7.4.4|^8.0.4" + }, + "require-dev": { + "symfony/cache": "^6.4|^7.0|^8.0", + "symfony/var-exporter": "^6.4.1|^7.0.1|^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\PropertyAccess\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides functions to read and write from/to an object or array using a simple string notation", + "homepage": "https://symfony.com", + "keywords": [ + "access", + "array", + "extraction", + "index", + "injection", + "object", + "property", + "property-path", + "reflection" + ], + "support": { + "source": "https://github.com/symfony/property-access/tree/v7.4.8" + }, + "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": "2026-03-24T13:12:05+00:00" + }, + { + "name": "symfony/property-info", + "version": "v7.4.15", + "source": { + "type": "git", + "url": "https://github.com/symfony/property-info.git", + "reference": "fce3f4d9cfeb4ddc674c357b5a4c3a23ccf408ad" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/property-info/zipball/fce3f4d9cfeb4ddc674c357b5a4c3a23ccf408ad", + "reference": "fce3f4d9cfeb4ddc674c357b5a4c3a23ccf408ad", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/string": "^6.4|^7.0|^8.0", + "symfony/type-info": "^7.4.7|^8.0.7" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "<5.2|>=7", + "phpdocumentor/type-resolver": "<1.5.1", + "symfony/cache": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/serializer": "<6.4" + }, + "require-dev": { + "phpdocumentor/reflection-docblock": "^5.2|^6.0", + "phpstan/phpdoc-parser": "^1.0|^2.0", + "symfony/cache": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/serializer": "^6.4|^7.0|^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\PropertyInfo\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kévin Dunglas", + "email": "dunglas@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Extracts information about PHP class' properties using metadata of popular sources", + "homepage": "https://symfony.com", + "keywords": [ + "doctrine", + "phpdoc", + "property", + "symfony", + "type", + "validator" + ], + "support": { + "source": "https://github.com/symfony/property-info/tree/v7.4.15" + }, + "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": "2026-07-28T07:09:44+00:00" + }, + { + "name": "symfony/routing", + "version": "v6.4.41", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", @@ -5913,6 +6310,110 @@ ], "time": "2026-05-24T11:18:16+00:00" }, + { + "name": "symfony/serializer", + "version": "v7.4.15", + "source": { + "type": "git", + "url": "https://github.com/symfony/serializer.git", + "reference": "917f1575bec2853f45e012d8718f518365a9d258" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/serializer/zipball/917f1575bec2853f45e012d8718f518365a9d258", + "reference": "917f1575bec2853f45e012d8718f518365a9d258", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-php84": "^1.30" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "<5.2|>=7", + "phpdocumentor/type-resolver": "<1.5.1", + "symfony/dependency-injection": "<6.4", + "symfony/property-access": "<6.4.31|>=7.0,<7.4.2|>=8.0,<8.0.2", + "symfony/property-info": "<6.4.43", + "symfony/type-info": "<7.2.5", + "symfony/uid": "<6.4", + "symfony/validator": "<6.4", + "symfony/yaml": "<6.4" + }, + "require-dev": { + "phpdocumentor/reflection-docblock": "^5.2|^6.0", + "phpstan/phpdoc-parser": "^1.0|^2.0", + "seld/jsonlint": "^1.10", + "symfony/cache": "^6.4|^7.0|^8.0", + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^7.2|^8.0", + "symfony/error-handler": "^6.4|^7.0|^8.0", + "symfony/filesystem": "^6.4|^7.0|^8.0", + "symfony/form": "^6.4|^7.0|^8.0", + "symfony/http-foundation": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/messenger": "^6.4|^7.0|^8.0", + "symfony/mime": "^6.4|^7.0|^8.0", + "symfony/property-access": "^6.4.31|^7.4.2|^8.0.2", + "symfony/property-info": "^6.4.43|^7.4.15|^8.0.15", + "symfony/translation-contracts": "^2.5|^3", + "symfony/type-info": "^7.2.5|^8.0", + "symfony/uid": "^6.4|^7.0|^8.0", + "symfony/validator": "^6.4|^7.0|^8.0", + "symfony/var-dumper": "^6.4|^7.0|^8.0", + "symfony/var-exporter": "^6.4|^7.0|^8.0", + "symfony/yaml": "^6.4|^7.0|^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Serializer\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/serializer/tree/v7.4.15" + }, + "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": "2026-07-29T07:59:49+00:00" + }, { "name": "symfony/service-contracts", "version": "v3.7.0", @@ -6268,26 +6769,109 @@ ], "time": "2024-09-25T14:18:03+00:00" }, + { + "name": "symfony/type-info", + "version": "v7.4.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/type-info.git", + "reference": "cafeedbf157b890e94ac5b83eaed85595106d5d6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/type-info/zipball/cafeedbf157b890e94ac5b83eaed85595106d5d6", + "reference": "cafeedbf157b890e94ac5b83eaed85595106d5d6", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "phpstan/phpdoc-parser": "<1.30" + }, + "require-dev": { + "phpstan/phpdoc-parser": "^1.30|^2.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\TypeInfo\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mathias Arlaud", + "email": "mathias.arlaud@gmail.com" + }, + { + "name": "Baptiste LEDUC", + "email": "baptiste.leduc@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Extracts PHP types information.", + "homepage": "https://symfony.com", + "keywords": [ + "PHPStan", + "phpdoc", + "symfony", + "type" + ], + "support": { + "source": "https://github.com/symfony/type-info/tree/v7.4.9" + }, + "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": "2026-04-22T15:21:55+00:00" + }, { "name": "symfony/uid", - "version": "v6.4.32", + "version": "v7.4.9", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "6b973c385f00341b246f697d82dc01a09107acdd" + "reference": "2676b524340abcfe4d6151ec698463cebafee439" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/6b973c385f00341b246f697d82dc01a09107acdd", - "reference": "6b973c385f00341b246f697d82dc01a09107acdd", + "url": "https://api.github.com/repos/symfony/uid/zipball/2676b524340abcfe4d6151ec698463cebafee439", + "reference": "2676b524340abcfe4d6151ec698463cebafee439", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/polyfill-uuid": "^1.15" }, "require-dev": { - "symfony/console": "^5.4|^6.0|^7.0" + "symfony/console": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -6324,7 +6908,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v6.4.32" + "source": "https://github.com/symfony/uid/tree/v7.4.9" }, "funding": [ { @@ -6344,7 +6928,7 @@ "type": "tidelift" } ], - "time": "2025-12-23T15:07:59+00:00" + "time": "2026-04-30T15:19:22+00:00" }, { "name": "wapmorgan/mp3info", @@ -6394,44 +6978,32 @@ }, { "name": "web-auth/cose-lib", - "version": "4.3.0", + "version": "4.6.0", "source": { "type": "git", "url": "https://github.com/web-auth/cose-lib.git", - "reference": "e5c417b3b90e06c84638a18d350e438d760cb955" + "reference": "3afe04df137baf97c5c3e28c5ee6f05536405148" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/web-auth/cose-lib/zipball/e5c417b3b90e06c84638a18d350e438d760cb955", - "reference": "e5c417b3b90e06c84638a18d350e438d760cb955", + "url": "https://api.github.com/repos/web-auth/cose-lib/zipball/3afe04df137baf97c5c3e28c5ee6f05536405148", + "reference": "3afe04df137baf97c5c3e28c5ee6f05536405148", "shasum": "" }, "require": { - "brick/math": "^0.9|^0.10|^0.11|^0.12", + "brick/math": "^0.9|^0.10|^0.11|^0.12|^0.13|^0.14|^0.15|^0.16|^0.17|^0.18", "ext-json": "*", - "ext-mbstring": "*", "ext-openssl": "*", "php": ">=8.1", "spomky-labs/pki-framework": "^1.0" }, "require-dev": { - "ekino/phpstan-banned-code": "^1.0", - "infection/infection": "^0.27", - "php-parallel-lint/php-parallel-lint": "^1.3", - "phpstan/extension-installer": "^1.3", - "phpstan/phpstan": "^1.7", - "phpstan/phpstan-deprecation-rules": "^1.0", - "phpstan/phpstan-phpunit": "^1.1", - "phpstan/phpstan-strict-rules": "^1.2", - "phpunit/phpunit": "^10.1", - "qossmic/deptrac-shim": "^1.0", - "rector/rector": "^0.19", - "symfony/phpunit-bridge": "^6.4|^7.0", - "symplify/easy-coding-standard": "^12.0" + "spomky-labs/cbor-php": "^3.2.2" }, "suggest": { "ext-bcmath": "For better performance, please install either GMP (recommended) or BCMath extension", - "ext-gmp": "For better performance, please install either GMP (recommended) or BCMath extension" + "ext-gmp": "For better performance, please install either GMP (recommended) or BCMath extension", + "spomky-labs/cbor-php": "For COSE Signature support" }, "type": "library", "autoload": { @@ -6461,7 +7033,7 @@ ], "support": { "issues": "https://github.com/web-auth/cose-lib/issues", - "source": "https://github.com/web-auth/cose-lib/tree/4.3.0" + "source": "https://github.com/web-auth/cose-lib/tree/4.6.0" }, "funding": [ { @@ -6473,48 +7045,44 @@ "type": "patreon" } ], - "time": "2024-02-05T21:00:39+00:00" + "time": "2026-07-16T10:19:49+00:00" }, { "name": "web-auth/webauthn-lib", - "version": "4.9.3", + "version": "5.3.5", "source": { "type": "git", "url": "https://github.com/web-auth/webauthn-lib.git", - "reference": "129fbaccd22163429a39bf85e320fb9eddad035c" + "reference": "9e0986d999f4102e24ac8a598d3a80d98b56c19f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/web-auth/webauthn-lib/zipball/129fbaccd22163429a39bf85e320fb9eddad035c", - "reference": "129fbaccd22163429a39bf85e320fb9eddad035c", + "url": "https://api.github.com/repos/web-auth/webauthn-lib/zipball/9e0986d999f4102e24ac8a598d3a80d98b56c19f", + "reference": "9e0986d999f4102e24ac8a598d3a80d98b56c19f", "shasum": "" }, "require": { "ext-json": "*", - "ext-mbstring": "*", "ext-openssl": "*", - "lcobucci/clock": "^2.2|^3.0", "paragonie/constant_time_encoding": "^2.6|^3.0", - "php": ">=8.1", + "php": ">=8.2", + "phpdocumentor/reflection-docblock": "^5.3|^6.0", "psr/clock": "^1.0", "psr/event-dispatcher": "^1.0", - "psr/http-client": "^1.0", - "psr/http-factory": "^1.0", "psr/log": "^1.0|^2.0|^3.0", "spomky-labs/cbor-php": "^3.0", "spomky-labs/pki-framework": "^1.0", + "symfony/clock": "^6.4|^7.0|^8.0", "symfony/deprecation-contracts": "^3.2", - "symfony/uid": "^6.1|^7.0", + "symfony/property-access": "^6.4|^7.0|^8.0", + "symfony/property-info": "^6.4|^7.0|^8.0", + "symfony/serializer": "^6.4|^7.0|^8.0", + "symfony/uid": "^6.4|^7.0|^8.0", "web-auth/cose-lib": "^4.2.3" }, "suggest": { - "phpdocumentor/reflection-docblock": "As of 4.5.x, the phpdocumentor/reflection-docblock component will become mandatory for converting objects such as the Metadata Statement", - "psr/clock-implementation": "As of 4.5.x, the PSR Clock implementation will replace lcobucci/clock", "psr/log-implementation": "Recommended to receive logs from the library", "symfony/event-dispatcher": "Recommended to use dispatched events", - "symfony/property-access": "As of 4.5.x, the symfony/serializer component will become mandatory for converting objects such as the Metadata Statement", - "symfony/property-info": "As of 4.5.x, the symfony/serializer component will become mandatory for converting objects such as the Metadata Statement", - "symfony/serializer": "As of 4.5.x, the symfony/serializer component will become mandatory for converting objects such as the Metadata Statement", "web-token/jwt-library": "Mandatory for fetching Metadata Statement from distant sources" }, "type": "library", @@ -6551,7 +7119,7 @@ "webauthn" ], "support": { - "source": "https://github.com/web-auth/webauthn-lib/tree/4.9.3" + "source": "https://github.com/web-auth/webauthn-lib/tree/5.3.5" }, "funding": [ { @@ -6563,7 +7131,73 @@ "type": "patreon" } ], - "time": "2026-02-05T12:48:16+00:00" + "time": "2026-05-31T15:00:08+00:00" + }, + { + "name": "webmozart/assert", + "version": "2.4.1", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "2ccb7c2e821038c03a3e6e1700c570c158c55f70" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/2ccb7c2e821038c03a3e6e1700c570c158c55f70", + "reference": "2ccb7c2e821038c03a3e6e1700c570c158c55f70", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-date": "*", + "ext-filter": "*", + "php": "^8.2" + }, + "suggest": { + "ext-intl": "", + "ext-simplexml": "", + "ext-spl": "" + }, + "type": "library", + "extra": { + "psalm": { + "pluginClass": "Webmozart\\Assert\\PsalmPlugin" + }, + "branch-alias": { + "dev-master": "2.0-dev", + "dev-feature/2-0": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + }, + { + "name": "Woody Gilk", + "email": "woody.gilk@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/2.4.1" + }, + "time": "2026-06-15T15:31:57+00:00" } ], "packages-dev": [], diff --git a/composer/autoload_classmap.php b/composer/autoload_classmap.php index 2d0b3124c..d536d9a45 100644 --- a/composer/autoload_classmap.php +++ b/composer/autoload_classmap.php @@ -412,20 +412,29 @@ 'Brick\\Math\\BigRational' => $vendorDir . '/brick/math/src/BigRational.php', 'Brick\\Math\\Exception\\DivisionByZeroException' => $vendorDir . '/brick/math/src/Exception/DivisionByZeroException.php', 'Brick\\Math\\Exception\\IntegerOverflowException' => $vendorDir . '/brick/math/src/Exception/IntegerOverflowException.php', + 'Brick\\Math\\Exception\\InvalidArgumentException' => $vendorDir . '/brick/math/src/Exception/InvalidArgumentException.php', 'Brick\\Math\\Exception\\MathException' => $vendorDir . '/brick/math/src/Exception/MathException.php', 'Brick\\Math\\Exception\\NegativeNumberException' => $vendorDir . '/brick/math/src/Exception/NegativeNumberException.php', + 'Brick\\Math\\Exception\\NoInverseException' => $vendorDir . '/brick/math/src/Exception/NoInverseException.php', 'Brick\\Math\\Exception\\NumberFormatException' => $vendorDir . '/brick/math/src/Exception/NumberFormatException.php', + 'Brick\\Math\\Exception\\RandomSourceException' => $vendorDir . '/brick/math/src/Exception/RandomSourceException.php', 'Brick\\Math\\Exception\\RoundingNecessaryException' => $vendorDir . '/brick/math/src/Exception/RoundingNecessaryException.php', + 'Brick\\Math\\Exception\\UnsupportedPlatformException' => $vendorDir . '/brick/math/src/Exception/UnsupportedPlatformException.php', 'Brick\\Math\\Internal\\Calculator' => $vendorDir . '/brick/math/src/Internal/Calculator.php', + 'Brick\\Math\\Internal\\CalculatorRegistry' => $vendorDir . '/brick/math/src/Internal/CalculatorRegistry.php', 'Brick\\Math\\Internal\\Calculator\\BcMathCalculator' => $vendorDir . '/brick/math/src/Internal/Calculator/BcMathCalculator.php', 'Brick\\Math\\Internal\\Calculator\\GmpCalculator' => $vendorDir . '/brick/math/src/Internal/Calculator/GmpCalculator.php', 'Brick\\Math\\Internal\\Calculator\\NativeCalculator' => $vendorDir . '/brick/math/src/Internal/Calculator/NativeCalculator.php', + 'Brick\\Math\\Internal\\DecimalHelper' => $vendorDir . '/brick/math/src/Internal/DecimalHelper.php', + 'Brick\\Math\\Internal\\Safe' => $vendorDir . '/brick/math/src/Internal/Safe.php', 'Brick\\Math\\RoundingMode' => $vendorDir . '/brick/math/src/RoundingMode.php', 'CBOR\\AbstractCBORObject' => $vendorDir . '/spomky-labs/cbor-php/src/AbstractCBORObject.php', 'CBOR\\ByteStringObject' => $vendorDir . '/spomky-labs/cbor-php/src/ByteStringObject.php', 'CBOR\\CBORObject' => $vendorDir . '/spomky-labs/cbor-php/src/CBORObject.php', 'CBOR\\Decoder' => $vendorDir . '/spomky-labs/cbor-php/src/Decoder.php', 'CBOR\\DecoderInterface' => $vendorDir . '/spomky-labs/cbor-php/src/DecoderInterface.php', + 'CBOR\\Encoder' => $vendorDir . '/spomky-labs/cbor-php/src/Encoder.php', + 'CBOR\\EncoderInterface' => $vendorDir . '/spomky-labs/cbor-php/src/EncoderInterface.php', 'CBOR\\IndefiniteLengthByteStringObject' => $vendorDir . '/spomky-labs/cbor-php/src/IndefiniteLengthByteStringObject.php', 'CBOR\\IndefiniteLengthListObject' => $vendorDir . '/spomky-labs/cbor-php/src/IndefiniteLengthListObject.php', 'CBOR\\IndefiniteLengthMapObject' => $vendorDir . '/spomky-labs/cbor-php/src/IndefiniteLengthMapObject.php', @@ -466,6 +475,7 @@ 'CBOR\\Tag\\GenericTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/GenericTag.php', 'CBOR\\Tag\\MimeTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/MimeTag.php', 'CBOR\\Tag\\NegativeBigIntegerTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/NegativeBigIntegerTag.php', + 'CBOR\\Tag\\SelfDescribeCBORTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/SelfDescribeCBORTag.php', 'CBOR\\Tag\\TagInterface' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/TagInterface.php', 'CBOR\\Tag\\TagManager' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/TagManager.php', 'CBOR\\Tag\\TagManagerInterface' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/TagManagerInterface.php', @@ -508,12 +518,19 @@ 'Cose\\Algorithm\\Signature\\Signature' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/Signature.php', 'Cose\\Algorithms' => $vendorDir . '/web-auth/cose-lib/src/Algorithms.php', 'Cose\\BigInteger' => $vendorDir . '/web-auth/cose-lib/src/BigInteger.php', + 'Cose\\Encryption\\CoseEncrypt0Tag' => $vendorDir . '/web-auth/cose-lib/src/Encryption/CoseEncrypt0Tag.php', + 'Cose\\Encryption\\CoseEncryptTag' => $vendorDir . '/web-auth/cose-lib/src/Encryption/CoseEncryptTag.php', 'Cose\\Hash' => $vendorDir . '/web-auth/cose-lib/src/Hash.php', 'Cose\\Key\\Ec2Key' => $vendorDir . '/web-auth/cose-lib/src/Key/Ec2Key.php', 'Cose\\Key\\Key' => $vendorDir . '/web-auth/cose-lib/src/Key/Key.php', 'Cose\\Key\\OkpKey' => $vendorDir . '/web-auth/cose-lib/src/Key/OkpKey.php', 'Cose\\Key\\RsaKey' => $vendorDir . '/web-auth/cose-lib/src/Key/RsaKey.php', 'Cose\\Key\\SymmetricKey' => $vendorDir . '/web-auth/cose-lib/src/Key/SymmetricKey.php', + 'Cose\\Mac\\CoseMac0Tag' => $vendorDir . '/web-auth/cose-lib/src/Mac/CoseMac0Tag.php', + 'Cose\\Mac\\CoseMacTag' => $vendorDir . '/web-auth/cose-lib/src/Mac/CoseMacTag.php', + 'Cose\\Signature\\CoseSign1Tag' => $vendorDir . '/web-auth/cose-lib/src/Signature/CoseSign1Tag.php', + 'Cose\\Signature\\CoseSignTag' => $vendorDir . '/web-auth/cose-lib/src/Signature/CoseSignTag.php', + 'Cose\\Signature\\Signature1' => $vendorDir . '/web-auth/cose-lib/src/Signature/Signature1.php', 'DelayedTargetValidation' => $vendorDir . '/symfony/polyfill-php85/Resources/stubs/DelayedTargetValidation.php', 'Deprecated' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/Deprecated.php', 'Doctrine\\Common\\EventArgs' => $vendorDir . '/doctrine/event-manager/src/EventArgs.php', @@ -1297,9 +1314,6 @@ 'Laravel\\SerializableClosure\\Support\\ReflectionClosure' => $vendorDir . '/laravel/serializable-closure/src/Support/ReflectionClosure.php', 'Laravel\\SerializableClosure\\Support\\SelfReference' => $vendorDir . '/laravel/serializable-closure/src/Support/SelfReference.php', 'Laravel\\SerializableClosure\\UnsignedSerializableClosure' => $vendorDir . '/laravel/serializable-closure/src/UnsignedSerializableClosure.php', - 'Lcobucci\\Clock\\Clock' => $vendorDir . '/lcobucci/clock/src/Clock.php', - 'Lcobucci\\Clock\\FrozenClock' => $vendorDir . '/lcobucci/clock/src/FrozenClock.php', - 'Lcobucci\\Clock\\SystemClock' => $vendorDir . '/lcobucci/clock/src/SystemClock.php', 'MabeEnum\\Enum' => $vendorDir . '/marc-mabe/php-enum/src/Enum.php', 'MabeEnum\\EnumMap' => $vendorDir . '/marc-mabe/php-enum/src/EnumMap.php', 'MabeEnum\\EnumSerializableTrait' => $vendorDir . '/marc-mabe/php-enum/src/EnumSerializableTrait.php', @@ -1596,6 +1610,97 @@ 'PEAR_Error' => $vendorDir . '/pear/pear-core-minimal/src/PEAR.php', 'PEAR_ErrorStack' => $vendorDir . '/pear/pear-core-minimal/src/PEAR/ErrorStack.php', 'PEAR_Exception' => $vendorDir . '/pear/pear_exception/PEAR/Exception.php', + 'PHPStan\\PhpDocParser\\Ast\\AbstractNodeVisitor' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/AbstractNodeVisitor.php', + 'PHPStan\\PhpDocParser\\Ast\\Attribute' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Attribute.php', + 'PHPStan\\PhpDocParser\\Ast\\Comment' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Comment.php', + 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprArrayItemNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayItemNode.php', + 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprArrayNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayNode.php', + 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprFalseNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFalseNode.php', + 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprFloatNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFloatNode.php', + 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprIntegerNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprIntegerNode.php', + 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNode.php', + 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprNullNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNullNode.php', + 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprStringNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprStringNode.php', + 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprTrueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprTrueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstFetchNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstFetchNode.php', + 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\DoctrineConstExprStringNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/DoctrineConstExprStringNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Node' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Node.php', + 'PHPStan\\PhpDocParser\\Ast\\NodeAttributes' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/NodeAttributes.php', + 'PHPStan\\PhpDocParser\\Ast\\NodeTraverser' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/NodeTraverser.php', + 'PHPStan\\PhpDocParser\\Ast\\NodeVisitor' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/NodeVisitor.php', + 'PHPStan\\PhpDocParser\\Ast\\NodeVisitor\\CloningVisitor' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/NodeVisitor/CloningVisitor.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\AssertTagMethodValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagMethodValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\AssertTagPropertyValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagPropertyValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\AssertTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\DeprecatedTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/DeprecatedTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineAnnotation' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineAnnotation.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineArgument' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArgument.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineArray' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArray.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineArrayItem' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArrayItem.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ExtendsTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ExtendsTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\GenericTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/GenericTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ImplementsTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ImplementsTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\InvalidTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/InvalidTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MethodTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MethodTagValueParameterNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueParameterNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MixinTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/MixinTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamClosureThisTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamClosureThisTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamImmediatelyInvokedCallableTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamImmediatelyInvokedCallableTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamLaterInvokedCallableTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamLaterInvokedCallableTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamOutTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamOutTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocChildNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocChildNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTagNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTextNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTextNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PropertyTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PropertyTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PureUnlessCallableIsImpureTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PureUnlessCallableIsImpureTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PureUnlessParameterIsPassedTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PureUnlessParameterIsPassedTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\RequireExtendsTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireExtendsTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\RequireImplementsTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireImplementsTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ReturnTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ReturnTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\SealedTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/SealedTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\SelfOutTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/SelfOutTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TemplateTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/TemplateTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ThrowsTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ThrowsTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TypeAliasImportTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasImportTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TypeAliasTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TypelessParamTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypelessParamTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\UsesTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/UsesTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\VarTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/VarTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\ArrayShapeItemNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeItemNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\ArrayShapeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\ArrayShapeUnsealedTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeUnsealedTypeNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\ArrayTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayTypeNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\CallableTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\CallableTypeParameterNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeParameterNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\ConditionalTypeForParameterNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeForParameterNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\ConditionalTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\ConstTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ConstTypeNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\GenericTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/GenericTypeNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\IdentifierTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/IdentifierTypeNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\IntersectionTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/IntersectionTypeNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\InvalidTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/InvalidTypeNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\NullableTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/NullableTypeNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\ObjectShapeItemNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeItemNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\ObjectShapeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\OffsetAccessTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/OffsetAccessTypeNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\ThisTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ThisTypeNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\TypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/TypeNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\UnionTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/UnionTypeNode.php', + 'PHPStan\\PhpDocParser\\Lexer\\Lexer' => $vendorDir . '/phpstan/phpdoc-parser/src/Lexer/Lexer.php', + 'PHPStan\\PhpDocParser\\ParserConfig' => $vendorDir . '/phpstan/phpdoc-parser/src/ParserConfig.php', + 'PHPStan\\PhpDocParser\\Parser\\ConstExprParser' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php', + 'PHPStan\\PhpDocParser\\Parser\\ParserException' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/ParserException.php', + 'PHPStan\\PhpDocParser\\Parser\\PhpDocParser' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/PhpDocParser.php', + 'PHPStan\\PhpDocParser\\Parser\\StringUnescaper' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/StringUnescaper.php', + 'PHPStan\\PhpDocParser\\Parser\\TokenIterator' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/TokenIterator.php', + 'PHPStan\\PhpDocParser\\Parser\\TypeParser' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/TypeParser.php', + 'PHPStan\\PhpDocParser\\Printer\\DiffElem' => $vendorDir . '/phpstan/phpdoc-parser/src/Printer/DiffElem.php', + 'PHPStan\\PhpDocParser\\Printer\\Differ' => $vendorDir . '/phpstan/phpdoc-parser/src/Printer/Differ.php', + 'PHPStan\\PhpDocParser\\Printer\\Printer' => $vendorDir . '/phpstan/phpdoc-parser/src/Printer/Printer.php', 'ParagonIE\\ConstantTime\\Base32' => $vendorDir . '/paragonie/constant_time_encoding/src/Base32.php', 'ParagonIE\\ConstantTime\\Base32Hex' => $vendorDir . '/paragonie/constant_time_encoding/src/Base32Hex.php', 'ParagonIE\\ConstantTime\\Base64' => $vendorDir . '/paragonie/constant_time_encoding/src/Base64.php', @@ -3003,6 +3108,13 @@ 'Stecman\\Component\\Symfony\\Console\\BashCompletion\\EnvironmentCompletionContext' => $vendorDir . '/stecman/symfony-console-completion/src/EnvironmentCompletionContext.php', 'Stecman\\Component\\Symfony\\Console\\BashCompletion\\HookFactory' => $vendorDir . '/stecman/symfony-console-completion/src/HookFactory.php', 'Stringable' => $vendorDir . '/marc-mabe/php-enum/stubs/Stringable.php', + 'Symfony\\Component\\Clock\\Clock' => $vendorDir . '/symfony/clock/Clock.php', + 'Symfony\\Component\\Clock\\ClockAwareTrait' => $vendorDir . '/symfony/clock/ClockAwareTrait.php', + 'Symfony\\Component\\Clock\\ClockInterface' => $vendorDir . '/symfony/clock/ClockInterface.php', + 'Symfony\\Component\\Clock\\DatePoint' => $vendorDir . '/symfony/clock/DatePoint.php', + 'Symfony\\Component\\Clock\\MockClock' => $vendorDir . '/symfony/clock/MockClock.php', + 'Symfony\\Component\\Clock\\MonotonicClock' => $vendorDir . '/symfony/clock/MonotonicClock.php', + 'Symfony\\Component\\Clock\\NativeClock' => $vendorDir . '/symfony/clock/NativeClock.php', 'Symfony\\Component\\Console\\Application' => $vendorDir . '/symfony/console/Application.php', 'Symfony\\Component\\Console\\Attribute\\Argument' => $vendorDir . '/symfony/console/Attribute/Argument.php', 'Symfony\\Component\\Console\\Attribute\\AsCommand' => $vendorDir . '/symfony/console/Attribute/AsCommand.php', @@ -3462,6 +3574,51 @@ 'Symfony\\Component\\Process\\Pipes\\WindowsPipes' => $vendorDir . '/symfony/process/Pipes/WindowsPipes.php', 'Symfony\\Component\\Process\\Process' => $vendorDir . '/symfony/process/Process.php', 'Symfony\\Component\\Process\\ProcessUtils' => $vendorDir . '/symfony/process/ProcessUtils.php', + 'Symfony\\Component\\PropertyAccess\\Exception\\AccessException' => $vendorDir . '/symfony/property-access/Exception/AccessException.php', + 'Symfony\\Component\\PropertyAccess\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/property-access/Exception/ExceptionInterface.php', + 'Symfony\\Component\\PropertyAccess\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/property-access/Exception/InvalidArgumentException.php', + 'Symfony\\Component\\PropertyAccess\\Exception\\InvalidPropertyPathException' => $vendorDir . '/symfony/property-access/Exception/InvalidPropertyPathException.php', + 'Symfony\\Component\\PropertyAccess\\Exception\\InvalidTypeException' => $vendorDir . '/symfony/property-access/Exception/InvalidTypeException.php', + 'Symfony\\Component\\PropertyAccess\\Exception\\NoSuchIndexException' => $vendorDir . '/symfony/property-access/Exception/NoSuchIndexException.php', + 'Symfony\\Component\\PropertyAccess\\Exception\\NoSuchPropertyException' => $vendorDir . '/symfony/property-access/Exception/NoSuchPropertyException.php', + 'Symfony\\Component\\PropertyAccess\\Exception\\OutOfBoundsException' => $vendorDir . '/symfony/property-access/Exception/OutOfBoundsException.php', + 'Symfony\\Component\\PropertyAccess\\Exception\\RuntimeException' => $vendorDir . '/symfony/property-access/Exception/RuntimeException.php', + 'Symfony\\Component\\PropertyAccess\\Exception\\UnexpectedTypeException' => $vendorDir . '/symfony/property-access/Exception/UnexpectedTypeException.php', + 'Symfony\\Component\\PropertyAccess\\Exception\\UninitializedPropertyException' => $vendorDir . '/symfony/property-access/Exception/UninitializedPropertyException.php', + 'Symfony\\Component\\PropertyAccess\\PropertyAccess' => $vendorDir . '/symfony/property-access/PropertyAccess.php', + 'Symfony\\Component\\PropertyAccess\\PropertyAccessor' => $vendorDir . '/symfony/property-access/PropertyAccessor.php', + 'Symfony\\Component\\PropertyAccess\\PropertyAccessorBuilder' => $vendorDir . '/symfony/property-access/PropertyAccessorBuilder.php', + 'Symfony\\Component\\PropertyAccess\\PropertyAccessorInterface' => $vendorDir . '/symfony/property-access/PropertyAccessorInterface.php', + 'Symfony\\Component\\PropertyAccess\\PropertyPath' => $vendorDir . '/symfony/property-access/PropertyPath.php', + 'Symfony\\Component\\PropertyAccess\\PropertyPathBuilder' => $vendorDir . '/symfony/property-access/PropertyPathBuilder.php', + 'Symfony\\Component\\PropertyAccess\\PropertyPathInterface' => $vendorDir . '/symfony/property-access/PropertyPathInterface.php', + 'Symfony\\Component\\PropertyAccess\\PropertyPathIterator' => $vendorDir . '/symfony/property-access/PropertyPathIterator.php', + 'Symfony\\Component\\PropertyAccess\\PropertyPathIteratorInterface' => $vendorDir . '/symfony/property-access/PropertyPathIteratorInterface.php', + 'Symfony\\Component\\PropertyInfo\\DependencyInjection\\PropertyInfoConstructorPass' => $vendorDir . '/symfony/property-info/DependencyInjection/PropertyInfoConstructorPass.php', + 'Symfony\\Component\\PropertyInfo\\DependencyInjection\\PropertyInfoPass' => $vendorDir . '/symfony/property-info/DependencyInjection/PropertyInfoPass.php', + 'Symfony\\Component\\PropertyInfo\\Extractor\\ConstructorArgumentTypeExtractorInterface' => $vendorDir . '/symfony/property-info/Extractor/ConstructorArgumentTypeExtractorInterface.php', + 'Symfony\\Component\\PropertyInfo\\Extractor\\ConstructorExtractor' => $vendorDir . '/symfony/property-info/Extractor/ConstructorExtractor.php', + 'Symfony\\Component\\PropertyInfo\\Extractor\\PhpDocExtractor' => $vendorDir . '/symfony/property-info/Extractor/PhpDocExtractor.php', + 'Symfony\\Component\\PropertyInfo\\Extractor\\PhpStanExtractor' => $vendorDir . '/symfony/property-info/Extractor/PhpStanExtractor.php', + 'Symfony\\Component\\PropertyInfo\\Extractor\\ReflectionExtractor' => $vendorDir . '/symfony/property-info/Extractor/ReflectionExtractor.php', + 'Symfony\\Component\\PropertyInfo\\Extractor\\SerializerExtractor' => $vendorDir . '/symfony/property-info/Extractor/SerializerExtractor.php', + 'Symfony\\Component\\PropertyInfo\\PropertyAccessExtractorInterface' => $vendorDir . '/symfony/property-info/PropertyAccessExtractorInterface.php', + 'Symfony\\Component\\PropertyInfo\\PropertyDescriptionExtractorInterface' => $vendorDir . '/symfony/property-info/PropertyDescriptionExtractorInterface.php', + 'Symfony\\Component\\PropertyInfo\\PropertyDocBlockExtractorInterface' => $vendorDir . '/symfony/property-info/PropertyDocBlockExtractorInterface.php', + 'Symfony\\Component\\PropertyInfo\\PropertyInfoCacheExtractor' => $vendorDir . '/symfony/property-info/PropertyInfoCacheExtractor.php', + 'Symfony\\Component\\PropertyInfo\\PropertyInfoExtractor' => $vendorDir . '/symfony/property-info/PropertyInfoExtractor.php', + 'Symfony\\Component\\PropertyInfo\\PropertyInfoExtractorInterface' => $vendorDir . '/symfony/property-info/PropertyInfoExtractorInterface.php', + 'Symfony\\Component\\PropertyInfo\\PropertyInitializableExtractorInterface' => $vendorDir . '/symfony/property-info/PropertyInitializableExtractorInterface.php', + 'Symfony\\Component\\PropertyInfo\\PropertyListExtractorInterface' => $vendorDir . '/symfony/property-info/PropertyListExtractorInterface.php', + 'Symfony\\Component\\PropertyInfo\\PropertyReadInfo' => $vendorDir . '/symfony/property-info/PropertyReadInfo.php', + 'Symfony\\Component\\PropertyInfo\\PropertyReadInfoExtractorInterface' => $vendorDir . '/symfony/property-info/PropertyReadInfoExtractorInterface.php', + 'Symfony\\Component\\PropertyInfo\\PropertyTypeExtractorInterface' => $vendorDir . '/symfony/property-info/PropertyTypeExtractorInterface.php', + 'Symfony\\Component\\PropertyInfo\\PropertyWriteInfo' => $vendorDir . '/symfony/property-info/PropertyWriteInfo.php', + 'Symfony\\Component\\PropertyInfo\\PropertyWriteInfoExtractorInterface' => $vendorDir . '/symfony/property-info/PropertyWriteInfoExtractorInterface.php', + 'Symfony\\Component\\PropertyInfo\\Type' => $vendorDir . '/symfony/property-info/Type.php', + 'Symfony\\Component\\PropertyInfo\\Util\\LegacyTypeConverter' => $vendorDir . '/symfony/property-info/Util/LegacyTypeConverter.php', + 'Symfony\\Component\\PropertyInfo\\Util\\PhpDocTypeHelper' => $vendorDir . '/symfony/property-info/Util/PhpDocTypeHelper.php', + 'Symfony\\Component\\PropertyInfo\\Util\\PhpStanTypeHelper' => $vendorDir . '/symfony/property-info/Util/PhpStanTypeHelper.php', 'Symfony\\Component\\Routing\\Alias' => $vendorDir . '/symfony/routing/Alias.php', 'Symfony\\Component\\Routing\\Annotation\\Route' => $vendorDir . '/symfony/routing/Annotation/Route.php', 'Symfony\\Component\\Routing\\Attribute\\Route' => $vendorDir . '/symfony/routing/Attribute/Route.php', @@ -3533,6 +3690,140 @@ 'Symfony\\Component\\Routing\\RouteCompilerInterface' => $vendorDir . '/symfony/routing/RouteCompilerInterface.php', 'Symfony\\Component\\Routing\\Router' => $vendorDir . '/symfony/routing/Router.php', 'Symfony\\Component\\Routing\\RouterInterface' => $vendorDir . '/symfony/routing/RouterInterface.php', + 'Symfony\\Component\\Serializer\\Annotation\\Context' => $vendorDir . '/symfony/serializer/Annotation/Context.php', + 'Symfony\\Component\\Serializer\\Annotation\\DiscriminatorMap' => $vendorDir . '/symfony/serializer/Annotation/DiscriminatorMap.php', + 'Symfony\\Component\\Serializer\\Annotation\\Groups' => $vendorDir . '/symfony/serializer/Annotation/Groups.php', + 'Symfony\\Component\\Serializer\\Annotation\\Ignore' => $vendorDir . '/symfony/serializer/Annotation/Ignore.php', + 'Symfony\\Component\\Serializer\\Annotation\\MaxDepth' => $vendorDir . '/symfony/serializer/Annotation/MaxDepth.php', + 'Symfony\\Component\\Serializer\\Annotation\\SerializedName' => $vendorDir . '/symfony/serializer/Annotation/SerializedName.php', + 'Symfony\\Component\\Serializer\\Annotation\\SerializedPath' => $vendorDir . '/symfony/serializer/Annotation/SerializedPath.php', + 'Symfony\\Component\\Serializer\\Attribute\\Context' => $vendorDir . '/symfony/serializer/Attribute/Context.php', + 'Symfony\\Component\\Serializer\\Attribute\\DiscriminatorMap' => $vendorDir . '/symfony/serializer/Attribute/DiscriminatorMap.php', + 'Symfony\\Component\\Serializer\\Attribute\\ExtendsSerializationFor' => $vendorDir . '/symfony/serializer/Attribute/ExtendsSerializationFor.php', + 'Symfony\\Component\\Serializer\\Attribute\\Groups' => $vendorDir . '/symfony/serializer/Attribute/Groups.php', + 'Symfony\\Component\\Serializer\\Attribute\\Ignore' => $vendorDir . '/symfony/serializer/Attribute/Ignore.php', + 'Symfony\\Component\\Serializer\\Attribute\\MaxDepth' => $vendorDir . '/symfony/serializer/Attribute/MaxDepth.php', + 'Symfony\\Component\\Serializer\\Attribute\\SerializedName' => $vendorDir . '/symfony/serializer/Attribute/SerializedName.php', + 'Symfony\\Component\\Serializer\\Attribute\\SerializedPath' => $vendorDir . '/symfony/serializer/Attribute/SerializedPath.php', + 'Symfony\\Component\\Serializer\\CacheWarmer\\CompiledClassMetadataCacheWarmer' => $vendorDir . '/symfony/serializer/CacheWarmer/CompiledClassMetadataCacheWarmer.php', + 'Symfony\\Component\\Serializer\\Command\\DebugCommand' => $vendorDir . '/symfony/serializer/Command/DebugCommand.php', + 'Symfony\\Component\\Serializer\\Context\\ContextBuilderInterface' => $vendorDir . '/symfony/serializer/Context/ContextBuilderInterface.php', + 'Symfony\\Component\\Serializer\\Context\\ContextBuilderTrait' => $vendorDir . '/symfony/serializer/Context/ContextBuilderTrait.php', + 'Symfony\\Component\\Serializer\\Context\\Encoder\\CsvEncoderContextBuilder' => $vendorDir . '/symfony/serializer/Context/Encoder/CsvEncoderContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Encoder\\JsonEncoderContextBuilder' => $vendorDir . '/symfony/serializer/Context/Encoder/JsonEncoderContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Encoder\\XmlEncoderContextBuilder' => $vendorDir . '/symfony/serializer/Context/Encoder/XmlEncoderContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Encoder\\YamlEncoderContextBuilder' => $vendorDir . '/symfony/serializer/Context/Encoder/YamlEncoderContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Normalizer\\AbstractNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/AbstractNormalizerContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Normalizer\\AbstractObjectNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/AbstractObjectNormalizerContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Normalizer\\BackedEnumNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/BackedEnumNormalizerContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Normalizer\\ConstraintViolationListNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/ConstraintViolationListNormalizerContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Normalizer\\DateIntervalNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/DateIntervalNormalizerContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Normalizer\\DateTimeNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/DateTimeNormalizerContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Normalizer\\FormErrorNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/FormErrorNormalizerContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Normalizer\\GetSetMethodNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/GetSetMethodNormalizerContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Normalizer\\JsonSerializableNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/JsonSerializableNormalizerContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Normalizer\\ObjectNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/ObjectNormalizerContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Normalizer\\ProblemNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/ProblemNormalizerContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Normalizer\\PropertyNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/PropertyNormalizerContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Normalizer\\UidNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/UidNormalizerContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Normalizer\\UnwrappingDenormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/UnwrappingDenormalizerContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\SerializerContextBuilder' => $vendorDir . '/symfony/serializer/Context/SerializerContextBuilder.php', + 'Symfony\\Component\\Serializer\\DataCollector\\SerializerDataCollector' => $vendorDir . '/symfony/serializer/DataCollector/SerializerDataCollector.php', + 'Symfony\\Component\\Serializer\\Debug\\TraceableEncoder' => $vendorDir . '/symfony/serializer/Debug/TraceableEncoder.php', + 'Symfony\\Component\\Serializer\\Debug\\TraceableNormalizer' => $vendorDir . '/symfony/serializer/Debug/TraceableNormalizer.php', + 'Symfony\\Component\\Serializer\\Debug\\TraceableSerializer' => $vendorDir . '/symfony/serializer/Debug/TraceableSerializer.php', + 'Symfony\\Component\\Serializer\\DependencyInjection\\AttributeMetadataPass' => $vendorDir . '/symfony/serializer/DependencyInjection/AttributeMetadataPass.php', + 'Symfony\\Component\\Serializer\\DependencyInjection\\SerializerPass' => $vendorDir . '/symfony/serializer/DependencyInjection/SerializerPass.php', + 'Symfony\\Component\\Serializer\\Encoder\\ChainDecoder' => $vendorDir . '/symfony/serializer/Encoder/ChainDecoder.php', + 'Symfony\\Component\\Serializer\\Encoder\\ChainEncoder' => $vendorDir . '/symfony/serializer/Encoder/ChainEncoder.php', + 'Symfony\\Component\\Serializer\\Encoder\\ContextAwareDecoderInterface' => $vendorDir . '/symfony/serializer/Encoder/ContextAwareDecoderInterface.php', + 'Symfony\\Component\\Serializer\\Encoder\\ContextAwareEncoderInterface' => $vendorDir . '/symfony/serializer/Encoder/ContextAwareEncoderInterface.php', + 'Symfony\\Component\\Serializer\\Encoder\\CsvEncoder' => $vendorDir . '/symfony/serializer/Encoder/CsvEncoder.php', + 'Symfony\\Component\\Serializer\\Encoder\\DecoderInterface' => $vendorDir . '/symfony/serializer/Encoder/DecoderInterface.php', + 'Symfony\\Component\\Serializer\\Encoder\\EncoderInterface' => $vendorDir . '/symfony/serializer/Encoder/EncoderInterface.php', + 'Symfony\\Component\\Serializer\\Encoder\\JsonDecode' => $vendorDir . '/symfony/serializer/Encoder/JsonDecode.php', + 'Symfony\\Component\\Serializer\\Encoder\\JsonEncode' => $vendorDir . '/symfony/serializer/Encoder/JsonEncode.php', + 'Symfony\\Component\\Serializer\\Encoder\\JsonEncoder' => $vendorDir . '/symfony/serializer/Encoder/JsonEncoder.php', + 'Symfony\\Component\\Serializer\\Encoder\\NormalizationAwareInterface' => $vendorDir . '/symfony/serializer/Encoder/NormalizationAwareInterface.php', + 'Symfony\\Component\\Serializer\\Encoder\\XmlEncoder' => $vendorDir . '/symfony/serializer/Encoder/XmlEncoder.php', + 'Symfony\\Component\\Serializer\\Encoder\\YamlEncoder' => $vendorDir . '/symfony/serializer/Encoder/YamlEncoder.php', + 'Symfony\\Component\\Serializer\\Exception\\BadMethodCallException' => $vendorDir . '/symfony/serializer/Exception/BadMethodCallException.php', + 'Symfony\\Component\\Serializer\\Exception\\CircularReferenceException' => $vendorDir . '/symfony/serializer/Exception/CircularReferenceException.php', + 'Symfony\\Component\\Serializer\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/serializer/Exception/ExceptionInterface.php', + 'Symfony\\Component\\Serializer\\Exception\\ExtraAttributesException' => $vendorDir . '/symfony/serializer/Exception/ExtraAttributesException.php', + 'Symfony\\Component\\Serializer\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/serializer/Exception/InvalidArgumentException.php', + 'Symfony\\Component\\Serializer\\Exception\\LogicException' => $vendorDir . '/symfony/serializer/Exception/LogicException.php', + 'Symfony\\Component\\Serializer\\Exception\\MappingException' => $vendorDir . '/symfony/serializer/Exception/MappingException.php', + 'Symfony\\Component\\Serializer\\Exception\\MissingConstructorArgumentsException' => $vendorDir . '/symfony/serializer/Exception/MissingConstructorArgumentsException.php', + 'Symfony\\Component\\Serializer\\Exception\\NotEncodableValueException' => $vendorDir . '/symfony/serializer/Exception/NotEncodableValueException.php', + 'Symfony\\Component\\Serializer\\Exception\\NotNormalizableValueException' => $vendorDir . '/symfony/serializer/Exception/NotNormalizableValueException.php', + 'Symfony\\Component\\Serializer\\Exception\\PartialDenormalizationException' => $vendorDir . '/symfony/serializer/Exception/PartialDenormalizationException.php', + 'Symfony\\Component\\Serializer\\Exception\\RuntimeException' => $vendorDir . '/symfony/serializer/Exception/RuntimeException.php', + 'Symfony\\Component\\Serializer\\Exception\\UnexpectedPropertyException' => $vendorDir . '/symfony/serializer/Exception/UnexpectedPropertyException.php', + 'Symfony\\Component\\Serializer\\Exception\\UnexpectedValueException' => $vendorDir . '/symfony/serializer/Exception/UnexpectedValueException.php', + 'Symfony\\Component\\Serializer\\Exception\\UnsupportedException' => $vendorDir . '/symfony/serializer/Exception/UnsupportedException.php', + 'Symfony\\Component\\Serializer\\Exception\\UnsupportedFormatException' => $vendorDir . '/symfony/serializer/Exception/UnsupportedFormatException.php', + 'Symfony\\Component\\Serializer\\Extractor\\ObjectPropertyListExtractor' => $vendorDir . '/symfony/serializer/Extractor/ObjectPropertyListExtractor.php', + 'Symfony\\Component\\Serializer\\Extractor\\ObjectPropertyListExtractorInterface' => $vendorDir . '/symfony/serializer/Extractor/ObjectPropertyListExtractorInterface.php', + 'Symfony\\Component\\Serializer\\Mapping\\AttributeMetadata' => $vendorDir . '/symfony/serializer/Mapping/AttributeMetadata.php', + 'Symfony\\Component\\Serializer\\Mapping\\AttributeMetadataInterface' => $vendorDir . '/symfony/serializer/Mapping/AttributeMetadataInterface.php', + 'Symfony\\Component\\Serializer\\Mapping\\ClassDiscriminatorFromClassMetadata' => $vendorDir . '/symfony/serializer/Mapping/ClassDiscriminatorFromClassMetadata.php', + 'Symfony\\Component\\Serializer\\Mapping\\ClassDiscriminatorMapping' => $vendorDir . '/symfony/serializer/Mapping/ClassDiscriminatorMapping.php', + 'Symfony\\Component\\Serializer\\Mapping\\ClassDiscriminatorResolverInterface' => $vendorDir . '/symfony/serializer/Mapping/ClassDiscriminatorResolverInterface.php', + 'Symfony\\Component\\Serializer\\Mapping\\ClassMetadata' => $vendorDir . '/symfony/serializer/Mapping/ClassMetadata.php', + 'Symfony\\Component\\Serializer\\Mapping\\ClassMetadataInterface' => $vendorDir . '/symfony/serializer/Mapping/ClassMetadataInterface.php', + 'Symfony\\Component\\Serializer\\Mapping\\Factory\\CacheClassMetadataFactory' => $vendorDir . '/symfony/serializer/Mapping/Factory/CacheClassMetadataFactory.php', + 'Symfony\\Component\\Serializer\\Mapping\\Factory\\ClassMetadataFactory' => $vendorDir . '/symfony/serializer/Mapping/Factory/ClassMetadataFactory.php', + 'Symfony\\Component\\Serializer\\Mapping\\Factory\\ClassMetadataFactoryCompiler' => $vendorDir . '/symfony/serializer/Mapping/Factory/ClassMetadataFactoryCompiler.php', + 'Symfony\\Component\\Serializer\\Mapping\\Factory\\ClassMetadataFactoryInterface' => $vendorDir . '/symfony/serializer/Mapping/Factory/ClassMetadataFactoryInterface.php', + 'Symfony\\Component\\Serializer\\Mapping\\Factory\\ClassResolverTrait' => $vendorDir . '/symfony/serializer/Mapping/Factory/ClassResolverTrait.php', + 'Symfony\\Component\\Serializer\\Mapping\\Factory\\CompiledClassMetadataFactory' => $vendorDir . '/symfony/serializer/Mapping/Factory/CompiledClassMetadataFactory.php', + 'Symfony\\Component\\Serializer\\Mapping\\Loader\\AccessorCollisionResolverTrait' => $vendorDir . '/symfony/serializer/Mapping/Loader/AccessorCollisionResolverTrait.php', + 'Symfony\\Component\\Serializer\\Mapping\\Loader\\AttributeLoader' => $vendorDir . '/symfony/serializer/Mapping/Loader/AttributeLoader.php', + 'Symfony\\Component\\Serializer\\Mapping\\Loader\\FileLoader' => $vendorDir . '/symfony/serializer/Mapping/Loader/FileLoader.php', + 'Symfony\\Component\\Serializer\\Mapping\\Loader\\LoaderChain' => $vendorDir . '/symfony/serializer/Mapping/Loader/LoaderChain.php', + 'Symfony\\Component\\Serializer\\Mapping\\Loader\\LoaderInterface' => $vendorDir . '/symfony/serializer/Mapping/Loader/LoaderInterface.php', + 'Symfony\\Component\\Serializer\\Mapping\\Loader\\XmlFileLoader' => $vendorDir . '/symfony/serializer/Mapping/Loader/XmlFileLoader.php', + 'Symfony\\Component\\Serializer\\Mapping\\Loader\\YamlFileLoader' => $vendorDir . '/symfony/serializer/Mapping/Loader/YamlFileLoader.php', + 'Symfony\\Component\\Serializer\\NameConverter\\AdvancedNameConverterInterface' => $vendorDir . '/symfony/serializer/NameConverter/AdvancedNameConverterInterface.php', + 'Symfony\\Component\\Serializer\\NameConverter\\CamelCaseToSnakeCaseNameConverter' => $vendorDir . '/symfony/serializer/NameConverter/CamelCaseToSnakeCaseNameConverter.php', + 'Symfony\\Component\\Serializer\\NameConverter\\MetadataAwareNameConverter' => $vendorDir . '/symfony/serializer/NameConverter/MetadataAwareNameConverter.php', + 'Symfony\\Component\\Serializer\\NameConverter\\NameConverterInterface' => $vendorDir . '/symfony/serializer/NameConverter/NameConverterInterface.php', + 'Symfony\\Component\\Serializer\\NameConverter\\SnakeCaseToCamelCaseNameConverter' => $vendorDir . '/symfony/serializer/NameConverter/SnakeCaseToCamelCaseNameConverter.php', + 'Symfony\\Component\\Serializer\\Normalizer\\AbstractNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/AbstractNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\AbstractObjectNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/AbstractObjectNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\ArrayDenormalizer' => $vendorDir . '/symfony/serializer/Normalizer/ArrayDenormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\BackedEnumNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/BackedEnumNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\ConstraintViolationListNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/ConstraintViolationListNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\CustomNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/CustomNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\DataUriNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/DataUriNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\DateIntervalNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/DateIntervalNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\DateTimeNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/DateTimeNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\DateTimeZoneNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/DateTimeZoneNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\DenormalizableInterface' => $vendorDir . '/symfony/serializer/Normalizer/DenormalizableInterface.php', + 'Symfony\\Component\\Serializer\\Normalizer\\DenormalizerAwareInterface' => $vendorDir . '/symfony/serializer/Normalizer/DenormalizerAwareInterface.php', + 'Symfony\\Component\\Serializer\\Normalizer\\DenormalizerAwareTrait' => $vendorDir . '/symfony/serializer/Normalizer/DenormalizerAwareTrait.php', + 'Symfony\\Component\\Serializer\\Normalizer\\DenormalizerInterface' => $vendorDir . '/symfony/serializer/Normalizer/DenormalizerInterface.php', + 'Symfony\\Component\\Serializer\\Normalizer\\FormErrorNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/FormErrorNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\GetSetMethodNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/GetSetMethodNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\JsonSerializableNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/JsonSerializableNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\MimeMessageNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/MimeMessageNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\NormalizableInterface' => $vendorDir . '/symfony/serializer/Normalizer/NormalizableInterface.php', + 'Symfony\\Component\\Serializer\\Normalizer\\NormalizerAwareInterface' => $vendorDir . '/symfony/serializer/Normalizer/NormalizerAwareInterface.php', + 'Symfony\\Component\\Serializer\\Normalizer\\NormalizerAwareTrait' => $vendorDir . '/symfony/serializer/Normalizer/NormalizerAwareTrait.php', + 'Symfony\\Component\\Serializer\\Normalizer\\NormalizerInterface' => $vendorDir . '/symfony/serializer/Normalizer/NormalizerInterface.php', + 'Symfony\\Component\\Serializer\\Normalizer\\NumberNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/NumberNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\ObjectNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/ObjectNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\ObjectToPopulateTrait' => $vendorDir . '/symfony/serializer/Normalizer/ObjectToPopulateTrait.php', + 'Symfony\\Component\\Serializer\\Normalizer\\ProblemNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/ProblemNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\PropertyNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/PropertyNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\TranslatableNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/TranslatableNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\UidNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/UidNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\UnwrappingDenormalizer' => $vendorDir . '/symfony/serializer/Normalizer/UnwrappingDenormalizer.php', + 'Symfony\\Component\\Serializer\\Serializer' => $vendorDir . '/symfony/serializer/Serializer.php', + 'Symfony\\Component\\Serializer\\SerializerAwareInterface' => $vendorDir . '/symfony/serializer/SerializerAwareInterface.php', + 'Symfony\\Component\\Serializer\\SerializerAwareTrait' => $vendorDir . '/symfony/serializer/SerializerAwareTrait.php', + 'Symfony\\Component\\Serializer\\SerializerInterface' => $vendorDir . '/symfony/serializer/SerializerInterface.php', 'Symfony\\Component\\String\\AbstractString' => $vendorDir . '/symfony/string/AbstractString.php', 'Symfony\\Component\\String\\AbstractUnicodeString' => $vendorDir . '/symfony/string/AbstractUnicodeString.php', 'Symfony\\Component\\String\\ByteString' => $vendorDir . '/symfony/string/ByteString.php', @@ -3643,17 +3934,52 @@ 'Symfony\\Component\\Translation\\Util\\XliffUtils' => $vendorDir . '/symfony/translation/Util/XliffUtils.php', 'Symfony\\Component\\Translation\\Writer\\TranslationWriter' => $vendorDir . '/symfony/translation/Writer/TranslationWriter.php', 'Symfony\\Component\\Translation\\Writer\\TranslationWriterInterface' => $vendorDir . '/symfony/translation/Writer/TranslationWriterInterface.php', + 'Symfony\\Component\\TypeInfo\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/type-info/Exception/ExceptionInterface.php', + 'Symfony\\Component\\TypeInfo\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/type-info/Exception/InvalidArgumentException.php', + 'Symfony\\Component\\TypeInfo\\Exception\\LogicException' => $vendorDir . '/symfony/type-info/Exception/LogicException.php', + 'Symfony\\Component\\TypeInfo\\Exception\\RuntimeException' => $vendorDir . '/symfony/type-info/Exception/RuntimeException.php', + 'Symfony\\Component\\TypeInfo\\Exception\\UnsupportedException' => $vendorDir . '/symfony/type-info/Exception/UnsupportedException.php', + 'Symfony\\Component\\TypeInfo\\Type' => $vendorDir . '/symfony/type-info/Type.php', + 'Symfony\\Component\\TypeInfo\\TypeContext\\TypeContext' => $vendorDir . '/symfony/type-info/TypeContext/TypeContext.php', + 'Symfony\\Component\\TypeInfo\\TypeContext\\TypeContextFactory' => $vendorDir . '/symfony/type-info/TypeContext/TypeContextFactory.php', + 'Symfony\\Component\\TypeInfo\\TypeFactoryTrait' => $vendorDir . '/symfony/type-info/TypeFactoryTrait.php', + 'Symfony\\Component\\TypeInfo\\TypeIdentifier' => $vendorDir . '/symfony/type-info/TypeIdentifier.php', + 'Symfony\\Component\\TypeInfo\\TypeResolver\\PhpDocAwareReflectionTypeResolver' => $vendorDir . '/symfony/type-info/TypeResolver/PhpDocAwareReflectionTypeResolver.php', + 'Symfony\\Component\\TypeInfo\\TypeResolver\\ReflectionParameterTypeResolver' => $vendorDir . '/symfony/type-info/TypeResolver/ReflectionParameterTypeResolver.php', + 'Symfony\\Component\\TypeInfo\\TypeResolver\\ReflectionPropertyTypeResolver' => $vendorDir . '/symfony/type-info/TypeResolver/ReflectionPropertyTypeResolver.php', + 'Symfony\\Component\\TypeInfo\\TypeResolver\\ReflectionReturnTypeResolver' => $vendorDir . '/symfony/type-info/TypeResolver/ReflectionReturnTypeResolver.php', + 'Symfony\\Component\\TypeInfo\\TypeResolver\\ReflectionTypeResolver' => $vendorDir . '/symfony/type-info/TypeResolver/ReflectionTypeResolver.php', + 'Symfony\\Component\\TypeInfo\\TypeResolver\\StringTypeResolver' => $vendorDir . '/symfony/type-info/TypeResolver/StringTypeResolver.php', + 'Symfony\\Component\\TypeInfo\\TypeResolver\\TypeResolver' => $vendorDir . '/symfony/type-info/TypeResolver/TypeResolver.php', + 'Symfony\\Component\\TypeInfo\\TypeResolver\\TypeResolverInterface' => $vendorDir . '/symfony/type-info/TypeResolver/TypeResolverInterface.php', + 'Symfony\\Component\\TypeInfo\\Type\\ArrayShapeType' => $vendorDir . '/symfony/type-info/Type/ArrayShapeType.php', + 'Symfony\\Component\\TypeInfo\\Type\\BackedEnumType' => $vendorDir . '/symfony/type-info/Type/BackedEnumType.php', + 'Symfony\\Component\\TypeInfo\\Type\\BuiltinType' => $vendorDir . '/symfony/type-info/Type/BuiltinType.php', + 'Symfony\\Component\\TypeInfo\\Type\\CollectionType' => $vendorDir . '/symfony/type-info/Type/CollectionType.php', + 'Symfony\\Component\\TypeInfo\\Type\\CompositeTypeInterface' => $vendorDir . '/symfony/type-info/Type/CompositeTypeInterface.php', + 'Symfony\\Component\\TypeInfo\\Type\\EnumType' => $vendorDir . '/symfony/type-info/Type/EnumType.php', + 'Symfony\\Component\\TypeInfo\\Type\\GenericType' => $vendorDir . '/symfony/type-info/Type/GenericType.php', + 'Symfony\\Component\\TypeInfo\\Type\\IntersectionType' => $vendorDir . '/symfony/type-info/Type/IntersectionType.php', + 'Symfony\\Component\\TypeInfo\\Type\\NullableType' => $vendorDir . '/symfony/type-info/Type/NullableType.php', + 'Symfony\\Component\\TypeInfo\\Type\\ObjectType' => $vendorDir . '/symfony/type-info/Type/ObjectType.php', + 'Symfony\\Component\\TypeInfo\\Type\\TemplateType' => $vendorDir . '/symfony/type-info/Type/TemplateType.php', + 'Symfony\\Component\\TypeInfo\\Type\\UnionType' => $vendorDir . '/symfony/type-info/Type/UnionType.php', + 'Symfony\\Component\\TypeInfo\\Type\\WrappingTypeInterface' => $vendorDir . '/symfony/type-info/Type/WrappingTypeInterface.php', 'Symfony\\Component\\Uid\\AbstractUid' => $vendorDir . '/symfony/uid/AbstractUid.php', 'Symfony\\Component\\Uid\\BinaryUtil' => $vendorDir . '/symfony/uid/BinaryUtil.php', 'Symfony\\Component\\Uid\\Command\\GenerateUlidCommand' => $vendorDir . '/symfony/uid/Command/GenerateUlidCommand.php', 'Symfony\\Component\\Uid\\Command\\GenerateUuidCommand' => $vendorDir . '/symfony/uid/Command/GenerateUuidCommand.php', 'Symfony\\Component\\Uid\\Command\\InspectUlidCommand' => $vendorDir . '/symfony/uid/Command/InspectUlidCommand.php', 'Symfony\\Component\\Uid\\Command\\InspectUuidCommand' => $vendorDir . '/symfony/uid/Command/InspectUuidCommand.php', + 'Symfony\\Component\\Uid\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/uid/Exception/InvalidArgumentException.php', + 'Symfony\\Component\\Uid\\Exception\\LogicException' => $vendorDir . '/symfony/uid/Exception/LogicException.php', + 'Symfony\\Component\\Uid\\Factory\\MockUuidFactory' => $vendorDir . '/symfony/uid/Factory/MockUuidFactory.php', 'Symfony\\Component\\Uid\\Factory\\NameBasedUuidFactory' => $vendorDir . '/symfony/uid/Factory/NameBasedUuidFactory.php', 'Symfony\\Component\\Uid\\Factory\\RandomBasedUuidFactory' => $vendorDir . '/symfony/uid/Factory/RandomBasedUuidFactory.php', 'Symfony\\Component\\Uid\\Factory\\TimeBasedUuidFactory' => $vendorDir . '/symfony/uid/Factory/TimeBasedUuidFactory.php', 'Symfony\\Component\\Uid\\Factory\\UlidFactory' => $vendorDir . '/symfony/uid/Factory/UlidFactory.php', 'Symfony\\Component\\Uid\\Factory\\UuidFactory' => $vendorDir . '/symfony/uid/Factory/UuidFactory.php', + 'Symfony\\Component\\Uid\\HashableInterface' => $vendorDir . '/symfony/uid/HashableInterface.php', 'Symfony\\Component\\Uid\\MaxUlid' => $vendorDir . '/symfony/uid/MaxUlid.php', 'Symfony\\Component\\Uid\\MaxUuid' => $vendorDir . '/symfony/uid/MaxUuid.php', 'Symfony\\Component\\Uid\\NilUlid' => $vendorDir . '/symfony/uid/NilUlid.php', @@ -3696,26 +4022,33 @@ 'Symfony\\Polyfill\\Uuid\\Uuid' => $vendorDir . '/symfony/polyfill-uuid/Uuid.php', 'System' => $vendorDir . '/pear/pear-core-minimal/src/System.php', 'Webauthn\\AttestationStatement\\AndroidKeyAttestationStatementSupport' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AndroidKeyAttestationStatementSupport.php', - 'Webauthn\\AttestationStatement\\AndroidSafetyNetAttestationStatementSupport' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AndroidSafetyNetAttestationStatementSupport.php', 'Webauthn\\AttestationStatement\\AppleAttestationStatementSupport' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AppleAttestationStatementSupport.php', 'Webauthn\\AttestationStatement\\AttestationObject' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationObject.php', 'Webauthn\\AttestationStatement\\AttestationObjectLoader' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationObjectLoader.php', 'Webauthn\\AttestationStatement\\AttestationStatement' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatement.php', 'Webauthn\\AttestationStatement\\AttestationStatementSupport' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatementSupport.php', 'Webauthn\\AttestationStatement\\AttestationStatementSupportManager' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatementSupportManager.php', + 'Webauthn\\AttestationStatement\\AttestationStatementSupportManagerAwareInterface' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatementSupportManagerAwareInterface.php', + 'Webauthn\\AttestationStatement\\AttestationStatementSupportManagerAwareTrait' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatementSupportManagerAwareTrait.php', + 'Webauthn\\AttestationStatement\\CompoundAttestationStatementSupport' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/CompoundAttestationStatementSupport.php', 'Webauthn\\AttestationStatement\\FidoU2FAttestationStatementSupport' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/FidoU2FAttestationStatementSupport.php', 'Webauthn\\AttestationStatement\\NoneAttestationStatementSupport' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/NoneAttestationStatementSupport.php', 'Webauthn\\AttestationStatement\\PackedAttestationStatementSupport' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/PackedAttestationStatementSupport.php', 'Webauthn\\AttestationStatement\\TPMAttestationStatementSupport' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/TPMAttestationStatementSupport.php', 'Webauthn\\AttestedCredentialData' => $vendorDir . '/web-auth/webauthn-lib/src/AttestedCredentialData.php', + 'Webauthn\\AuthenticationExtensions\\AppIdExcludeInputExtension' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AppIdExcludeInputExtension.php', + 'Webauthn\\AuthenticationExtensions\\AppIdInputExtension' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AppIdInputExtension.php', 'Webauthn\\AuthenticationExtensions\\AuthenticationExtension' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtension.php', + 'Webauthn\\AuthenticationExtensions\\AuthenticationExtensionLoader' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionLoader.php', 'Webauthn\\AuthenticationExtensions\\AuthenticationExtensions' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensions.php', - 'Webauthn\\AuthenticationExtensions\\AuthenticationExtensionsClientInputs' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientInputs.php', - 'Webauthn\\AuthenticationExtensions\\AuthenticationExtensionsClientOutputs' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientOutputs.php', - 'Webauthn\\AuthenticationExtensions\\AuthenticationExtensionsClientOutputsLoader' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientOutputsLoader.php', + 'Webauthn\\AuthenticationExtensions\\CredentialPropertiesInputExtension' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/CredentialPropertiesInputExtension.php', 'Webauthn\\AuthenticationExtensions\\ExtensionOutputChecker' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputChecker.php', 'Webauthn\\AuthenticationExtensions\\ExtensionOutputCheckerHandler' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputCheckerHandler.php', 'Webauthn\\AuthenticationExtensions\\ExtensionOutputError' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputError.php', + 'Webauthn\\AuthenticationExtensions\\LargeBlobInputExtension' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/LargeBlobInputExtension.php', + 'Webauthn\\AuthenticationExtensions\\PseudoRandomFunctionInputExtension' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/PseudoRandomFunctionInputExtension.php', + 'Webauthn\\AuthenticationExtensions\\PseudoRandomFunctionInputExtensionBuilder' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/PseudoRandomFunctionInputExtensionBuilder.php', + 'Webauthn\\AuthenticationExtensions\\UvmInputExtension' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/UvmInputExtension.php', 'Webauthn\\AuthenticatorAssertionResponse' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticatorAssertionResponse.php', 'Webauthn\\AuthenticatorAssertionResponseValidator' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticatorAssertionResponseValidator.php', 'Webauthn\\AuthenticatorAttestationResponse' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticatorAttestationResponse.php', @@ -3729,6 +4062,7 @@ 'Webauthn\\CeremonyStep\\CeremonyStepManagerFactory' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CeremonyStepManagerFactory.php', 'Webauthn\\CeremonyStep\\CheckAlgorithm' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckAlgorithm.php', 'Webauthn\\CeremonyStep\\CheckAllowedCredentialList' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckAllowedCredentialList.php', + 'Webauthn\\CeremonyStep\\CheckAllowedOrigins' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckAllowedOrigins.php', 'Webauthn\\CeremonyStep\\CheckAttestationFormatIsKnownAndValid' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckAttestationFormatIsKnownAndValid.php', 'Webauthn\\CeremonyStep\\CheckBackupBitsAreConsistent' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckBackupBitsAreConsistent.php', 'Webauthn\\CeremonyStep\\CheckChallenge' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckChallenge.php', @@ -3747,9 +4081,6 @@ 'Webauthn\\CeremonyStep\\CheckUserWasPresent' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckUserWasPresent.php', 'Webauthn\\CeremonyStep\\HostTopOriginValidator' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/HostTopOriginValidator.php', 'Webauthn\\CeremonyStep\\TopOriginValidator' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/TopOriginValidator.php', - 'Webauthn\\CertificateChainChecker\\CertificateChainChecker' => $vendorDir . '/web-auth/webauthn-lib/src/CertificateChainChecker/CertificateChainChecker.php', - 'Webauthn\\CertificateChainChecker\\PhpCertificateChainChecker' => $vendorDir . '/web-auth/webauthn-lib/src/CertificateChainChecker/PhpCertificateChainChecker.php', - 'Webauthn\\CertificateToolbox' => $vendorDir . '/web-auth/webauthn-lib/src/CertificateToolbox.php', 'Webauthn\\ClientDataCollector\\ClientDataCollector' => $vendorDir . '/web-auth/webauthn-lib/src/ClientDataCollector/ClientDataCollector.php', 'Webauthn\\ClientDataCollector\\ClientDataCollectorManager' => $vendorDir . '/web-auth/webauthn-lib/src/ClientDataCollector/ClientDataCollectorManager.php', 'Webauthn\\ClientDataCollector\\WebauthnAuthenticationCollector' => $vendorDir . '/web-auth/webauthn-lib/src/ClientDataCollector/WebauthnAuthenticationCollector.php', @@ -3757,6 +4088,7 @@ 'Webauthn\\Counter\\CounterChecker' => $vendorDir . '/web-auth/webauthn-lib/src/Counter/CounterChecker.php', 'Webauthn\\Counter\\ThrowExceptionIfInvalid' => $vendorDir . '/web-auth/webauthn-lib/src/Counter/ThrowExceptionIfInvalid.php', 'Webauthn\\Credential' => $vendorDir . '/web-auth/webauthn-lib/src/Credential.php', + 'Webauthn\\CredentialRecord' => $vendorDir . '/web-auth/webauthn-lib/src/CredentialRecord.php', 'Webauthn\\Denormalizer\\AttestationObjectDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/AttestationObjectDenormalizer.php', 'Webauthn\\Denormalizer\\AttestationStatementDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/AttestationStatementDenormalizer.php', 'Webauthn\\Denormalizer\\AttestedCredentialDataNormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/AttestedCredentialDataNormalizer.php', @@ -3767,14 +4099,20 @@ 'Webauthn\\Denormalizer\\AuthenticatorDataDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/AuthenticatorDataDenormalizer.php', 'Webauthn\\Denormalizer\\AuthenticatorResponseDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/AuthenticatorResponseDenormalizer.php', 'Webauthn\\Denormalizer\\CollectedClientDataDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/CollectedClientDataDenormalizer.php', + 'Webauthn\\Denormalizer\\CredentialRecordDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/CredentialRecordDenormalizer.php', 'Webauthn\\Denormalizer\\ExtensionDescriptorDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/ExtensionDescriptorDenormalizer.php', 'Webauthn\\Denormalizer\\PublicKeyCredentialDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialDenormalizer.php', 'Webauthn\\Denormalizer\\PublicKeyCredentialDescriptorNormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialDescriptorNormalizer.php', 'Webauthn\\Denormalizer\\PublicKeyCredentialOptionsDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialOptionsDenormalizer.php', 'Webauthn\\Denormalizer\\PublicKeyCredentialParametersDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialParametersDenormalizer.php', + 'Webauthn\\Denormalizer\\PublicKeyCredentialRpEntityDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialRpEntityDenormalizer.php', 'Webauthn\\Denormalizer\\PublicKeyCredentialSourceDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialSourceDenormalizer.php', 'Webauthn\\Denormalizer\\PublicKeyCredentialUserEntityDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialUserEntityDenormalizer.php', + 'Webauthn\\Denormalizer\\SignalAllAcceptedCredentialsDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/SignalAllAcceptedCredentialsDenormalizer.php', + 'Webauthn\\Denormalizer\\SignalCurrentUserDetailsDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/SignalCurrentUserDetailsDenormalizer.php', + 'Webauthn\\Denormalizer\\SignalUnknownCredentialDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/SignalUnknownCredentialDenormalizer.php', 'Webauthn\\Denormalizer\\TrustPathDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/TrustPathDenormalizer.php', + 'Webauthn\\Denormalizer\\UrlNormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/UrlNormalizer.php', 'Webauthn\\Denormalizer\\VerificationMethodANDCombinationsDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/VerificationMethodANDCombinationsDenormalizer.php', 'Webauthn\\Denormalizer\\WebauthnSerializerFactory' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/WebauthnSerializerFactory.php', 'Webauthn\\Event\\AttestationObjectLoaded' => $vendorDir . '/web-auth/webauthn-lib/src/Event/AttestationObjectLoaded.php', @@ -3783,6 +4121,8 @@ 'Webauthn\\Event\\AuthenticatorAssertionResponseValidationSucceededEvent' => $vendorDir . '/web-auth/webauthn-lib/src/Event/AuthenticatorAssertionResponseValidationSucceededEvent.php', 'Webauthn\\Event\\AuthenticatorAttestationResponseValidationFailedEvent' => $vendorDir . '/web-auth/webauthn-lib/src/Event/AuthenticatorAttestationResponseValidationFailedEvent.php', 'Webauthn\\Event\\AuthenticatorAttestationResponseValidationSucceededEvent' => $vendorDir . '/web-auth/webauthn-lib/src/Event/AuthenticatorAttestationResponseValidationSucceededEvent.php', + 'Webauthn\\Event\\BackupEligibilityChangedEvent' => $vendorDir . '/web-auth/webauthn-lib/src/Event/BackupEligibilityChangedEvent.php', + 'Webauthn\\Event\\BackupStatusChangedEvent' => $vendorDir . '/web-auth/webauthn-lib/src/Event/BackupStatusChangedEvent.php', 'Webauthn\\Event\\BeforeCertificateChainValidation' => $vendorDir . '/web-auth/webauthn-lib/src/Event/BeforeCertificateChainValidation.php', 'Webauthn\\Event\\CanDispatchEvents' => $vendorDir . '/web-auth/webauthn-lib/src/Event/CanDispatchEvents.php', 'Webauthn\\Event\\CertificateChainValidationFailed' => $vendorDir . '/web-auth/webauthn-lib/src/Event/CertificateChainValidationFailed.php', @@ -3817,25 +4157,6 @@ 'Webauthn\\MetadataService\\CertificateChain\\CertificateChainValidator' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/CertificateChain/CertificateChainValidator.php', 'Webauthn\\MetadataService\\CertificateChain\\CertificateToolbox' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/CertificateChain/CertificateToolbox.php', 'Webauthn\\MetadataService\\CertificateChain\\PhpCertificateChainValidator' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/CertificateChain/PhpCertificateChainValidator.php', - 'Webauthn\\MetadataService\\Denormalizer\\ExtensionDescriptorDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Denormalizer/ExtensionDescriptorDenormalizer.php', - 'Webauthn\\MetadataService\\Denormalizer\\MetadataStatementSerializerFactory' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Denormalizer/MetadataStatementSerializerFactory.php', - 'Webauthn\\MetadataService\\Event\\BeforeCertificateChainValidation' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Event/BeforeCertificateChainValidation.php', - 'Webauthn\\MetadataService\\Event\\CanDispatchEvents' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Event/CanDispatchEvents.php', - 'Webauthn\\MetadataService\\Event\\CertificateChainValidationFailed' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Event/CertificateChainValidationFailed.php', - 'Webauthn\\MetadataService\\Event\\CertificateChainValidationSucceeded' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Event/CertificateChainValidationSucceeded.php', - 'Webauthn\\MetadataService\\Event\\MetadataStatementFound' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Event/MetadataStatementFound.php', - 'Webauthn\\MetadataService\\Event\\NullEventDispatcher' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Event/NullEventDispatcher.php', - 'Webauthn\\MetadataService\\Event\\WebauthnEvent' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Event/WebauthnEvent.php', - 'Webauthn\\MetadataService\\Exception\\CertificateChainException' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Exception/CertificateChainException.php', - 'Webauthn\\MetadataService\\Exception\\CertificateException' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Exception/CertificateException.php', - 'Webauthn\\MetadataService\\Exception\\CertificateRevocationListException' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Exception/CertificateRevocationListException.php', - 'Webauthn\\MetadataService\\Exception\\ExpiredCertificateException' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Exception/ExpiredCertificateException.php', - 'Webauthn\\MetadataService\\Exception\\InvalidCertificateException' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Exception/InvalidCertificateException.php', - 'Webauthn\\MetadataService\\Exception\\MetadataServiceException' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Exception/MetadataServiceException.php', - 'Webauthn\\MetadataService\\Exception\\MetadataStatementException' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Exception/MetadataStatementException.php', - 'Webauthn\\MetadataService\\Exception\\MetadataStatementLoadingException' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Exception/MetadataStatementLoadingException.php', - 'Webauthn\\MetadataService\\Exception\\MissingMetadataStatementException' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Exception/MissingMetadataStatementException.php', - 'Webauthn\\MetadataService\\Exception\\RevokedCertificateException' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Exception/RevokedCertificateException.php', 'Webauthn\\MetadataService\\MetadataStatementRepository' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/MetadataStatementRepository.php', 'Webauthn\\MetadataService\\Psr18HttpClient' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Psr18HttpClient.php', 'Webauthn\\MetadataService\\Service\\ChainedMetadataServices' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Service/ChainedMetadataServices.php', @@ -3848,7 +4169,6 @@ 'Webauthn\\MetadataService\\Service\\MetadataBLOBPayload' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Service/MetadataBLOBPayload.php', 'Webauthn\\MetadataService\\Service\\MetadataBLOBPayloadEntry' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Service/MetadataBLOBPayloadEntry.php', 'Webauthn\\MetadataService\\Service\\MetadataService' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Service/MetadataService.php', - 'Webauthn\\MetadataService\\Service\\StringMetadataService' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Service/StringMetadataService.php', 'Webauthn\\MetadataService\\Statement\\AbstractDescriptor' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/AbstractDescriptor.php', 'Webauthn\\MetadataService\\Statement\\AlternativeDescriptions' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/AlternativeDescriptions.php', 'Webauthn\\MetadataService\\Statement\\AuthenticatorGetInfo' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/AuthenticatorGetInfo.php', @@ -3857,7 +4177,6 @@ 'Webauthn\\MetadataService\\Statement\\BiometricStatusReport' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/BiometricStatusReport.php', 'Webauthn\\MetadataService\\Statement\\CodeAccuracyDescriptor' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/CodeAccuracyDescriptor.php', 'Webauthn\\MetadataService\\Statement\\DisplayPNGCharacteristicsDescriptor' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/DisplayPNGCharacteristicsDescriptor.php', - 'Webauthn\\MetadataService\\Statement\\EcdaaTrustAnchor' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/EcdaaTrustAnchor.php', 'Webauthn\\MetadataService\\Statement\\ExtensionDescriptor' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/ExtensionDescriptor.php', 'Webauthn\\MetadataService\\Statement\\MetadataStatement' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/MetadataStatement.php', 'Webauthn\\MetadataService\\Statement\\PatternAccuracyDescriptor' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/PatternAccuracyDescriptor.php', @@ -3868,35 +4187,36 @@ 'Webauthn\\MetadataService\\Statement\\VerificationMethodDescriptor' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/VerificationMethodDescriptor.php', 'Webauthn\\MetadataService\\Statement\\Version' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/Version.php', 'Webauthn\\MetadataService\\StatusReportRepository' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/StatusReportRepository.php', - 'Webauthn\\MetadataService\\ValueFilter' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/ValueFilter.php', + 'Webauthn\\PasskeyEndpointsResponse' => $vendorDir . '/web-auth/webauthn-lib/src/PasskeyEndpointsResponse.php', 'Webauthn\\PublicKeyCredential' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredential.php', 'Webauthn\\PublicKeyCredentialCreationOptions' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialCreationOptions.php', 'Webauthn\\PublicKeyCredentialDescriptor' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialDescriptor.php', - 'Webauthn\\PublicKeyCredentialDescriptorCollection' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialDescriptorCollection.php', 'Webauthn\\PublicKeyCredentialEntity' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialEntity.php', - 'Webauthn\\PublicKeyCredentialLoader' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialLoader.php', 'Webauthn\\PublicKeyCredentialOptions' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialOptions.php', 'Webauthn\\PublicKeyCredentialParameters' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialParameters.php', 'Webauthn\\PublicKeyCredentialRequestOptions' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialRequestOptions.php', 'Webauthn\\PublicKeyCredentialRpEntity' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialRpEntity.php', 'Webauthn\\PublicKeyCredentialSource' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialSource.php', - 'Webauthn\\PublicKeyCredentialSourceRepository' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialSourceRepository.php', 'Webauthn\\PublicKeyCredentialUserEntity' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialUserEntity.php', + 'Webauthn\\Signal\\AllAcceptedCredentials' => $vendorDir . '/web-auth/webauthn-lib/src/Signal/AllAcceptedCredentials.php', + 'Webauthn\\Signal\\CurrentUserDetails' => $vendorDir . '/web-auth/webauthn-lib/src/Signal/CurrentUserDetails.php', + 'Webauthn\\Signal\\Signal' => $vendorDir . '/web-auth/webauthn-lib/src/Signal/Signal.php', + 'Webauthn\\Signal\\UnknownCredential' => $vendorDir . '/web-auth/webauthn-lib/src/Signal/UnknownCredential.php', 'Webauthn\\SimpleFakeCredentialGenerator' => $vendorDir . '/web-auth/webauthn-lib/src/SimpleFakeCredentialGenerator.php', 'Webauthn\\StringStream' => $vendorDir . '/web-auth/webauthn-lib/src/StringStream.php', - 'Webauthn\\TokenBinding\\IgnoreTokenBindingHandler' => $vendorDir . '/web-auth/webauthn-lib/src/TokenBinding/IgnoreTokenBindingHandler.php', - 'Webauthn\\TokenBinding\\SecTokenBindingHandler' => $vendorDir . '/web-auth/webauthn-lib/src/TokenBinding/SecTokenBindingHandler.php', - 'Webauthn\\TokenBinding\\TokenBinding' => $vendorDir . '/web-auth/webauthn-lib/src/TokenBinding/TokenBinding.php', - 'Webauthn\\TokenBinding\\TokenBindingHandler' => $vendorDir . '/web-auth/webauthn-lib/src/TokenBinding/TokenBindingHandler.php', - 'Webauthn\\TokenBinding\\TokenBindingNotSupportedHandler' => $vendorDir . '/web-auth/webauthn-lib/src/TokenBinding/TokenBindingNotSupportedHandler.php', 'Webauthn\\TrustPath\\CertificateTrustPath' => $vendorDir . '/web-auth/webauthn-lib/src/TrustPath/CertificateTrustPath.php', - 'Webauthn\\TrustPath\\EcdaaKeyIdTrustPath' => $vendorDir . '/web-auth/webauthn-lib/src/TrustPath/EcdaaKeyIdTrustPath.php', 'Webauthn\\TrustPath\\EmptyTrustPath' => $vendorDir . '/web-auth/webauthn-lib/src/TrustPath/EmptyTrustPath.php', 'Webauthn\\TrustPath\\TrustPath' => $vendorDir . '/web-auth/webauthn-lib/src/TrustPath/TrustPath.php', - 'Webauthn\\TrustPath\\TrustPathLoader' => $vendorDir . '/web-auth/webauthn-lib/src/TrustPath/TrustPathLoader.php', 'Webauthn\\U2FPublicKey' => $vendorDir . '/web-auth/webauthn-lib/src/U2FPublicKey.php', + 'Webauthn\\Url' => $vendorDir . '/web-auth/webauthn-lib/src/Url.php', 'Webauthn\\Util\\Base64' => $vendorDir . '/web-auth/webauthn-lib/src/Util/Base64.php', 'Webauthn\\Util\\CoseSignatureFixer' => $vendorDir . '/web-auth/webauthn-lib/src/Util/CoseSignatureFixer.php', + 'Webauthn\\Util\\CredentialRecordConverter' => $vendorDir . '/web-auth/webauthn-lib/src/Util/CredentialRecordConverter.php', + 'Webmozart\\Assert\\Assert' => $vendorDir . '/webmozart/assert/src/Assert.php', + 'Webmozart\\Assert\\HasAssert' => $vendorDir . '/webmozart/assert/src/HasAssert.php', + 'Webmozart\\Assert\\InvalidArgumentException' => $vendorDir . '/webmozart/assert/src/InvalidArgumentException.php', + 'Webmozart\\Assert\\Mixin' => $vendorDir . '/webmozart/assert/src/Mixin.php', + 'Webmozart\\Assert\\PsalmPlugin' => $vendorDir . '/webmozart/assert/src/PsalmPlugin.php', 'ZipStreamer\\COMPR' => $vendorDir . '/deepdiver/zipstreamer/src/COMPR.php', 'ZipStreamer\\Count64' => $vendorDir . '/deepdiver/zipstreamer/src/Count64.php', 'ZipStreamer\\Lib\\Count64Base' => $vendorDir . '/deepdiver/zipstreamer/src/Lib/Count64Base.php', @@ -4446,6 +4766,166 @@ 'libphonenumber\\data\\ShortNumberMetadata_ZW' => $vendorDir . '/giggsey/libphonenumber-for-php-lite/src/data/ShortNumberMetadata_ZW.php', 'ownCloud\\TarStreamer\\TarHeader' => $vendorDir . '/deepdiver1975/tarstreamer/src/TarHeader.php', 'ownCloud\\TarStreamer\\TarStreamer' => $vendorDir . '/deepdiver1975/tarstreamer/src/TarStreamer.php', + 'phpDocumentor\\Reflection\\DocBlock' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock.php', + 'phpDocumentor\\Reflection\\DocBlockFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlockFactory.php', + 'phpDocumentor\\Reflection\\DocBlockFactoryInterface' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlockFactoryInterface.php', + 'phpDocumentor\\Reflection\\DocBlock\\Description' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Description.php', + 'phpDocumentor\\Reflection\\DocBlock\\DescriptionFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/DescriptionFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\ExampleFinder' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/ExampleFinder.php', + 'phpDocumentor\\Reflection\\DocBlock\\Serializer' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Serializer.php', + 'phpDocumentor\\Reflection\\DocBlock\\StandardTagFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/StandardTagFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tag' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tag.php', + 'phpDocumentor\\Reflection\\DocBlock\\TagFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/TagFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Author' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Author.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\BaseTag' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/BaseTag.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Covers' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Covers.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Deprecated' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Deprecated.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Example' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Example.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Extends_' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Extends_.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\AbstractPHPStanFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/AbstractPHPStanFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\ExtendsFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ExtendsFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\Factory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/Factory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\ImplementsFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ImplementsFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\MethodFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/MethodFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\MethodParameterFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/MethodParameterFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\MixinFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/MixinFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\PHPStanFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PHPStanFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\ParamFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ParamFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\PropertyFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\PropertyReadFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyReadFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\PropertyWriteFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyWriteFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\ReturnFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ReturnFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\TemplateCovariantFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/TemplateCovariantFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\TemplateFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/TemplateFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\ThrowsFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ThrowsFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\VarFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/VarFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Formatter' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Formatter\\AlignFormatter' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/AlignFormatter.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Formatter\\PassthroughFormatter' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/PassthroughFormatter.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Generic' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Generic.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Implements_' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Implements_.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\InvalidTag' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/InvalidTag.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Link' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Link.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Method' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Method.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\MethodParameter' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/MethodParameter.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Mixin' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Mixin.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Param' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Param.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Property' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Property.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\PropertyRead' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyRead.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\PropertyWrite' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyWrite.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Reference\\Fqsen' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Fqsen.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Reference\\Reference' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Reference.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Reference\\Url' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Url.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Return_' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Return_.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\See' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/See.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Since' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Since.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Source' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Source.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\TagWithType' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TagWithType.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Template' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Template.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\TemplateCovariant' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateCovariant.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\TemplateExtends' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateExtends.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\TemplateImplements' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateImplements.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Throws' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Throws.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Uses' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Uses.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Var_' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Var_.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Version' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Version.php', + 'phpDocumentor\\Reflection\\Element' => $vendorDir . '/phpdocumentor/reflection-common/src/Element.php', + 'phpDocumentor\\Reflection\\Exception\\CannotCreateTag' => $vendorDir . '/phpdocumentor/reflection-docblock/src/Exception/CannotCreateTag.php', + 'phpDocumentor\\Reflection\\Exception\\ParserException' => $vendorDir . '/phpdocumentor/reflection-docblock/src/Exception/ParserException.php', + 'phpDocumentor\\Reflection\\Exception\\PcreException' => $vendorDir . '/phpdocumentor/reflection-docblock/src/Exception/PcreException.php', + 'phpDocumentor\\Reflection\\Exception\\ReflectionDocblockException' => $vendorDir . '/phpdocumentor/reflection-docblock/src/Exception/ReflectionDocblockException.php', + 'phpDocumentor\\Reflection\\File' => $vendorDir . '/phpdocumentor/reflection-common/src/File.php', + 'phpDocumentor\\Reflection\\Fqsen' => $vendorDir . '/phpdocumentor/reflection-common/src/Fqsen.php', + 'phpDocumentor\\Reflection\\FqsenResolver' => $vendorDir . '/phpdocumentor/type-resolver/src/FqsenResolver.php', + 'phpDocumentor\\Reflection\\Location' => $vendorDir . '/phpdocumentor/reflection-common/src/Location.php', + 'phpDocumentor\\Reflection\\Project' => $vendorDir . '/phpdocumentor/reflection-common/src/Project.php', + 'phpDocumentor\\Reflection\\ProjectFactory' => $vendorDir . '/phpdocumentor/reflection-common/src/ProjectFactory.php', + 'phpDocumentor\\Reflection\\PseudoType' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoType.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\ArrayKey' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/ArrayKey.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\ArrayShape' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/ArrayShape.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\ArrayShapeItem' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/ArrayShapeItem.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\CallableArray' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/CallableArray.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\CallableString' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/CallableString.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\ClassString' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/ClassString.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\ClosedResource' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/ClosedResource.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\Conditional' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/Conditional.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\ConditionalForParameter' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/ConditionalForParameter.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\ConstExpression' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/ConstExpression.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\EnumString' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/EnumString.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\False_' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/False_.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\FloatValue' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/FloatValue.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\Generic' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/Generic.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\HtmlEscapedString' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/HtmlEscapedString.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\IntMask' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/IntMask.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\IntMaskOf' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/IntMaskOf.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\IntegerRange' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/IntegerRange.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\IntegerValue' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/IntegerValue.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\InterfaceString' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/InterfaceString.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\KeyOf' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/KeyOf.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\ListShape' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/ListShape.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\ListShapeItem' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/ListShapeItem.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\List_' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/List_.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\LiteralString' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/LiteralString.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\LowercaseString' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/LowercaseString.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\NegativeInteger' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/NegativeInteger.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\NeverReturn' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/NeverReturn.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\NeverReturns' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/NeverReturns.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\NoReturn' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/NoReturn.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\NonEmptyArray' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyArray.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\NonEmptyList' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyList.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\NonEmptyLowercaseString' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyLowercaseString.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\NonEmptyString' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyString.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\NonFalsyString' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/NonFalsyString.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\NonNegativeInteger' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/NonNegativeInteger.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\NonPositiveInteger' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/NonPositiveInteger.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\NonZeroInteger' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/NonZeroInteger.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\NumericString' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/NumericString.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\Numeric_' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/Numeric_.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\ObjectShape' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/ObjectShape.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\ObjectShapeItem' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/ObjectShapeItem.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\OffsetAccess' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/OffsetAccess.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\OpenResource' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/OpenResource.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\PositiveInteger' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/PositiveInteger.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\PrivatePropertiesOf' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/PrivatePropertiesOf.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\PropertiesOf' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/PropertiesOf.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\ProtectedPropertiesOf' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/ProtectedPropertiesOf.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\PublicPropertiesOf' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/PublicPropertiesOf.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\Scalar' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/Scalar.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\ShapeItem' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/ShapeItem.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\StringValue' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/StringValue.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\TraitString' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/TraitString.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\True_' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/True_.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\TruthyString' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/TruthyString.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\ValueOf' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/ValueOf.php', + 'phpDocumentor\\Reflection\\Type' => $vendorDir . '/phpdocumentor/type-resolver/src/Type.php', + 'phpDocumentor\\Reflection\\TypeResolver' => $vendorDir . '/phpdocumentor/type-resolver/src/TypeResolver.php', + 'phpDocumentor\\Reflection\\Types\\AbstractList' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/AbstractList.php', + 'phpDocumentor\\Reflection\\Types\\AggregatedType' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/AggregatedType.php', + 'phpDocumentor\\Reflection\\Types\\Array_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Array_.php', + 'phpDocumentor\\Reflection\\Types\\Boolean' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Boolean.php', + 'phpDocumentor\\Reflection\\Types\\CallableParameter' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/CallableParameter.php', + 'phpDocumentor\\Reflection\\Types\\Callable_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Callable_.php', + 'phpDocumentor\\Reflection\\Types\\Compound' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Compound.php', + 'phpDocumentor\\Reflection\\Types\\Context' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Context.php', + 'phpDocumentor\\Reflection\\Types\\ContextFactory' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/ContextFactory.php', + 'phpDocumentor\\Reflection\\Types\\Expression' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Expression.php', + 'phpDocumentor\\Reflection\\Types\\Float_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Float_.php', + 'phpDocumentor\\Reflection\\Types\\Integer' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Integer.php', + 'phpDocumentor\\Reflection\\Types\\Intersection' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Intersection.php', + 'phpDocumentor\\Reflection\\Types\\Iterable_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Iterable_.php', + 'phpDocumentor\\Reflection\\Types\\Mixed_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Mixed_.php', + 'phpDocumentor\\Reflection\\Types\\Never_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Never_.php', + 'phpDocumentor\\Reflection\\Types\\Null_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Null_.php', + 'phpDocumentor\\Reflection\\Types\\Nullable' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Nullable.php', + 'phpDocumentor\\Reflection\\Types\\Object_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Object_.php', + 'phpDocumentor\\Reflection\\Types\\Parent_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Parent_.php', + 'phpDocumentor\\Reflection\\Types\\Resource_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Resource_.php', + 'phpDocumentor\\Reflection\\Types\\Self_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Self_.php', + 'phpDocumentor\\Reflection\\Types\\Static_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Static_.php', + 'phpDocumentor\\Reflection\\Types\\String_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/String_.php', + 'phpDocumentor\\Reflection\\Types\\This' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/This.php', + 'phpDocumentor\\Reflection\\Types\\Void_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Void_.php', + 'phpDocumentor\\Reflection\\Utils' => $vendorDir . '/phpdocumentor/reflection-docblock/src/Utils.php', 'phpseclib3\\Common\\Functions\\Strings' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Common/Functions/Strings.php', 'phpseclib3\\Crypt\\AES' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/AES.php', 'phpseclib3\\Crypt\\Blowfish' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/Blowfish.php', diff --git a/composer/autoload_files.php b/composer/autoload_files.php index ecb7ddd8e..06c187571 100644 --- a/composer/autoload_files.php +++ b/composer/autoload_files.php @@ -7,9 +7,11 @@ return array( '6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php', + 'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php', '383eaff206634a77a1be54e64e6459c7' => $vendorDir . '/sabre/uri/lib/functions.php', '7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php', - 'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php', + '8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php', + 'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php', '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php', '2b9d0f43f9552984cfa82fee95491826' => $vendorDir . '/sabre/event/lib/coroutine.php', 'd81bab31d3feb45bfe2f283ea3c8fdf7' => $vendorDir . '/sabre/event/lib/Loop/functions.php', @@ -17,14 +19,13 @@ '3569eecfeed3bcf0bad3c998a494ecb8' => $vendorDir . '/sabre/xml/lib/Deserializer/functions.php', '93aa591bc4ca510c520999e34229ee79' => $vendorDir . '/sabre/xml/lib/Serializer/functions.php', 'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php', - '8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php', 'ebdb698ed4152ae445614b69b5e4bb6a' => $vendorDir . '/sabre/http/lib/functions.php', + '9d2b9fc6db0f153a0a149fefb182415e' => $vendorDir . '/symfony/polyfill-php84/bootstrap.php', '09f6b20656683369174dd6fa83b7e5fb' => $vendorDir . '/symfony/polyfill-uuid/bootstrap.php', - 'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php', 'b067bc7112e384b61c701452d53a14a8' => $vendorDir . '/mtdowling/jmespath.php/src/JmesPath.php', + '2203a247e6fda86070a5e4e07aed533a' => $vendorDir . '/symfony/clock/Resources/now.php', '8a9dc1de0ca7e01f3e08231539562f61' => $vendorDir . '/aws/aws-sdk-php/src/functions.php', 'decc78cc4436b1292c6c0d151b19445c' => $vendorDir . '/phpseclib/phpseclib/phpseclib/bootstrap.php', - '9d2b9fc6db0f153a0a149fefb182415e' => $vendorDir . '/symfony/polyfill-php84/bootstrap.php', '606a39d89246991a373564698c2d8383' => $vendorDir . '/symfony/polyfill-php85/bootstrap.php', '2c2415ec15363ede1bff13a287462ba1' => $vendorDir . '/symfony/polyfill-php86/bootstrap.php', 'a1105708a18b76903365ca1c4aa61b02' => $vendorDir . '/symfony/translation/Resources/functions.php', diff --git a/composer/autoload_psr4.php b/composer/autoload_psr4.php index fea701de0..8d097bbc8 100644 --- a/composer/autoload_psr4.php +++ b/composer/autoload_psr4.php @@ -8,6 +8,7 @@ return array( 'wapmorgan\\Mp3Info\\' => array($vendorDir . '/wapmorgan/mp3info/src'), 'phpseclib3\\' => array($vendorDir . '/phpseclib/phpseclib/phpseclib'), + 'phpDocumentor\\Reflection\\' => array($vendorDir . '/phpdocumentor/reflection-docblock/src', $vendorDir . '/phpdocumentor/type-resolver/src', $vendorDir . '/phpdocumentor/reflection-common/src'), 'ownCloud\\TarStreamer\\' => array($vendorDir . '/deepdiver1975/tarstreamer/src'), 'libphonenumber\\' => array($vendorDir . '/giggsey/libphonenumber-for-php-lite/src'), 'kornrunner\\Blurhash\\' => array($vendorDir . '/kornrunner/blurhash/src'), @@ -16,6 +17,7 @@ 'cweagans\\Composer\\' => array($vendorDir . '/cweagans/composer-patches/src'), 'bantu\\IniGetWrapper\\' => array($vendorDir . '/bantu/ini-get-wrapper/src'), 'ZipStreamer\\' => array($vendorDir . '/deepdiver/zipstreamer/src'), + 'Webmozart\\Assert\\' => array($vendorDir . '/webmozart/assert/src'), 'Webauthn\\' => array($vendorDir . '/web-auth/webauthn-lib/src'), 'Symfony\\Polyfill\\Uuid\\' => array($vendorDir . '/symfony/polyfill-uuid'), 'Symfony\\Polyfill\\Php86\\' => array($vendorDir . '/symfony/polyfill-php86'), @@ -28,9 +30,13 @@ 'Symfony\\Contracts\\Service\\' => array($vendorDir . '/symfony/service-contracts'), 'Symfony\\Contracts\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher-contracts'), 'Symfony\\Component\\Uid\\' => array($vendorDir . '/symfony/uid'), + 'Symfony\\Component\\TypeInfo\\' => array($vendorDir . '/symfony/type-info'), 'Symfony\\Component\\Translation\\' => array($vendorDir . '/symfony/translation'), 'Symfony\\Component\\String\\' => array($vendorDir . '/symfony/string'), + 'Symfony\\Component\\Serializer\\' => array($vendorDir . '/symfony/serializer'), 'Symfony\\Component\\Routing\\' => array($vendorDir . '/symfony/routing'), + 'Symfony\\Component\\PropertyInfo\\' => array($vendorDir . '/symfony/property-info'), + 'Symfony\\Component\\PropertyAccess\\' => array($vendorDir . '/symfony/property-access'), 'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'), 'Symfony\\Component\\Mime\\' => array($vendorDir . '/symfony/mime'), 'Symfony\\Component\\Mailer\\' => array($vendorDir . '/symfony/mailer'), @@ -40,6 +46,7 @@ 'Symfony\\Component\\DomCrawler\\' => array($vendorDir . '/symfony/dom-crawler'), 'Symfony\\Component\\CssSelector\\' => array($vendorDir . '/symfony/css-selector'), 'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'), + 'Symfony\\Component\\Clock\\' => array($vendorDir . '/symfony/clock'), 'Stecman\\Component\\Symfony\\Console\\BashCompletion\\' => array($vendorDir . '/stecman/symfony-console-completion/src'), 'SpomkyLabs\\Pki\\' => array($vendorDir . '/spomky-labs/pki-framework/src'), 'SearchDAV\\' => array($vendorDir . '/icewind/searchdav/src'), @@ -59,13 +66,13 @@ 'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'), 'Predis\\' => array($vendorDir . '/predis/predis/src'), 'ParagonIE\\ConstantTime\\' => array($vendorDir . '/paragonie/constant_time_encoding/src'), + 'PHPStan\\PhpDocParser\\' => array($vendorDir . '/phpstan/phpdoc-parser/src'), 'OpenStack\\' => array($vendorDir . '/php-opencloud/openstack/src'), 'Nextcloud\\LogNormalizer\\' => array($vendorDir . '/nextcloud/lognormalizer/src'), 'MicrosoftAzure\\Storage\\Common\\' => array($vendorDir . '/microsoft/azure-storage-common/src/Common'), 'MicrosoftAzure\\Storage\\Blob\\' => array($vendorDir . '/microsoft/azure-storage-blob/src/Blob'), 'Masterminds\\' => array($vendorDir . '/masterminds/html5/src'), 'MabeEnum\\' => array($vendorDir . '/marc-mabe/php-enum/src'), - 'Lcobucci\\Clock\\' => array($vendorDir . '/lcobucci/clock/src'), 'Laravel\\SerializableClosure\\' => array($vendorDir . '/laravel/serializable-closure/src'), 'JsonSchema\\' => array($vendorDir . '/justinrainbow/json-schema/src/JsonSchema'), 'JmesPath\\' => array($vendorDir . '/mtdowling/jmespath.php/src'), diff --git a/composer/autoload_static.php b/composer/autoload_static.php index a75415bdf..8220d1800 100644 --- a/composer/autoload_static.php +++ b/composer/autoload_static.php @@ -8,9 +8,11 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 { public static $files = array ( '6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php', + 'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php', '383eaff206634a77a1be54e64e6459c7' => __DIR__ . '/..' . '/sabre/uri/lib/functions.php', '7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php', - 'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php', + '8825ede83f2f289127722d4e842cf7e8' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/bootstrap.php', + 'b6b991a57620e2fb6b2f66f03fe9ddc2' => __DIR__ . '/..' . '/symfony/string/Resources/functions.php', '37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php', '2b9d0f43f9552984cfa82fee95491826' => __DIR__ . '/..' . '/sabre/event/lib/coroutine.php', 'd81bab31d3feb45bfe2f283ea3c8fdf7' => __DIR__ . '/..' . '/sabre/event/lib/Loop/functions.php', @@ -18,14 +20,13 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 '3569eecfeed3bcf0bad3c998a494ecb8' => __DIR__ . '/..' . '/sabre/xml/lib/Deserializer/functions.php', '93aa591bc4ca510c520999e34229ee79' => __DIR__ . '/..' . '/sabre/xml/lib/Serializer/functions.php', 'f598d06aa772fa33d905e87be6398fb1' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/bootstrap.php', - '8825ede83f2f289127722d4e842cf7e8' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/bootstrap.php', 'ebdb698ed4152ae445614b69b5e4bb6a' => __DIR__ . '/..' . '/sabre/http/lib/functions.php', + '9d2b9fc6db0f153a0a149fefb182415e' => __DIR__ . '/..' . '/symfony/polyfill-php84/bootstrap.php', '09f6b20656683369174dd6fa83b7e5fb' => __DIR__ . '/..' . '/symfony/polyfill-uuid/bootstrap.php', - 'b6b991a57620e2fb6b2f66f03fe9ddc2' => __DIR__ . '/..' . '/symfony/string/Resources/functions.php', 'b067bc7112e384b61c701452d53a14a8' => __DIR__ . '/..' . '/mtdowling/jmespath.php/src/JmesPath.php', + '2203a247e6fda86070a5e4e07aed533a' => __DIR__ . '/..' . '/symfony/clock/Resources/now.php', '8a9dc1de0ca7e01f3e08231539562f61' => __DIR__ . '/..' . '/aws/aws-sdk-php/src/functions.php', 'decc78cc4436b1292c6c0d151b19445c' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/bootstrap.php', - '9d2b9fc6db0f153a0a149fefb182415e' => __DIR__ . '/..' . '/symfony/polyfill-php84/bootstrap.php', '606a39d89246991a373564698c2d8383' => __DIR__ . '/..' . '/symfony/polyfill-php85/bootstrap.php', '2c2415ec15363ede1bff13a287462ba1' => __DIR__ . '/..' . '/symfony/polyfill-php86/bootstrap.php', 'a1105708a18b76903365ca1c4aa61b02' => __DIR__ . '/..' . '/symfony/translation/Resources/functions.php', @@ -39,6 +40,7 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 'p' => array ( 'phpseclib3\\' => 11, + 'phpDocumentor\\Reflection\\' => 25, ), 'o' => array ( @@ -71,6 +73,7 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 ), 'W' => array ( + 'Webmozart\\Assert\\' => 17, 'Webauthn\\' => 9, ), 'S' => @@ -86,9 +89,13 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 'Symfony\\Contracts\\Service\\' => 26, 'Symfony\\Contracts\\EventDispatcher\\' => 34, 'Symfony\\Component\\Uid\\' => 22, + 'Symfony\\Component\\TypeInfo\\' => 27, 'Symfony\\Component\\Translation\\' => 30, 'Symfony\\Component\\String\\' => 25, + 'Symfony\\Component\\Serializer\\' => 29, 'Symfony\\Component\\Routing\\' => 26, + 'Symfony\\Component\\PropertyInfo\\' => 31, + 'Symfony\\Component\\PropertyAccess\\' => 33, 'Symfony\\Component\\Process\\' => 26, 'Symfony\\Component\\Mime\\' => 23, 'Symfony\\Component\\Mailer\\' => 25, @@ -98,6 +105,7 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 'Symfony\\Component\\DomCrawler\\' => 29, 'Symfony\\Component\\CssSelector\\' => 30, 'Symfony\\Component\\Console\\' => 26, + 'Symfony\\Component\\Clock\\' => 24, 'Stecman\\Component\\Symfony\\Console\\BashCompletion\\' => 49, 'SpomkyLabs\\Pki\\' => 15, 'SearchDAV\\' => 10, @@ -120,6 +128,7 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 'Psr\\Cache\\' => 10, 'Predis\\' => 7, 'ParagonIE\\ConstantTime\\' => 23, + 'PHPStan\\PhpDocParser\\' => 21, ), 'O' => array ( @@ -138,7 +147,6 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 ), 'L' => array ( - 'Lcobucci\\Clock\\' => 15, 'Laravel\\SerializableClosure\\' => 28, ), 'J' => @@ -205,6 +213,12 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 array ( 0 => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib', ), + 'phpDocumentor\\Reflection\\' => + array ( + 0 => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src', + 1 => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src', + 2 => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src', + ), 'ownCloud\\TarStreamer\\' => array ( 0 => __DIR__ . '/..' . '/deepdiver1975/tarstreamer/src', @@ -237,6 +251,10 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 array ( 0 => __DIR__ . '/..' . '/deepdiver/zipstreamer/src', ), + 'Webmozart\\Assert\\' => + array ( + 0 => __DIR__ . '/..' . '/webmozart/assert/src', + ), 'Webauthn\\' => array ( 0 => __DIR__ . '/..' . '/web-auth/webauthn-lib/src', @@ -285,6 +303,10 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 array ( 0 => __DIR__ . '/..' . '/symfony/uid', ), + 'Symfony\\Component\\TypeInfo\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/type-info', + ), 'Symfony\\Component\\Translation\\' => array ( 0 => __DIR__ . '/..' . '/symfony/translation', @@ -293,10 +315,22 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 array ( 0 => __DIR__ . '/..' . '/symfony/string', ), + 'Symfony\\Component\\Serializer\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/serializer', + ), 'Symfony\\Component\\Routing\\' => array ( 0 => __DIR__ . '/..' . '/symfony/routing', ), + 'Symfony\\Component\\PropertyInfo\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/property-info', + ), + 'Symfony\\Component\\PropertyAccess\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/property-access', + ), 'Symfony\\Component\\Process\\' => array ( 0 => __DIR__ . '/..' . '/symfony/process', @@ -333,6 +367,10 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 array ( 0 => __DIR__ . '/..' . '/symfony/console', ), + 'Symfony\\Component\\Clock\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/clock', + ), 'Stecman\\Component\\Symfony\\Console\\BashCompletion\\' => array ( 0 => __DIR__ . '/..' . '/stecman/symfony-console-completion/src', @@ -410,6 +448,10 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 array ( 0 => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src', ), + 'PHPStan\\PhpDocParser\\' => + array ( + 0 => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src', + ), 'OpenStack\\' => array ( 0 => __DIR__ . '/..' . '/php-opencloud/openstack/src', @@ -434,10 +476,6 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 array ( 0 => __DIR__ . '/..' . '/marc-mabe/php-enum/src', ), - 'Lcobucci\\Clock\\' => - array ( - 0 => __DIR__ . '/..' . '/lcobucci/clock/src', - ), 'Laravel\\SerializableClosure\\' => array ( 0 => __DIR__ . '/..' . '/laravel/serializable-closure/src', @@ -967,20 +1005,29 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 'Brick\\Math\\BigRational' => __DIR__ . '/..' . '/brick/math/src/BigRational.php', 'Brick\\Math\\Exception\\DivisionByZeroException' => __DIR__ . '/..' . '/brick/math/src/Exception/DivisionByZeroException.php', 'Brick\\Math\\Exception\\IntegerOverflowException' => __DIR__ . '/..' . '/brick/math/src/Exception/IntegerOverflowException.php', + 'Brick\\Math\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/brick/math/src/Exception/InvalidArgumentException.php', 'Brick\\Math\\Exception\\MathException' => __DIR__ . '/..' . '/brick/math/src/Exception/MathException.php', 'Brick\\Math\\Exception\\NegativeNumberException' => __DIR__ . '/..' . '/brick/math/src/Exception/NegativeNumberException.php', + 'Brick\\Math\\Exception\\NoInverseException' => __DIR__ . '/..' . '/brick/math/src/Exception/NoInverseException.php', 'Brick\\Math\\Exception\\NumberFormatException' => __DIR__ . '/..' . '/brick/math/src/Exception/NumberFormatException.php', + 'Brick\\Math\\Exception\\RandomSourceException' => __DIR__ . '/..' . '/brick/math/src/Exception/RandomSourceException.php', 'Brick\\Math\\Exception\\RoundingNecessaryException' => __DIR__ . '/..' . '/brick/math/src/Exception/RoundingNecessaryException.php', + 'Brick\\Math\\Exception\\UnsupportedPlatformException' => __DIR__ . '/..' . '/brick/math/src/Exception/UnsupportedPlatformException.php', 'Brick\\Math\\Internal\\Calculator' => __DIR__ . '/..' . '/brick/math/src/Internal/Calculator.php', + 'Brick\\Math\\Internal\\CalculatorRegistry' => __DIR__ . '/..' . '/brick/math/src/Internal/CalculatorRegistry.php', 'Brick\\Math\\Internal\\Calculator\\BcMathCalculator' => __DIR__ . '/..' . '/brick/math/src/Internal/Calculator/BcMathCalculator.php', 'Brick\\Math\\Internal\\Calculator\\GmpCalculator' => __DIR__ . '/..' . '/brick/math/src/Internal/Calculator/GmpCalculator.php', 'Brick\\Math\\Internal\\Calculator\\NativeCalculator' => __DIR__ . '/..' . '/brick/math/src/Internal/Calculator/NativeCalculator.php', + 'Brick\\Math\\Internal\\DecimalHelper' => __DIR__ . '/..' . '/brick/math/src/Internal/DecimalHelper.php', + 'Brick\\Math\\Internal\\Safe' => __DIR__ . '/..' . '/brick/math/src/Internal/Safe.php', 'Brick\\Math\\RoundingMode' => __DIR__ . '/..' . '/brick/math/src/RoundingMode.php', 'CBOR\\AbstractCBORObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/AbstractCBORObject.php', 'CBOR\\ByteStringObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/ByteStringObject.php', 'CBOR\\CBORObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/CBORObject.php', 'CBOR\\Decoder' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Decoder.php', 'CBOR\\DecoderInterface' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/DecoderInterface.php', + 'CBOR\\Encoder' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Encoder.php', + 'CBOR\\EncoderInterface' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/EncoderInterface.php', 'CBOR\\IndefiniteLengthByteStringObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/IndefiniteLengthByteStringObject.php', 'CBOR\\IndefiniteLengthListObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/IndefiniteLengthListObject.php', 'CBOR\\IndefiniteLengthMapObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/IndefiniteLengthMapObject.php', @@ -1021,6 +1068,7 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 'CBOR\\Tag\\GenericTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/GenericTag.php', 'CBOR\\Tag\\MimeTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/MimeTag.php', 'CBOR\\Tag\\NegativeBigIntegerTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/NegativeBigIntegerTag.php', + 'CBOR\\Tag\\SelfDescribeCBORTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/SelfDescribeCBORTag.php', 'CBOR\\Tag\\TagInterface' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/TagInterface.php', 'CBOR\\Tag\\TagManager' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/TagManager.php', 'CBOR\\Tag\\TagManagerInterface' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/TagManagerInterface.php', @@ -1063,12 +1111,19 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 'Cose\\Algorithm\\Signature\\Signature' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/Signature.php', 'Cose\\Algorithms' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithms.php', 'Cose\\BigInteger' => __DIR__ . '/..' . '/web-auth/cose-lib/src/BigInteger.php', + 'Cose\\Encryption\\CoseEncrypt0Tag' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Encryption/CoseEncrypt0Tag.php', + 'Cose\\Encryption\\CoseEncryptTag' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Encryption/CoseEncryptTag.php', 'Cose\\Hash' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Hash.php', 'Cose\\Key\\Ec2Key' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Key/Ec2Key.php', 'Cose\\Key\\Key' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Key/Key.php', 'Cose\\Key\\OkpKey' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Key/OkpKey.php', 'Cose\\Key\\RsaKey' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Key/RsaKey.php', 'Cose\\Key\\SymmetricKey' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Key/SymmetricKey.php', + 'Cose\\Mac\\CoseMac0Tag' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Mac/CoseMac0Tag.php', + 'Cose\\Mac\\CoseMacTag' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Mac/CoseMacTag.php', + 'Cose\\Signature\\CoseSign1Tag' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Signature/CoseSign1Tag.php', + 'Cose\\Signature\\CoseSignTag' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Signature/CoseSignTag.php', + 'Cose\\Signature\\Signature1' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Signature/Signature1.php', 'DelayedTargetValidation' => __DIR__ . '/..' . '/symfony/polyfill-php85/Resources/stubs/DelayedTargetValidation.php', 'Deprecated' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/Deprecated.php', 'Doctrine\\Common\\EventArgs' => __DIR__ . '/..' . '/doctrine/event-manager/src/EventArgs.php', @@ -1852,9 +1907,6 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 'Laravel\\SerializableClosure\\Support\\ReflectionClosure' => __DIR__ . '/..' . '/laravel/serializable-closure/src/Support/ReflectionClosure.php', 'Laravel\\SerializableClosure\\Support\\SelfReference' => __DIR__ . '/..' . '/laravel/serializable-closure/src/Support/SelfReference.php', 'Laravel\\SerializableClosure\\UnsignedSerializableClosure' => __DIR__ . '/..' . '/laravel/serializable-closure/src/UnsignedSerializableClosure.php', - 'Lcobucci\\Clock\\Clock' => __DIR__ . '/..' . '/lcobucci/clock/src/Clock.php', - 'Lcobucci\\Clock\\FrozenClock' => __DIR__ . '/..' . '/lcobucci/clock/src/FrozenClock.php', - 'Lcobucci\\Clock\\SystemClock' => __DIR__ . '/..' . '/lcobucci/clock/src/SystemClock.php', 'MabeEnum\\Enum' => __DIR__ . '/..' . '/marc-mabe/php-enum/src/Enum.php', 'MabeEnum\\EnumMap' => __DIR__ . '/..' . '/marc-mabe/php-enum/src/EnumMap.php', 'MabeEnum\\EnumSerializableTrait' => __DIR__ . '/..' . '/marc-mabe/php-enum/src/EnumSerializableTrait.php', @@ -2151,6 +2203,97 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 'PEAR_Error' => __DIR__ . '/..' . '/pear/pear-core-minimal/src/PEAR.php', 'PEAR_ErrorStack' => __DIR__ . '/..' . '/pear/pear-core-minimal/src/PEAR/ErrorStack.php', 'PEAR_Exception' => __DIR__ . '/..' . '/pear/pear_exception/PEAR/Exception.php', + 'PHPStan\\PhpDocParser\\Ast\\AbstractNodeVisitor' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/AbstractNodeVisitor.php', + 'PHPStan\\PhpDocParser\\Ast\\Attribute' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Attribute.php', + 'PHPStan\\PhpDocParser\\Ast\\Comment' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Comment.php', + 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprArrayItemNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayItemNode.php', + 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprArrayNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayNode.php', + 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprFalseNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFalseNode.php', + 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprFloatNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFloatNode.php', + 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprIntegerNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprIntegerNode.php', + 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNode.php', + 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprNullNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNullNode.php', + 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprStringNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprStringNode.php', + 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprTrueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprTrueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstFetchNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstFetchNode.php', + 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\DoctrineConstExprStringNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/DoctrineConstExprStringNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Node' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Node.php', + 'PHPStan\\PhpDocParser\\Ast\\NodeAttributes' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/NodeAttributes.php', + 'PHPStan\\PhpDocParser\\Ast\\NodeTraverser' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/NodeTraverser.php', + 'PHPStan\\PhpDocParser\\Ast\\NodeVisitor' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/NodeVisitor.php', + 'PHPStan\\PhpDocParser\\Ast\\NodeVisitor\\CloningVisitor' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/NodeVisitor/CloningVisitor.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\AssertTagMethodValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagMethodValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\AssertTagPropertyValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagPropertyValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\AssertTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\DeprecatedTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/DeprecatedTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineAnnotation' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineAnnotation.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineArgument' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArgument.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineArray' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArray.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineArrayItem' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArrayItem.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ExtendsTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ExtendsTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\GenericTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/GenericTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ImplementsTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ImplementsTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\InvalidTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/InvalidTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MethodTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MethodTagValueParameterNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueParameterNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MixinTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/MixinTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamClosureThisTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamClosureThisTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamImmediatelyInvokedCallableTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamImmediatelyInvokedCallableTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamLaterInvokedCallableTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamLaterInvokedCallableTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamOutTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamOutTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocChildNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocChildNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTagNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTextNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTextNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PropertyTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PropertyTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PureUnlessCallableIsImpureTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PureUnlessCallableIsImpureTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PureUnlessParameterIsPassedTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PureUnlessParameterIsPassedTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\RequireExtendsTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireExtendsTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\RequireImplementsTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireImplementsTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ReturnTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ReturnTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\SealedTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/SealedTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\SelfOutTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/SelfOutTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TemplateTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/TemplateTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ThrowsTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ThrowsTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TypeAliasImportTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasImportTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TypeAliasTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TypelessParamTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypelessParamTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\UsesTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/UsesTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\VarTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/VarTagValueNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\ArrayShapeItemNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeItemNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\ArrayShapeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\ArrayShapeUnsealedTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeUnsealedTypeNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\ArrayTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayTypeNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\CallableTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\CallableTypeParameterNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeParameterNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\ConditionalTypeForParameterNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeForParameterNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\ConditionalTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\ConstTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ConstTypeNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\GenericTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/GenericTypeNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\IdentifierTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/IdentifierTypeNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\IntersectionTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/IntersectionTypeNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\InvalidTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/InvalidTypeNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\NullableTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/NullableTypeNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\ObjectShapeItemNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeItemNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\ObjectShapeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\OffsetAccessTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/OffsetAccessTypeNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\ThisTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ThisTypeNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\TypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/TypeNode.php', + 'PHPStan\\PhpDocParser\\Ast\\Type\\UnionTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/UnionTypeNode.php', + 'PHPStan\\PhpDocParser\\Lexer\\Lexer' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Lexer/Lexer.php', + 'PHPStan\\PhpDocParser\\ParserConfig' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/ParserConfig.php', + 'PHPStan\\PhpDocParser\\Parser\\ConstExprParser' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php', + 'PHPStan\\PhpDocParser\\Parser\\ParserException' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/ParserException.php', + 'PHPStan\\PhpDocParser\\Parser\\PhpDocParser' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/PhpDocParser.php', + 'PHPStan\\PhpDocParser\\Parser\\StringUnescaper' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/StringUnescaper.php', + 'PHPStan\\PhpDocParser\\Parser\\TokenIterator' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/TokenIterator.php', + 'PHPStan\\PhpDocParser\\Parser\\TypeParser' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/TypeParser.php', + 'PHPStan\\PhpDocParser\\Printer\\DiffElem' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Printer/DiffElem.php', + 'PHPStan\\PhpDocParser\\Printer\\Differ' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Printer/Differ.php', + 'PHPStan\\PhpDocParser\\Printer\\Printer' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Printer/Printer.php', 'ParagonIE\\ConstantTime\\Base32' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Base32.php', 'ParagonIE\\ConstantTime\\Base32Hex' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Base32Hex.php', 'ParagonIE\\ConstantTime\\Base64' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Base64.php', @@ -3558,6 +3701,13 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 'Stecman\\Component\\Symfony\\Console\\BashCompletion\\EnvironmentCompletionContext' => __DIR__ . '/..' . '/stecman/symfony-console-completion/src/EnvironmentCompletionContext.php', 'Stecman\\Component\\Symfony\\Console\\BashCompletion\\HookFactory' => __DIR__ . '/..' . '/stecman/symfony-console-completion/src/HookFactory.php', 'Stringable' => __DIR__ . '/..' . '/marc-mabe/php-enum/stubs/Stringable.php', + 'Symfony\\Component\\Clock\\Clock' => __DIR__ . '/..' . '/symfony/clock/Clock.php', + 'Symfony\\Component\\Clock\\ClockAwareTrait' => __DIR__ . '/..' . '/symfony/clock/ClockAwareTrait.php', + 'Symfony\\Component\\Clock\\ClockInterface' => __DIR__ . '/..' . '/symfony/clock/ClockInterface.php', + 'Symfony\\Component\\Clock\\DatePoint' => __DIR__ . '/..' . '/symfony/clock/DatePoint.php', + 'Symfony\\Component\\Clock\\MockClock' => __DIR__ . '/..' . '/symfony/clock/MockClock.php', + 'Symfony\\Component\\Clock\\MonotonicClock' => __DIR__ . '/..' . '/symfony/clock/MonotonicClock.php', + 'Symfony\\Component\\Clock\\NativeClock' => __DIR__ . '/..' . '/symfony/clock/NativeClock.php', 'Symfony\\Component\\Console\\Application' => __DIR__ . '/..' . '/symfony/console/Application.php', 'Symfony\\Component\\Console\\Attribute\\Argument' => __DIR__ . '/..' . '/symfony/console/Attribute/Argument.php', 'Symfony\\Component\\Console\\Attribute\\AsCommand' => __DIR__ . '/..' . '/symfony/console/Attribute/AsCommand.php', @@ -4017,6 +4167,51 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 'Symfony\\Component\\Process\\Pipes\\WindowsPipes' => __DIR__ . '/..' . '/symfony/process/Pipes/WindowsPipes.php', 'Symfony\\Component\\Process\\Process' => __DIR__ . '/..' . '/symfony/process/Process.php', 'Symfony\\Component\\Process\\ProcessUtils' => __DIR__ . '/..' . '/symfony/process/ProcessUtils.php', + 'Symfony\\Component\\PropertyAccess\\Exception\\AccessException' => __DIR__ . '/..' . '/symfony/property-access/Exception/AccessException.php', + 'Symfony\\Component\\PropertyAccess\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/property-access/Exception/ExceptionInterface.php', + 'Symfony\\Component\\PropertyAccess\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/property-access/Exception/InvalidArgumentException.php', + 'Symfony\\Component\\PropertyAccess\\Exception\\InvalidPropertyPathException' => __DIR__ . '/..' . '/symfony/property-access/Exception/InvalidPropertyPathException.php', + 'Symfony\\Component\\PropertyAccess\\Exception\\InvalidTypeException' => __DIR__ . '/..' . '/symfony/property-access/Exception/InvalidTypeException.php', + 'Symfony\\Component\\PropertyAccess\\Exception\\NoSuchIndexException' => __DIR__ . '/..' . '/symfony/property-access/Exception/NoSuchIndexException.php', + 'Symfony\\Component\\PropertyAccess\\Exception\\NoSuchPropertyException' => __DIR__ . '/..' . '/symfony/property-access/Exception/NoSuchPropertyException.php', + 'Symfony\\Component\\PropertyAccess\\Exception\\OutOfBoundsException' => __DIR__ . '/..' . '/symfony/property-access/Exception/OutOfBoundsException.php', + 'Symfony\\Component\\PropertyAccess\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/property-access/Exception/RuntimeException.php', + 'Symfony\\Component\\PropertyAccess\\Exception\\UnexpectedTypeException' => __DIR__ . '/..' . '/symfony/property-access/Exception/UnexpectedTypeException.php', + 'Symfony\\Component\\PropertyAccess\\Exception\\UninitializedPropertyException' => __DIR__ . '/..' . '/symfony/property-access/Exception/UninitializedPropertyException.php', + 'Symfony\\Component\\PropertyAccess\\PropertyAccess' => __DIR__ . '/..' . '/symfony/property-access/PropertyAccess.php', + 'Symfony\\Component\\PropertyAccess\\PropertyAccessor' => __DIR__ . '/..' . '/symfony/property-access/PropertyAccessor.php', + 'Symfony\\Component\\PropertyAccess\\PropertyAccessorBuilder' => __DIR__ . '/..' . '/symfony/property-access/PropertyAccessorBuilder.php', + 'Symfony\\Component\\PropertyAccess\\PropertyAccessorInterface' => __DIR__ . '/..' . '/symfony/property-access/PropertyAccessorInterface.php', + 'Symfony\\Component\\PropertyAccess\\PropertyPath' => __DIR__ . '/..' . '/symfony/property-access/PropertyPath.php', + 'Symfony\\Component\\PropertyAccess\\PropertyPathBuilder' => __DIR__ . '/..' . '/symfony/property-access/PropertyPathBuilder.php', + 'Symfony\\Component\\PropertyAccess\\PropertyPathInterface' => __DIR__ . '/..' . '/symfony/property-access/PropertyPathInterface.php', + 'Symfony\\Component\\PropertyAccess\\PropertyPathIterator' => __DIR__ . '/..' . '/symfony/property-access/PropertyPathIterator.php', + 'Symfony\\Component\\PropertyAccess\\PropertyPathIteratorInterface' => __DIR__ . '/..' . '/symfony/property-access/PropertyPathIteratorInterface.php', + 'Symfony\\Component\\PropertyInfo\\DependencyInjection\\PropertyInfoConstructorPass' => __DIR__ . '/..' . '/symfony/property-info/DependencyInjection/PropertyInfoConstructorPass.php', + 'Symfony\\Component\\PropertyInfo\\DependencyInjection\\PropertyInfoPass' => __DIR__ . '/..' . '/symfony/property-info/DependencyInjection/PropertyInfoPass.php', + 'Symfony\\Component\\PropertyInfo\\Extractor\\ConstructorArgumentTypeExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/Extractor/ConstructorArgumentTypeExtractorInterface.php', + 'Symfony\\Component\\PropertyInfo\\Extractor\\ConstructorExtractor' => __DIR__ . '/..' . '/symfony/property-info/Extractor/ConstructorExtractor.php', + 'Symfony\\Component\\PropertyInfo\\Extractor\\PhpDocExtractor' => __DIR__ . '/..' . '/symfony/property-info/Extractor/PhpDocExtractor.php', + 'Symfony\\Component\\PropertyInfo\\Extractor\\PhpStanExtractor' => __DIR__ . '/..' . '/symfony/property-info/Extractor/PhpStanExtractor.php', + 'Symfony\\Component\\PropertyInfo\\Extractor\\ReflectionExtractor' => __DIR__ . '/..' . '/symfony/property-info/Extractor/ReflectionExtractor.php', + 'Symfony\\Component\\PropertyInfo\\Extractor\\SerializerExtractor' => __DIR__ . '/..' . '/symfony/property-info/Extractor/SerializerExtractor.php', + 'Symfony\\Component\\PropertyInfo\\PropertyAccessExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/PropertyAccessExtractorInterface.php', + 'Symfony\\Component\\PropertyInfo\\PropertyDescriptionExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/PropertyDescriptionExtractorInterface.php', + 'Symfony\\Component\\PropertyInfo\\PropertyDocBlockExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/PropertyDocBlockExtractorInterface.php', + 'Symfony\\Component\\PropertyInfo\\PropertyInfoCacheExtractor' => __DIR__ . '/..' . '/symfony/property-info/PropertyInfoCacheExtractor.php', + 'Symfony\\Component\\PropertyInfo\\PropertyInfoExtractor' => __DIR__ . '/..' . '/symfony/property-info/PropertyInfoExtractor.php', + 'Symfony\\Component\\PropertyInfo\\PropertyInfoExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/PropertyInfoExtractorInterface.php', + 'Symfony\\Component\\PropertyInfo\\PropertyInitializableExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/PropertyInitializableExtractorInterface.php', + 'Symfony\\Component\\PropertyInfo\\PropertyListExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/PropertyListExtractorInterface.php', + 'Symfony\\Component\\PropertyInfo\\PropertyReadInfo' => __DIR__ . '/..' . '/symfony/property-info/PropertyReadInfo.php', + 'Symfony\\Component\\PropertyInfo\\PropertyReadInfoExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/PropertyReadInfoExtractorInterface.php', + 'Symfony\\Component\\PropertyInfo\\PropertyTypeExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/PropertyTypeExtractorInterface.php', + 'Symfony\\Component\\PropertyInfo\\PropertyWriteInfo' => __DIR__ . '/..' . '/symfony/property-info/PropertyWriteInfo.php', + 'Symfony\\Component\\PropertyInfo\\PropertyWriteInfoExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/PropertyWriteInfoExtractorInterface.php', + 'Symfony\\Component\\PropertyInfo\\Type' => __DIR__ . '/..' . '/symfony/property-info/Type.php', + 'Symfony\\Component\\PropertyInfo\\Util\\LegacyTypeConverter' => __DIR__ . '/..' . '/symfony/property-info/Util/LegacyTypeConverter.php', + 'Symfony\\Component\\PropertyInfo\\Util\\PhpDocTypeHelper' => __DIR__ . '/..' . '/symfony/property-info/Util/PhpDocTypeHelper.php', + 'Symfony\\Component\\PropertyInfo\\Util\\PhpStanTypeHelper' => __DIR__ . '/..' . '/symfony/property-info/Util/PhpStanTypeHelper.php', 'Symfony\\Component\\Routing\\Alias' => __DIR__ . '/..' . '/symfony/routing/Alias.php', 'Symfony\\Component\\Routing\\Annotation\\Route' => __DIR__ . '/..' . '/symfony/routing/Annotation/Route.php', 'Symfony\\Component\\Routing\\Attribute\\Route' => __DIR__ . '/..' . '/symfony/routing/Attribute/Route.php', @@ -4088,6 +4283,140 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 'Symfony\\Component\\Routing\\RouteCompilerInterface' => __DIR__ . '/..' . '/symfony/routing/RouteCompilerInterface.php', 'Symfony\\Component\\Routing\\Router' => __DIR__ . '/..' . '/symfony/routing/Router.php', 'Symfony\\Component\\Routing\\RouterInterface' => __DIR__ . '/..' . '/symfony/routing/RouterInterface.php', + 'Symfony\\Component\\Serializer\\Annotation\\Context' => __DIR__ . '/..' . '/symfony/serializer/Annotation/Context.php', + 'Symfony\\Component\\Serializer\\Annotation\\DiscriminatorMap' => __DIR__ . '/..' . '/symfony/serializer/Annotation/DiscriminatorMap.php', + 'Symfony\\Component\\Serializer\\Annotation\\Groups' => __DIR__ . '/..' . '/symfony/serializer/Annotation/Groups.php', + 'Symfony\\Component\\Serializer\\Annotation\\Ignore' => __DIR__ . '/..' . '/symfony/serializer/Annotation/Ignore.php', + 'Symfony\\Component\\Serializer\\Annotation\\MaxDepth' => __DIR__ . '/..' . '/symfony/serializer/Annotation/MaxDepth.php', + 'Symfony\\Component\\Serializer\\Annotation\\SerializedName' => __DIR__ . '/..' . '/symfony/serializer/Annotation/SerializedName.php', + 'Symfony\\Component\\Serializer\\Annotation\\SerializedPath' => __DIR__ . '/..' . '/symfony/serializer/Annotation/SerializedPath.php', + 'Symfony\\Component\\Serializer\\Attribute\\Context' => __DIR__ . '/..' . '/symfony/serializer/Attribute/Context.php', + 'Symfony\\Component\\Serializer\\Attribute\\DiscriminatorMap' => __DIR__ . '/..' . '/symfony/serializer/Attribute/DiscriminatorMap.php', + 'Symfony\\Component\\Serializer\\Attribute\\ExtendsSerializationFor' => __DIR__ . '/..' . '/symfony/serializer/Attribute/ExtendsSerializationFor.php', + 'Symfony\\Component\\Serializer\\Attribute\\Groups' => __DIR__ . '/..' . '/symfony/serializer/Attribute/Groups.php', + 'Symfony\\Component\\Serializer\\Attribute\\Ignore' => __DIR__ . '/..' . '/symfony/serializer/Attribute/Ignore.php', + 'Symfony\\Component\\Serializer\\Attribute\\MaxDepth' => __DIR__ . '/..' . '/symfony/serializer/Attribute/MaxDepth.php', + 'Symfony\\Component\\Serializer\\Attribute\\SerializedName' => __DIR__ . '/..' . '/symfony/serializer/Attribute/SerializedName.php', + 'Symfony\\Component\\Serializer\\Attribute\\SerializedPath' => __DIR__ . '/..' . '/symfony/serializer/Attribute/SerializedPath.php', + 'Symfony\\Component\\Serializer\\CacheWarmer\\CompiledClassMetadataCacheWarmer' => __DIR__ . '/..' . '/symfony/serializer/CacheWarmer/CompiledClassMetadataCacheWarmer.php', + 'Symfony\\Component\\Serializer\\Command\\DebugCommand' => __DIR__ . '/..' . '/symfony/serializer/Command/DebugCommand.php', + 'Symfony\\Component\\Serializer\\Context\\ContextBuilderInterface' => __DIR__ . '/..' . '/symfony/serializer/Context/ContextBuilderInterface.php', + 'Symfony\\Component\\Serializer\\Context\\ContextBuilderTrait' => __DIR__ . '/..' . '/symfony/serializer/Context/ContextBuilderTrait.php', + 'Symfony\\Component\\Serializer\\Context\\Encoder\\CsvEncoderContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Encoder/CsvEncoderContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Encoder\\JsonEncoderContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Encoder/JsonEncoderContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Encoder\\XmlEncoderContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Encoder/XmlEncoderContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Encoder\\YamlEncoderContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Encoder/YamlEncoderContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Normalizer\\AbstractNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/AbstractNormalizerContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Normalizer\\AbstractObjectNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/AbstractObjectNormalizerContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Normalizer\\BackedEnumNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/BackedEnumNormalizerContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Normalizer\\ConstraintViolationListNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/ConstraintViolationListNormalizerContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Normalizer\\DateIntervalNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/DateIntervalNormalizerContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Normalizer\\DateTimeNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/DateTimeNormalizerContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Normalizer\\FormErrorNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/FormErrorNormalizerContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Normalizer\\GetSetMethodNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/GetSetMethodNormalizerContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Normalizer\\JsonSerializableNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/JsonSerializableNormalizerContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Normalizer\\ObjectNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/ObjectNormalizerContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Normalizer\\ProblemNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/ProblemNormalizerContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Normalizer\\PropertyNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/PropertyNormalizerContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Normalizer\\UidNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/UidNormalizerContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\Normalizer\\UnwrappingDenormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/UnwrappingDenormalizerContextBuilder.php', + 'Symfony\\Component\\Serializer\\Context\\SerializerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/SerializerContextBuilder.php', + 'Symfony\\Component\\Serializer\\DataCollector\\SerializerDataCollector' => __DIR__ . '/..' . '/symfony/serializer/DataCollector/SerializerDataCollector.php', + 'Symfony\\Component\\Serializer\\Debug\\TraceableEncoder' => __DIR__ . '/..' . '/symfony/serializer/Debug/TraceableEncoder.php', + 'Symfony\\Component\\Serializer\\Debug\\TraceableNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Debug/TraceableNormalizer.php', + 'Symfony\\Component\\Serializer\\Debug\\TraceableSerializer' => __DIR__ . '/..' . '/symfony/serializer/Debug/TraceableSerializer.php', + 'Symfony\\Component\\Serializer\\DependencyInjection\\AttributeMetadataPass' => __DIR__ . '/..' . '/symfony/serializer/DependencyInjection/AttributeMetadataPass.php', + 'Symfony\\Component\\Serializer\\DependencyInjection\\SerializerPass' => __DIR__ . '/..' . '/symfony/serializer/DependencyInjection/SerializerPass.php', + 'Symfony\\Component\\Serializer\\Encoder\\ChainDecoder' => __DIR__ . '/..' . '/symfony/serializer/Encoder/ChainDecoder.php', + 'Symfony\\Component\\Serializer\\Encoder\\ChainEncoder' => __DIR__ . '/..' . '/symfony/serializer/Encoder/ChainEncoder.php', + 'Symfony\\Component\\Serializer\\Encoder\\ContextAwareDecoderInterface' => __DIR__ . '/..' . '/symfony/serializer/Encoder/ContextAwareDecoderInterface.php', + 'Symfony\\Component\\Serializer\\Encoder\\ContextAwareEncoderInterface' => __DIR__ . '/..' . '/symfony/serializer/Encoder/ContextAwareEncoderInterface.php', + 'Symfony\\Component\\Serializer\\Encoder\\CsvEncoder' => __DIR__ . '/..' . '/symfony/serializer/Encoder/CsvEncoder.php', + 'Symfony\\Component\\Serializer\\Encoder\\DecoderInterface' => __DIR__ . '/..' . '/symfony/serializer/Encoder/DecoderInterface.php', + 'Symfony\\Component\\Serializer\\Encoder\\EncoderInterface' => __DIR__ . '/..' . '/symfony/serializer/Encoder/EncoderInterface.php', + 'Symfony\\Component\\Serializer\\Encoder\\JsonDecode' => __DIR__ . '/..' . '/symfony/serializer/Encoder/JsonDecode.php', + 'Symfony\\Component\\Serializer\\Encoder\\JsonEncode' => __DIR__ . '/..' . '/symfony/serializer/Encoder/JsonEncode.php', + 'Symfony\\Component\\Serializer\\Encoder\\JsonEncoder' => __DIR__ . '/..' . '/symfony/serializer/Encoder/JsonEncoder.php', + 'Symfony\\Component\\Serializer\\Encoder\\NormalizationAwareInterface' => __DIR__ . '/..' . '/symfony/serializer/Encoder/NormalizationAwareInterface.php', + 'Symfony\\Component\\Serializer\\Encoder\\XmlEncoder' => __DIR__ . '/..' . '/symfony/serializer/Encoder/XmlEncoder.php', + 'Symfony\\Component\\Serializer\\Encoder\\YamlEncoder' => __DIR__ . '/..' . '/symfony/serializer/Encoder/YamlEncoder.php', + 'Symfony\\Component\\Serializer\\Exception\\BadMethodCallException' => __DIR__ . '/..' . '/symfony/serializer/Exception/BadMethodCallException.php', + 'Symfony\\Component\\Serializer\\Exception\\CircularReferenceException' => __DIR__ . '/..' . '/symfony/serializer/Exception/CircularReferenceException.php', + 'Symfony\\Component\\Serializer\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/serializer/Exception/ExceptionInterface.php', + 'Symfony\\Component\\Serializer\\Exception\\ExtraAttributesException' => __DIR__ . '/..' . '/symfony/serializer/Exception/ExtraAttributesException.php', + 'Symfony\\Component\\Serializer\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/serializer/Exception/InvalidArgumentException.php', + 'Symfony\\Component\\Serializer\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/serializer/Exception/LogicException.php', + 'Symfony\\Component\\Serializer\\Exception\\MappingException' => __DIR__ . '/..' . '/symfony/serializer/Exception/MappingException.php', + 'Symfony\\Component\\Serializer\\Exception\\MissingConstructorArgumentsException' => __DIR__ . '/..' . '/symfony/serializer/Exception/MissingConstructorArgumentsException.php', + 'Symfony\\Component\\Serializer\\Exception\\NotEncodableValueException' => __DIR__ . '/..' . '/symfony/serializer/Exception/NotEncodableValueException.php', + 'Symfony\\Component\\Serializer\\Exception\\NotNormalizableValueException' => __DIR__ . '/..' . '/symfony/serializer/Exception/NotNormalizableValueException.php', + 'Symfony\\Component\\Serializer\\Exception\\PartialDenormalizationException' => __DIR__ . '/..' . '/symfony/serializer/Exception/PartialDenormalizationException.php', + 'Symfony\\Component\\Serializer\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/serializer/Exception/RuntimeException.php', + 'Symfony\\Component\\Serializer\\Exception\\UnexpectedPropertyException' => __DIR__ . '/..' . '/symfony/serializer/Exception/UnexpectedPropertyException.php', + 'Symfony\\Component\\Serializer\\Exception\\UnexpectedValueException' => __DIR__ . '/..' . '/symfony/serializer/Exception/UnexpectedValueException.php', + 'Symfony\\Component\\Serializer\\Exception\\UnsupportedException' => __DIR__ . '/..' . '/symfony/serializer/Exception/UnsupportedException.php', + 'Symfony\\Component\\Serializer\\Exception\\UnsupportedFormatException' => __DIR__ . '/..' . '/symfony/serializer/Exception/UnsupportedFormatException.php', + 'Symfony\\Component\\Serializer\\Extractor\\ObjectPropertyListExtractor' => __DIR__ . '/..' . '/symfony/serializer/Extractor/ObjectPropertyListExtractor.php', + 'Symfony\\Component\\Serializer\\Extractor\\ObjectPropertyListExtractorInterface' => __DIR__ . '/..' . '/symfony/serializer/Extractor/ObjectPropertyListExtractorInterface.php', + 'Symfony\\Component\\Serializer\\Mapping\\AttributeMetadata' => __DIR__ . '/..' . '/symfony/serializer/Mapping/AttributeMetadata.php', + 'Symfony\\Component\\Serializer\\Mapping\\AttributeMetadataInterface' => __DIR__ . '/..' . '/symfony/serializer/Mapping/AttributeMetadataInterface.php', + 'Symfony\\Component\\Serializer\\Mapping\\ClassDiscriminatorFromClassMetadata' => __DIR__ . '/..' . '/symfony/serializer/Mapping/ClassDiscriminatorFromClassMetadata.php', + 'Symfony\\Component\\Serializer\\Mapping\\ClassDiscriminatorMapping' => __DIR__ . '/..' . '/symfony/serializer/Mapping/ClassDiscriminatorMapping.php', + 'Symfony\\Component\\Serializer\\Mapping\\ClassDiscriminatorResolverInterface' => __DIR__ . '/..' . '/symfony/serializer/Mapping/ClassDiscriminatorResolverInterface.php', + 'Symfony\\Component\\Serializer\\Mapping\\ClassMetadata' => __DIR__ . '/..' . '/symfony/serializer/Mapping/ClassMetadata.php', + 'Symfony\\Component\\Serializer\\Mapping\\ClassMetadataInterface' => __DIR__ . '/..' . '/symfony/serializer/Mapping/ClassMetadataInterface.php', + 'Symfony\\Component\\Serializer\\Mapping\\Factory\\CacheClassMetadataFactory' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Factory/CacheClassMetadataFactory.php', + 'Symfony\\Component\\Serializer\\Mapping\\Factory\\ClassMetadataFactory' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Factory/ClassMetadataFactory.php', + 'Symfony\\Component\\Serializer\\Mapping\\Factory\\ClassMetadataFactoryCompiler' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Factory/ClassMetadataFactoryCompiler.php', + 'Symfony\\Component\\Serializer\\Mapping\\Factory\\ClassMetadataFactoryInterface' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Factory/ClassMetadataFactoryInterface.php', + 'Symfony\\Component\\Serializer\\Mapping\\Factory\\ClassResolverTrait' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Factory/ClassResolverTrait.php', + 'Symfony\\Component\\Serializer\\Mapping\\Factory\\CompiledClassMetadataFactory' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Factory/CompiledClassMetadataFactory.php', + 'Symfony\\Component\\Serializer\\Mapping\\Loader\\AccessorCollisionResolverTrait' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Loader/AccessorCollisionResolverTrait.php', + 'Symfony\\Component\\Serializer\\Mapping\\Loader\\AttributeLoader' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Loader/AttributeLoader.php', + 'Symfony\\Component\\Serializer\\Mapping\\Loader\\FileLoader' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Loader/FileLoader.php', + 'Symfony\\Component\\Serializer\\Mapping\\Loader\\LoaderChain' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Loader/LoaderChain.php', + 'Symfony\\Component\\Serializer\\Mapping\\Loader\\LoaderInterface' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Loader/LoaderInterface.php', + 'Symfony\\Component\\Serializer\\Mapping\\Loader\\XmlFileLoader' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Loader/XmlFileLoader.php', + 'Symfony\\Component\\Serializer\\Mapping\\Loader\\YamlFileLoader' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Loader/YamlFileLoader.php', + 'Symfony\\Component\\Serializer\\NameConverter\\AdvancedNameConverterInterface' => __DIR__ . '/..' . '/symfony/serializer/NameConverter/AdvancedNameConverterInterface.php', + 'Symfony\\Component\\Serializer\\NameConverter\\CamelCaseToSnakeCaseNameConverter' => __DIR__ . '/..' . '/symfony/serializer/NameConverter/CamelCaseToSnakeCaseNameConverter.php', + 'Symfony\\Component\\Serializer\\NameConverter\\MetadataAwareNameConverter' => __DIR__ . '/..' . '/symfony/serializer/NameConverter/MetadataAwareNameConverter.php', + 'Symfony\\Component\\Serializer\\NameConverter\\NameConverterInterface' => __DIR__ . '/..' . '/symfony/serializer/NameConverter/NameConverterInterface.php', + 'Symfony\\Component\\Serializer\\NameConverter\\SnakeCaseToCamelCaseNameConverter' => __DIR__ . '/..' . '/symfony/serializer/NameConverter/SnakeCaseToCamelCaseNameConverter.php', + 'Symfony\\Component\\Serializer\\Normalizer\\AbstractNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/AbstractNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\AbstractObjectNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/AbstractObjectNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\ArrayDenormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/ArrayDenormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\BackedEnumNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/BackedEnumNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\ConstraintViolationListNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/ConstraintViolationListNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\CustomNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/CustomNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\DataUriNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/DataUriNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\DateIntervalNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/DateIntervalNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\DateTimeNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/DateTimeNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\DateTimeZoneNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/DateTimeZoneNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\DenormalizableInterface' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/DenormalizableInterface.php', + 'Symfony\\Component\\Serializer\\Normalizer\\DenormalizerAwareInterface' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/DenormalizerAwareInterface.php', + 'Symfony\\Component\\Serializer\\Normalizer\\DenormalizerAwareTrait' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/DenormalizerAwareTrait.php', + 'Symfony\\Component\\Serializer\\Normalizer\\DenormalizerInterface' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/DenormalizerInterface.php', + 'Symfony\\Component\\Serializer\\Normalizer\\FormErrorNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/FormErrorNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\GetSetMethodNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/GetSetMethodNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\JsonSerializableNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/JsonSerializableNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\MimeMessageNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/MimeMessageNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\NormalizableInterface' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/NormalizableInterface.php', + 'Symfony\\Component\\Serializer\\Normalizer\\NormalizerAwareInterface' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/NormalizerAwareInterface.php', + 'Symfony\\Component\\Serializer\\Normalizer\\NormalizerAwareTrait' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/NormalizerAwareTrait.php', + 'Symfony\\Component\\Serializer\\Normalizer\\NormalizerInterface' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/NormalizerInterface.php', + 'Symfony\\Component\\Serializer\\Normalizer\\NumberNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/NumberNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\ObjectNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/ObjectNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\ObjectToPopulateTrait' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/ObjectToPopulateTrait.php', + 'Symfony\\Component\\Serializer\\Normalizer\\ProblemNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/ProblemNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\PropertyNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/PropertyNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\TranslatableNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/TranslatableNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\UidNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/UidNormalizer.php', + 'Symfony\\Component\\Serializer\\Normalizer\\UnwrappingDenormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/UnwrappingDenormalizer.php', + 'Symfony\\Component\\Serializer\\Serializer' => __DIR__ . '/..' . '/symfony/serializer/Serializer.php', + 'Symfony\\Component\\Serializer\\SerializerAwareInterface' => __DIR__ . '/..' . '/symfony/serializer/SerializerAwareInterface.php', + 'Symfony\\Component\\Serializer\\SerializerAwareTrait' => __DIR__ . '/..' . '/symfony/serializer/SerializerAwareTrait.php', + 'Symfony\\Component\\Serializer\\SerializerInterface' => __DIR__ . '/..' . '/symfony/serializer/SerializerInterface.php', 'Symfony\\Component\\String\\AbstractString' => __DIR__ . '/..' . '/symfony/string/AbstractString.php', 'Symfony\\Component\\String\\AbstractUnicodeString' => __DIR__ . '/..' . '/symfony/string/AbstractUnicodeString.php', 'Symfony\\Component\\String\\ByteString' => __DIR__ . '/..' . '/symfony/string/ByteString.php', @@ -4198,17 +4527,52 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 'Symfony\\Component\\Translation\\Util\\XliffUtils' => __DIR__ . '/..' . '/symfony/translation/Util/XliffUtils.php', 'Symfony\\Component\\Translation\\Writer\\TranslationWriter' => __DIR__ . '/..' . '/symfony/translation/Writer/TranslationWriter.php', 'Symfony\\Component\\Translation\\Writer\\TranslationWriterInterface' => __DIR__ . '/..' . '/symfony/translation/Writer/TranslationWriterInterface.php', + 'Symfony\\Component\\TypeInfo\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/type-info/Exception/ExceptionInterface.php', + 'Symfony\\Component\\TypeInfo\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/type-info/Exception/InvalidArgumentException.php', + 'Symfony\\Component\\TypeInfo\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/type-info/Exception/LogicException.php', + 'Symfony\\Component\\TypeInfo\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/type-info/Exception/RuntimeException.php', + 'Symfony\\Component\\TypeInfo\\Exception\\UnsupportedException' => __DIR__ . '/..' . '/symfony/type-info/Exception/UnsupportedException.php', + 'Symfony\\Component\\TypeInfo\\Type' => __DIR__ . '/..' . '/symfony/type-info/Type.php', + 'Symfony\\Component\\TypeInfo\\TypeContext\\TypeContext' => __DIR__ . '/..' . '/symfony/type-info/TypeContext/TypeContext.php', + 'Symfony\\Component\\TypeInfo\\TypeContext\\TypeContextFactory' => __DIR__ . '/..' . '/symfony/type-info/TypeContext/TypeContextFactory.php', + 'Symfony\\Component\\TypeInfo\\TypeFactoryTrait' => __DIR__ . '/..' . '/symfony/type-info/TypeFactoryTrait.php', + 'Symfony\\Component\\TypeInfo\\TypeIdentifier' => __DIR__ . '/..' . '/symfony/type-info/TypeIdentifier.php', + 'Symfony\\Component\\TypeInfo\\TypeResolver\\PhpDocAwareReflectionTypeResolver' => __DIR__ . '/..' . '/symfony/type-info/TypeResolver/PhpDocAwareReflectionTypeResolver.php', + 'Symfony\\Component\\TypeInfo\\TypeResolver\\ReflectionParameterTypeResolver' => __DIR__ . '/..' . '/symfony/type-info/TypeResolver/ReflectionParameterTypeResolver.php', + 'Symfony\\Component\\TypeInfo\\TypeResolver\\ReflectionPropertyTypeResolver' => __DIR__ . '/..' . '/symfony/type-info/TypeResolver/ReflectionPropertyTypeResolver.php', + 'Symfony\\Component\\TypeInfo\\TypeResolver\\ReflectionReturnTypeResolver' => __DIR__ . '/..' . '/symfony/type-info/TypeResolver/ReflectionReturnTypeResolver.php', + 'Symfony\\Component\\TypeInfo\\TypeResolver\\ReflectionTypeResolver' => __DIR__ . '/..' . '/symfony/type-info/TypeResolver/ReflectionTypeResolver.php', + 'Symfony\\Component\\TypeInfo\\TypeResolver\\StringTypeResolver' => __DIR__ . '/..' . '/symfony/type-info/TypeResolver/StringTypeResolver.php', + 'Symfony\\Component\\TypeInfo\\TypeResolver\\TypeResolver' => __DIR__ . '/..' . '/symfony/type-info/TypeResolver/TypeResolver.php', + 'Symfony\\Component\\TypeInfo\\TypeResolver\\TypeResolverInterface' => __DIR__ . '/..' . '/symfony/type-info/TypeResolver/TypeResolverInterface.php', + 'Symfony\\Component\\TypeInfo\\Type\\ArrayShapeType' => __DIR__ . '/..' . '/symfony/type-info/Type/ArrayShapeType.php', + 'Symfony\\Component\\TypeInfo\\Type\\BackedEnumType' => __DIR__ . '/..' . '/symfony/type-info/Type/BackedEnumType.php', + 'Symfony\\Component\\TypeInfo\\Type\\BuiltinType' => __DIR__ . '/..' . '/symfony/type-info/Type/BuiltinType.php', + 'Symfony\\Component\\TypeInfo\\Type\\CollectionType' => __DIR__ . '/..' . '/symfony/type-info/Type/CollectionType.php', + 'Symfony\\Component\\TypeInfo\\Type\\CompositeTypeInterface' => __DIR__ . '/..' . '/symfony/type-info/Type/CompositeTypeInterface.php', + 'Symfony\\Component\\TypeInfo\\Type\\EnumType' => __DIR__ . '/..' . '/symfony/type-info/Type/EnumType.php', + 'Symfony\\Component\\TypeInfo\\Type\\GenericType' => __DIR__ . '/..' . '/symfony/type-info/Type/GenericType.php', + 'Symfony\\Component\\TypeInfo\\Type\\IntersectionType' => __DIR__ . '/..' . '/symfony/type-info/Type/IntersectionType.php', + 'Symfony\\Component\\TypeInfo\\Type\\NullableType' => __DIR__ . '/..' . '/symfony/type-info/Type/NullableType.php', + 'Symfony\\Component\\TypeInfo\\Type\\ObjectType' => __DIR__ . '/..' . '/symfony/type-info/Type/ObjectType.php', + 'Symfony\\Component\\TypeInfo\\Type\\TemplateType' => __DIR__ . '/..' . '/symfony/type-info/Type/TemplateType.php', + 'Symfony\\Component\\TypeInfo\\Type\\UnionType' => __DIR__ . '/..' . '/symfony/type-info/Type/UnionType.php', + 'Symfony\\Component\\TypeInfo\\Type\\WrappingTypeInterface' => __DIR__ . '/..' . '/symfony/type-info/Type/WrappingTypeInterface.php', 'Symfony\\Component\\Uid\\AbstractUid' => __DIR__ . '/..' . '/symfony/uid/AbstractUid.php', 'Symfony\\Component\\Uid\\BinaryUtil' => __DIR__ . '/..' . '/symfony/uid/BinaryUtil.php', 'Symfony\\Component\\Uid\\Command\\GenerateUlidCommand' => __DIR__ . '/..' . '/symfony/uid/Command/GenerateUlidCommand.php', 'Symfony\\Component\\Uid\\Command\\GenerateUuidCommand' => __DIR__ . '/..' . '/symfony/uid/Command/GenerateUuidCommand.php', 'Symfony\\Component\\Uid\\Command\\InspectUlidCommand' => __DIR__ . '/..' . '/symfony/uid/Command/InspectUlidCommand.php', 'Symfony\\Component\\Uid\\Command\\InspectUuidCommand' => __DIR__ . '/..' . '/symfony/uid/Command/InspectUuidCommand.php', + 'Symfony\\Component\\Uid\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/uid/Exception/InvalidArgumentException.php', + 'Symfony\\Component\\Uid\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/uid/Exception/LogicException.php', + 'Symfony\\Component\\Uid\\Factory\\MockUuidFactory' => __DIR__ . '/..' . '/symfony/uid/Factory/MockUuidFactory.php', 'Symfony\\Component\\Uid\\Factory\\NameBasedUuidFactory' => __DIR__ . '/..' . '/symfony/uid/Factory/NameBasedUuidFactory.php', 'Symfony\\Component\\Uid\\Factory\\RandomBasedUuidFactory' => __DIR__ . '/..' . '/symfony/uid/Factory/RandomBasedUuidFactory.php', 'Symfony\\Component\\Uid\\Factory\\TimeBasedUuidFactory' => __DIR__ . '/..' . '/symfony/uid/Factory/TimeBasedUuidFactory.php', 'Symfony\\Component\\Uid\\Factory\\UlidFactory' => __DIR__ . '/..' . '/symfony/uid/Factory/UlidFactory.php', 'Symfony\\Component\\Uid\\Factory\\UuidFactory' => __DIR__ . '/..' . '/symfony/uid/Factory/UuidFactory.php', + 'Symfony\\Component\\Uid\\HashableInterface' => __DIR__ . '/..' . '/symfony/uid/HashableInterface.php', 'Symfony\\Component\\Uid\\MaxUlid' => __DIR__ . '/..' . '/symfony/uid/MaxUlid.php', 'Symfony\\Component\\Uid\\MaxUuid' => __DIR__ . '/..' . '/symfony/uid/MaxUuid.php', 'Symfony\\Component\\Uid\\NilUlid' => __DIR__ . '/..' . '/symfony/uid/NilUlid.php', @@ -4251,26 +4615,33 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 'Symfony\\Polyfill\\Uuid\\Uuid' => __DIR__ . '/..' . '/symfony/polyfill-uuid/Uuid.php', 'System' => __DIR__ . '/..' . '/pear/pear-core-minimal/src/System.php', 'Webauthn\\AttestationStatement\\AndroidKeyAttestationStatementSupport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AndroidKeyAttestationStatementSupport.php', - 'Webauthn\\AttestationStatement\\AndroidSafetyNetAttestationStatementSupport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AndroidSafetyNetAttestationStatementSupport.php', 'Webauthn\\AttestationStatement\\AppleAttestationStatementSupport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AppleAttestationStatementSupport.php', 'Webauthn\\AttestationStatement\\AttestationObject' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationObject.php', 'Webauthn\\AttestationStatement\\AttestationObjectLoader' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationObjectLoader.php', 'Webauthn\\AttestationStatement\\AttestationStatement' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatement.php', 'Webauthn\\AttestationStatement\\AttestationStatementSupport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatementSupport.php', 'Webauthn\\AttestationStatement\\AttestationStatementSupportManager' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatementSupportManager.php', + 'Webauthn\\AttestationStatement\\AttestationStatementSupportManagerAwareInterface' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatementSupportManagerAwareInterface.php', + 'Webauthn\\AttestationStatement\\AttestationStatementSupportManagerAwareTrait' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatementSupportManagerAwareTrait.php', + 'Webauthn\\AttestationStatement\\CompoundAttestationStatementSupport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/CompoundAttestationStatementSupport.php', 'Webauthn\\AttestationStatement\\FidoU2FAttestationStatementSupport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/FidoU2FAttestationStatementSupport.php', 'Webauthn\\AttestationStatement\\NoneAttestationStatementSupport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/NoneAttestationStatementSupport.php', 'Webauthn\\AttestationStatement\\PackedAttestationStatementSupport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/PackedAttestationStatementSupport.php', 'Webauthn\\AttestationStatement\\TPMAttestationStatementSupport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/TPMAttestationStatementSupport.php', 'Webauthn\\AttestedCredentialData' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestedCredentialData.php', + 'Webauthn\\AuthenticationExtensions\\AppIdExcludeInputExtension' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AppIdExcludeInputExtension.php', + 'Webauthn\\AuthenticationExtensions\\AppIdInputExtension' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AppIdInputExtension.php', 'Webauthn\\AuthenticationExtensions\\AuthenticationExtension' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtension.php', + 'Webauthn\\AuthenticationExtensions\\AuthenticationExtensionLoader' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionLoader.php', 'Webauthn\\AuthenticationExtensions\\AuthenticationExtensions' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensions.php', - 'Webauthn\\AuthenticationExtensions\\AuthenticationExtensionsClientInputs' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientInputs.php', - 'Webauthn\\AuthenticationExtensions\\AuthenticationExtensionsClientOutputs' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientOutputs.php', - 'Webauthn\\AuthenticationExtensions\\AuthenticationExtensionsClientOutputsLoader' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientOutputsLoader.php', + 'Webauthn\\AuthenticationExtensions\\CredentialPropertiesInputExtension' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/CredentialPropertiesInputExtension.php', 'Webauthn\\AuthenticationExtensions\\ExtensionOutputChecker' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputChecker.php', 'Webauthn\\AuthenticationExtensions\\ExtensionOutputCheckerHandler' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputCheckerHandler.php', 'Webauthn\\AuthenticationExtensions\\ExtensionOutputError' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputError.php', + 'Webauthn\\AuthenticationExtensions\\LargeBlobInputExtension' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/LargeBlobInputExtension.php', + 'Webauthn\\AuthenticationExtensions\\PseudoRandomFunctionInputExtension' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/PseudoRandomFunctionInputExtension.php', + 'Webauthn\\AuthenticationExtensions\\PseudoRandomFunctionInputExtensionBuilder' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/PseudoRandomFunctionInputExtensionBuilder.php', + 'Webauthn\\AuthenticationExtensions\\UvmInputExtension' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/UvmInputExtension.php', 'Webauthn\\AuthenticatorAssertionResponse' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticatorAssertionResponse.php', 'Webauthn\\AuthenticatorAssertionResponseValidator' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticatorAssertionResponseValidator.php', 'Webauthn\\AuthenticatorAttestationResponse' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticatorAttestationResponse.php', @@ -4284,6 +4655,7 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 'Webauthn\\CeremonyStep\\CeremonyStepManagerFactory' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CeremonyStepManagerFactory.php', 'Webauthn\\CeremonyStep\\CheckAlgorithm' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckAlgorithm.php', 'Webauthn\\CeremonyStep\\CheckAllowedCredentialList' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckAllowedCredentialList.php', + 'Webauthn\\CeremonyStep\\CheckAllowedOrigins' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckAllowedOrigins.php', 'Webauthn\\CeremonyStep\\CheckAttestationFormatIsKnownAndValid' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckAttestationFormatIsKnownAndValid.php', 'Webauthn\\CeremonyStep\\CheckBackupBitsAreConsistent' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckBackupBitsAreConsistent.php', 'Webauthn\\CeremonyStep\\CheckChallenge' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckChallenge.php', @@ -4302,9 +4674,6 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 'Webauthn\\CeremonyStep\\CheckUserWasPresent' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckUserWasPresent.php', 'Webauthn\\CeremonyStep\\HostTopOriginValidator' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/HostTopOriginValidator.php', 'Webauthn\\CeremonyStep\\TopOriginValidator' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/TopOriginValidator.php', - 'Webauthn\\CertificateChainChecker\\CertificateChainChecker' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CertificateChainChecker/CertificateChainChecker.php', - 'Webauthn\\CertificateChainChecker\\PhpCertificateChainChecker' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CertificateChainChecker/PhpCertificateChainChecker.php', - 'Webauthn\\CertificateToolbox' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CertificateToolbox.php', 'Webauthn\\ClientDataCollector\\ClientDataCollector' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/ClientDataCollector/ClientDataCollector.php', 'Webauthn\\ClientDataCollector\\ClientDataCollectorManager' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/ClientDataCollector/ClientDataCollectorManager.php', 'Webauthn\\ClientDataCollector\\WebauthnAuthenticationCollector' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/ClientDataCollector/WebauthnAuthenticationCollector.php', @@ -4312,6 +4681,7 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 'Webauthn\\Counter\\CounterChecker' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Counter/CounterChecker.php', 'Webauthn\\Counter\\ThrowExceptionIfInvalid' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Counter/ThrowExceptionIfInvalid.php', 'Webauthn\\Credential' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Credential.php', + 'Webauthn\\CredentialRecord' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CredentialRecord.php', 'Webauthn\\Denormalizer\\AttestationObjectDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/AttestationObjectDenormalizer.php', 'Webauthn\\Denormalizer\\AttestationStatementDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/AttestationStatementDenormalizer.php', 'Webauthn\\Denormalizer\\AttestedCredentialDataNormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/AttestedCredentialDataNormalizer.php', @@ -4322,14 +4692,20 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 'Webauthn\\Denormalizer\\AuthenticatorDataDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/AuthenticatorDataDenormalizer.php', 'Webauthn\\Denormalizer\\AuthenticatorResponseDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/AuthenticatorResponseDenormalizer.php', 'Webauthn\\Denormalizer\\CollectedClientDataDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/CollectedClientDataDenormalizer.php', + 'Webauthn\\Denormalizer\\CredentialRecordDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/CredentialRecordDenormalizer.php', 'Webauthn\\Denormalizer\\ExtensionDescriptorDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/ExtensionDescriptorDenormalizer.php', 'Webauthn\\Denormalizer\\PublicKeyCredentialDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialDenormalizer.php', 'Webauthn\\Denormalizer\\PublicKeyCredentialDescriptorNormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialDescriptorNormalizer.php', 'Webauthn\\Denormalizer\\PublicKeyCredentialOptionsDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialOptionsDenormalizer.php', 'Webauthn\\Denormalizer\\PublicKeyCredentialParametersDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialParametersDenormalizer.php', + 'Webauthn\\Denormalizer\\PublicKeyCredentialRpEntityDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialRpEntityDenormalizer.php', 'Webauthn\\Denormalizer\\PublicKeyCredentialSourceDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialSourceDenormalizer.php', 'Webauthn\\Denormalizer\\PublicKeyCredentialUserEntityDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialUserEntityDenormalizer.php', + 'Webauthn\\Denormalizer\\SignalAllAcceptedCredentialsDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/SignalAllAcceptedCredentialsDenormalizer.php', + 'Webauthn\\Denormalizer\\SignalCurrentUserDetailsDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/SignalCurrentUserDetailsDenormalizer.php', + 'Webauthn\\Denormalizer\\SignalUnknownCredentialDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/SignalUnknownCredentialDenormalizer.php', 'Webauthn\\Denormalizer\\TrustPathDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/TrustPathDenormalizer.php', + 'Webauthn\\Denormalizer\\UrlNormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/UrlNormalizer.php', 'Webauthn\\Denormalizer\\VerificationMethodANDCombinationsDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/VerificationMethodANDCombinationsDenormalizer.php', 'Webauthn\\Denormalizer\\WebauthnSerializerFactory' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/WebauthnSerializerFactory.php', 'Webauthn\\Event\\AttestationObjectLoaded' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/AttestationObjectLoaded.php', @@ -4338,6 +4714,8 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 'Webauthn\\Event\\AuthenticatorAssertionResponseValidationSucceededEvent' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/AuthenticatorAssertionResponseValidationSucceededEvent.php', 'Webauthn\\Event\\AuthenticatorAttestationResponseValidationFailedEvent' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/AuthenticatorAttestationResponseValidationFailedEvent.php', 'Webauthn\\Event\\AuthenticatorAttestationResponseValidationSucceededEvent' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/AuthenticatorAttestationResponseValidationSucceededEvent.php', + 'Webauthn\\Event\\BackupEligibilityChangedEvent' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/BackupEligibilityChangedEvent.php', + 'Webauthn\\Event\\BackupStatusChangedEvent' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/BackupStatusChangedEvent.php', 'Webauthn\\Event\\BeforeCertificateChainValidation' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/BeforeCertificateChainValidation.php', 'Webauthn\\Event\\CanDispatchEvents' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/CanDispatchEvents.php', 'Webauthn\\Event\\CertificateChainValidationFailed' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/CertificateChainValidationFailed.php', @@ -4372,25 +4750,6 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 'Webauthn\\MetadataService\\CertificateChain\\CertificateChainValidator' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/CertificateChain/CertificateChainValidator.php', 'Webauthn\\MetadataService\\CertificateChain\\CertificateToolbox' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/CertificateChain/CertificateToolbox.php', 'Webauthn\\MetadataService\\CertificateChain\\PhpCertificateChainValidator' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/CertificateChain/PhpCertificateChainValidator.php', - 'Webauthn\\MetadataService\\Denormalizer\\ExtensionDescriptorDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Denormalizer/ExtensionDescriptorDenormalizer.php', - 'Webauthn\\MetadataService\\Denormalizer\\MetadataStatementSerializerFactory' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Denormalizer/MetadataStatementSerializerFactory.php', - 'Webauthn\\MetadataService\\Event\\BeforeCertificateChainValidation' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Event/BeforeCertificateChainValidation.php', - 'Webauthn\\MetadataService\\Event\\CanDispatchEvents' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Event/CanDispatchEvents.php', - 'Webauthn\\MetadataService\\Event\\CertificateChainValidationFailed' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Event/CertificateChainValidationFailed.php', - 'Webauthn\\MetadataService\\Event\\CertificateChainValidationSucceeded' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Event/CertificateChainValidationSucceeded.php', - 'Webauthn\\MetadataService\\Event\\MetadataStatementFound' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Event/MetadataStatementFound.php', - 'Webauthn\\MetadataService\\Event\\NullEventDispatcher' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Event/NullEventDispatcher.php', - 'Webauthn\\MetadataService\\Event\\WebauthnEvent' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Event/WebauthnEvent.php', - 'Webauthn\\MetadataService\\Exception\\CertificateChainException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Exception/CertificateChainException.php', - 'Webauthn\\MetadataService\\Exception\\CertificateException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Exception/CertificateException.php', - 'Webauthn\\MetadataService\\Exception\\CertificateRevocationListException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Exception/CertificateRevocationListException.php', - 'Webauthn\\MetadataService\\Exception\\ExpiredCertificateException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Exception/ExpiredCertificateException.php', - 'Webauthn\\MetadataService\\Exception\\InvalidCertificateException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Exception/InvalidCertificateException.php', - 'Webauthn\\MetadataService\\Exception\\MetadataServiceException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Exception/MetadataServiceException.php', - 'Webauthn\\MetadataService\\Exception\\MetadataStatementException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Exception/MetadataStatementException.php', - 'Webauthn\\MetadataService\\Exception\\MetadataStatementLoadingException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Exception/MetadataStatementLoadingException.php', - 'Webauthn\\MetadataService\\Exception\\MissingMetadataStatementException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Exception/MissingMetadataStatementException.php', - 'Webauthn\\MetadataService\\Exception\\RevokedCertificateException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Exception/RevokedCertificateException.php', 'Webauthn\\MetadataService\\MetadataStatementRepository' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/MetadataStatementRepository.php', 'Webauthn\\MetadataService\\Psr18HttpClient' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Psr18HttpClient.php', 'Webauthn\\MetadataService\\Service\\ChainedMetadataServices' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Service/ChainedMetadataServices.php', @@ -4403,7 +4762,6 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 'Webauthn\\MetadataService\\Service\\MetadataBLOBPayload' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Service/MetadataBLOBPayload.php', 'Webauthn\\MetadataService\\Service\\MetadataBLOBPayloadEntry' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Service/MetadataBLOBPayloadEntry.php', 'Webauthn\\MetadataService\\Service\\MetadataService' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Service/MetadataService.php', - 'Webauthn\\MetadataService\\Service\\StringMetadataService' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Service/StringMetadataService.php', 'Webauthn\\MetadataService\\Statement\\AbstractDescriptor' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/AbstractDescriptor.php', 'Webauthn\\MetadataService\\Statement\\AlternativeDescriptions' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/AlternativeDescriptions.php', 'Webauthn\\MetadataService\\Statement\\AuthenticatorGetInfo' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/AuthenticatorGetInfo.php', @@ -4412,7 +4770,6 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 'Webauthn\\MetadataService\\Statement\\BiometricStatusReport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/BiometricStatusReport.php', 'Webauthn\\MetadataService\\Statement\\CodeAccuracyDescriptor' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/CodeAccuracyDescriptor.php', 'Webauthn\\MetadataService\\Statement\\DisplayPNGCharacteristicsDescriptor' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/DisplayPNGCharacteristicsDescriptor.php', - 'Webauthn\\MetadataService\\Statement\\EcdaaTrustAnchor' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/EcdaaTrustAnchor.php', 'Webauthn\\MetadataService\\Statement\\ExtensionDescriptor' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/ExtensionDescriptor.php', 'Webauthn\\MetadataService\\Statement\\MetadataStatement' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/MetadataStatement.php', 'Webauthn\\MetadataService\\Statement\\PatternAccuracyDescriptor' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/PatternAccuracyDescriptor.php', @@ -4423,35 +4780,36 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 'Webauthn\\MetadataService\\Statement\\VerificationMethodDescriptor' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/VerificationMethodDescriptor.php', 'Webauthn\\MetadataService\\Statement\\Version' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/Version.php', 'Webauthn\\MetadataService\\StatusReportRepository' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/StatusReportRepository.php', - 'Webauthn\\MetadataService\\ValueFilter' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/ValueFilter.php', + 'Webauthn\\PasskeyEndpointsResponse' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PasskeyEndpointsResponse.php', 'Webauthn\\PublicKeyCredential' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredential.php', 'Webauthn\\PublicKeyCredentialCreationOptions' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialCreationOptions.php', 'Webauthn\\PublicKeyCredentialDescriptor' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialDescriptor.php', - 'Webauthn\\PublicKeyCredentialDescriptorCollection' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialDescriptorCollection.php', 'Webauthn\\PublicKeyCredentialEntity' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialEntity.php', - 'Webauthn\\PublicKeyCredentialLoader' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialLoader.php', 'Webauthn\\PublicKeyCredentialOptions' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialOptions.php', 'Webauthn\\PublicKeyCredentialParameters' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialParameters.php', 'Webauthn\\PublicKeyCredentialRequestOptions' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialRequestOptions.php', 'Webauthn\\PublicKeyCredentialRpEntity' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialRpEntity.php', 'Webauthn\\PublicKeyCredentialSource' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialSource.php', - 'Webauthn\\PublicKeyCredentialSourceRepository' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialSourceRepository.php', 'Webauthn\\PublicKeyCredentialUserEntity' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialUserEntity.php', + 'Webauthn\\Signal\\AllAcceptedCredentials' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Signal/AllAcceptedCredentials.php', + 'Webauthn\\Signal\\CurrentUserDetails' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Signal/CurrentUserDetails.php', + 'Webauthn\\Signal\\Signal' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Signal/Signal.php', + 'Webauthn\\Signal\\UnknownCredential' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Signal/UnknownCredential.php', 'Webauthn\\SimpleFakeCredentialGenerator' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/SimpleFakeCredentialGenerator.php', 'Webauthn\\StringStream' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/StringStream.php', - 'Webauthn\\TokenBinding\\IgnoreTokenBindingHandler' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TokenBinding/IgnoreTokenBindingHandler.php', - 'Webauthn\\TokenBinding\\SecTokenBindingHandler' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TokenBinding/SecTokenBindingHandler.php', - 'Webauthn\\TokenBinding\\TokenBinding' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TokenBinding/TokenBinding.php', - 'Webauthn\\TokenBinding\\TokenBindingHandler' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TokenBinding/TokenBindingHandler.php', - 'Webauthn\\TokenBinding\\TokenBindingNotSupportedHandler' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TokenBinding/TokenBindingNotSupportedHandler.php', 'Webauthn\\TrustPath\\CertificateTrustPath' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TrustPath/CertificateTrustPath.php', - 'Webauthn\\TrustPath\\EcdaaKeyIdTrustPath' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TrustPath/EcdaaKeyIdTrustPath.php', 'Webauthn\\TrustPath\\EmptyTrustPath' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TrustPath/EmptyTrustPath.php', 'Webauthn\\TrustPath\\TrustPath' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TrustPath/TrustPath.php', - 'Webauthn\\TrustPath\\TrustPathLoader' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TrustPath/TrustPathLoader.php', 'Webauthn\\U2FPublicKey' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/U2FPublicKey.php', + 'Webauthn\\Url' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Url.php', 'Webauthn\\Util\\Base64' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Util/Base64.php', 'Webauthn\\Util\\CoseSignatureFixer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Util/CoseSignatureFixer.php', + 'Webauthn\\Util\\CredentialRecordConverter' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Util/CredentialRecordConverter.php', + 'Webmozart\\Assert\\Assert' => __DIR__ . '/..' . '/webmozart/assert/src/Assert.php', + 'Webmozart\\Assert\\HasAssert' => __DIR__ . '/..' . '/webmozart/assert/src/HasAssert.php', + 'Webmozart\\Assert\\InvalidArgumentException' => __DIR__ . '/..' . '/webmozart/assert/src/InvalidArgumentException.php', + 'Webmozart\\Assert\\Mixin' => __DIR__ . '/..' . '/webmozart/assert/src/Mixin.php', + 'Webmozart\\Assert\\PsalmPlugin' => __DIR__ . '/..' . '/webmozart/assert/src/PsalmPlugin.php', 'ZipStreamer\\COMPR' => __DIR__ . '/..' . '/deepdiver/zipstreamer/src/COMPR.php', 'ZipStreamer\\Count64' => __DIR__ . '/..' . '/deepdiver/zipstreamer/src/Count64.php', 'ZipStreamer\\Lib\\Count64Base' => __DIR__ . '/..' . '/deepdiver/zipstreamer/src/Lib/Count64Base.php', @@ -5001,6 +5359,166 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 'libphonenumber\\data\\ShortNumberMetadata_ZW' => __DIR__ . '/..' . '/giggsey/libphonenumber-for-php-lite/src/data/ShortNumberMetadata_ZW.php', 'ownCloud\\TarStreamer\\TarHeader' => __DIR__ . '/..' . '/deepdiver1975/tarstreamer/src/TarHeader.php', 'ownCloud\\TarStreamer\\TarStreamer' => __DIR__ . '/..' . '/deepdiver1975/tarstreamer/src/TarStreamer.php', + 'phpDocumentor\\Reflection\\DocBlock' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock.php', + 'phpDocumentor\\Reflection\\DocBlockFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlockFactory.php', + 'phpDocumentor\\Reflection\\DocBlockFactoryInterface' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlockFactoryInterface.php', + 'phpDocumentor\\Reflection\\DocBlock\\Description' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Description.php', + 'phpDocumentor\\Reflection\\DocBlock\\DescriptionFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/DescriptionFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\ExampleFinder' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/ExampleFinder.php', + 'phpDocumentor\\Reflection\\DocBlock\\Serializer' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Serializer.php', + 'phpDocumentor\\Reflection\\DocBlock\\StandardTagFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/StandardTagFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tag' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tag.php', + 'phpDocumentor\\Reflection\\DocBlock\\TagFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/TagFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Author' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Author.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\BaseTag' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/BaseTag.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Covers' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Covers.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Deprecated' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Deprecated.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Example' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Example.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Extends_' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Extends_.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\AbstractPHPStanFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/AbstractPHPStanFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\ExtendsFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ExtendsFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\Factory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/Factory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\ImplementsFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ImplementsFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\MethodFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/MethodFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\MethodParameterFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/MethodParameterFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\MixinFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/MixinFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\PHPStanFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PHPStanFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\ParamFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ParamFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\PropertyFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\PropertyReadFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyReadFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\PropertyWriteFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyWriteFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\ReturnFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ReturnFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\TemplateCovariantFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/TemplateCovariantFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\TemplateFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/TemplateFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\ThrowsFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ThrowsFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\VarFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/VarFactory.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Formatter' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Formatter\\AlignFormatter' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/AlignFormatter.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Formatter\\PassthroughFormatter' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/PassthroughFormatter.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Generic' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Generic.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Implements_' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Implements_.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\InvalidTag' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/InvalidTag.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Link' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Link.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Method' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Method.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\MethodParameter' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/MethodParameter.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Mixin' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Mixin.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Param' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Param.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Property' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Property.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\PropertyRead' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyRead.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\PropertyWrite' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyWrite.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Reference\\Fqsen' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Fqsen.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Reference\\Reference' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Reference.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Reference\\Url' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Url.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Return_' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Return_.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\See' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/See.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Since' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Since.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Source' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Source.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\TagWithType' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TagWithType.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Template' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Template.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\TemplateCovariant' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateCovariant.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\TemplateExtends' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateExtends.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\TemplateImplements' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateImplements.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Throws' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Throws.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Uses' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Uses.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Var_' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Var_.php', + 'phpDocumentor\\Reflection\\DocBlock\\Tags\\Version' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Version.php', + 'phpDocumentor\\Reflection\\Element' => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src/Element.php', + 'phpDocumentor\\Reflection\\Exception\\CannotCreateTag' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/Exception/CannotCreateTag.php', + 'phpDocumentor\\Reflection\\Exception\\ParserException' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/Exception/ParserException.php', + 'phpDocumentor\\Reflection\\Exception\\PcreException' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/Exception/PcreException.php', + 'phpDocumentor\\Reflection\\Exception\\ReflectionDocblockException' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/Exception/ReflectionDocblockException.php', + 'phpDocumentor\\Reflection\\File' => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src/File.php', + 'phpDocumentor\\Reflection\\Fqsen' => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src/Fqsen.php', + 'phpDocumentor\\Reflection\\FqsenResolver' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/FqsenResolver.php', + 'phpDocumentor\\Reflection\\Location' => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src/Location.php', + 'phpDocumentor\\Reflection\\Project' => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src/Project.php', + 'phpDocumentor\\Reflection\\ProjectFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src/ProjectFactory.php', + 'phpDocumentor\\Reflection\\PseudoType' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoType.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\ArrayKey' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/ArrayKey.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\ArrayShape' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/ArrayShape.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\ArrayShapeItem' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/ArrayShapeItem.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\CallableArray' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/CallableArray.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\CallableString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/CallableString.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\ClassString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/ClassString.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\ClosedResource' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/ClosedResource.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\Conditional' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/Conditional.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\ConditionalForParameter' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/ConditionalForParameter.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\ConstExpression' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/ConstExpression.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\EnumString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/EnumString.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\False_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/False_.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\FloatValue' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/FloatValue.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\Generic' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/Generic.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\HtmlEscapedString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/HtmlEscapedString.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\IntMask' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/IntMask.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\IntMaskOf' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/IntMaskOf.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\IntegerRange' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/IntegerRange.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\IntegerValue' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/IntegerValue.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\InterfaceString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/InterfaceString.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\KeyOf' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/KeyOf.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\ListShape' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/ListShape.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\ListShapeItem' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/ListShapeItem.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\List_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/List_.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\LiteralString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/LiteralString.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\LowercaseString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/LowercaseString.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\NegativeInteger' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/NegativeInteger.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\NeverReturn' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/NeverReturn.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\NeverReturns' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/NeverReturns.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\NoReturn' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/NoReturn.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\NonEmptyArray' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyArray.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\NonEmptyList' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyList.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\NonEmptyLowercaseString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyLowercaseString.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\NonEmptyString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyString.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\NonFalsyString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/NonFalsyString.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\NonNegativeInteger' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/NonNegativeInteger.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\NonPositiveInteger' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/NonPositiveInteger.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\NonZeroInteger' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/NonZeroInteger.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\NumericString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/NumericString.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\Numeric_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/Numeric_.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\ObjectShape' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/ObjectShape.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\ObjectShapeItem' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/ObjectShapeItem.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\OffsetAccess' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/OffsetAccess.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\OpenResource' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/OpenResource.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\PositiveInteger' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/PositiveInteger.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\PrivatePropertiesOf' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/PrivatePropertiesOf.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\PropertiesOf' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/PropertiesOf.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\ProtectedPropertiesOf' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/ProtectedPropertiesOf.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\PublicPropertiesOf' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/PublicPropertiesOf.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\Scalar' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/Scalar.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\ShapeItem' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/ShapeItem.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\StringValue' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/StringValue.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\TraitString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/TraitString.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\True_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/True_.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\TruthyString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/TruthyString.php', + 'phpDocumentor\\Reflection\\PseudoTypes\\ValueOf' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/ValueOf.php', + 'phpDocumentor\\Reflection\\Type' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Type.php', + 'phpDocumentor\\Reflection\\TypeResolver' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/TypeResolver.php', + 'phpDocumentor\\Reflection\\Types\\AbstractList' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/AbstractList.php', + 'phpDocumentor\\Reflection\\Types\\AggregatedType' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/AggregatedType.php', + 'phpDocumentor\\Reflection\\Types\\Array_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Array_.php', + 'phpDocumentor\\Reflection\\Types\\Boolean' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Boolean.php', + 'phpDocumentor\\Reflection\\Types\\CallableParameter' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/CallableParameter.php', + 'phpDocumentor\\Reflection\\Types\\Callable_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Callable_.php', + 'phpDocumentor\\Reflection\\Types\\Compound' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Compound.php', + 'phpDocumentor\\Reflection\\Types\\Context' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Context.php', + 'phpDocumentor\\Reflection\\Types\\ContextFactory' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/ContextFactory.php', + 'phpDocumentor\\Reflection\\Types\\Expression' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Expression.php', + 'phpDocumentor\\Reflection\\Types\\Float_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Float_.php', + 'phpDocumentor\\Reflection\\Types\\Integer' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Integer.php', + 'phpDocumentor\\Reflection\\Types\\Intersection' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Intersection.php', + 'phpDocumentor\\Reflection\\Types\\Iterable_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Iterable_.php', + 'phpDocumentor\\Reflection\\Types\\Mixed_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Mixed_.php', + 'phpDocumentor\\Reflection\\Types\\Never_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Never_.php', + 'phpDocumentor\\Reflection\\Types\\Null_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Null_.php', + 'phpDocumentor\\Reflection\\Types\\Nullable' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Nullable.php', + 'phpDocumentor\\Reflection\\Types\\Object_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Object_.php', + 'phpDocumentor\\Reflection\\Types\\Parent_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Parent_.php', + 'phpDocumentor\\Reflection\\Types\\Resource_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Resource_.php', + 'phpDocumentor\\Reflection\\Types\\Self_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Self_.php', + 'phpDocumentor\\Reflection\\Types\\Static_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Static_.php', + 'phpDocumentor\\Reflection\\Types\\String_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/String_.php', + 'phpDocumentor\\Reflection\\Types\\This' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/This.php', + 'phpDocumentor\\Reflection\\Types\\Void_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Void_.php', + 'phpDocumentor\\Reflection\\Utils' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/Utils.php', 'phpseclib3\\Common\\Functions\\Strings' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Common/Functions/Strings.php', 'phpseclib3\\Crypt\\AES' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/AES.php', 'phpseclib3\\Crypt\\Blowfish' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/Blowfish.php', diff --git a/composer/installed.json b/composer/installed.json index 00439f648..4ec1cd4bb 100644 --- a/composer/installed.json +++ b/composer/installed.json @@ -196,28 +196,27 @@ }, { "name": "brick/math", - "version": "0.12.1", - "version_normalized": "0.12.1.0", + "version": "0.18.0", + "version_normalized": "0.18.0.0", "source": { "type": "git", "url": "https://github.com/brick/math.git", - "reference": "f510c0a40911935b77b86859eb5223d58d660df1" + "reference": "82944324d1c1bdb2c2618e89978d4e2ad78d69ad" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brick/math/zipball/f510c0a40911935b77b86859eb5223d58d660df1", - "reference": "f510c0a40911935b77b86859eb5223d58d660df1", + "url": "https://api.github.com/repos/brick/math/zipball/82944324d1c1bdb2c2618e89978d4e2ad78d69ad", + "reference": "82944324d1c1bdb2c2618e89978d4e2ad78d69ad", "shasum": "" }, "require": { - "php": "^8.1" + "php": "^8.2" }, "require-dev": { - "php-coveralls/php-coveralls": "^2.2", - "phpunit/phpunit": "^10.1", - "vimeo/psalm": "5.16.0" + "phpstan/phpstan": "2.1.22", + "phpunit/phpunit": "^11.5" }, - "time": "2023-11-29T23:19:16+00:00", + "time": "2026-06-14T18:21:03+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -247,7 +246,7 @@ ], "support": { "issues": "https://github.com/brick/math/issues", - "source": "https://github.com/brick/math/tree/0.12.1" + "source": "https://github.com/brick/math/tree/0.18.0" }, "funding": [ { @@ -1908,73 +1907,6 @@ }, "install-path": "../laravel/serializable-closure" }, - { - "name": "lcobucci/clock", - "version": "3.5.0", - "version_normalized": "3.5.0.0", - "source": { - "type": "git", - "url": "https://github.com/lcobucci/clock.git", - "reference": "a3139d9e97d47826f27e6a17bb63f13621f86058" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/lcobucci/clock/zipball/a3139d9e97d47826f27e6a17bb63f13621f86058", - "reference": "a3139d9e97d47826f27e6a17bb63f13621f86058", - "shasum": "" - }, - "require": { - "php": "~8.3.0 || ~8.4.0 || ~8.5.0", - "psr/clock": "^1.0" - }, - "provide": { - "psr/clock-implementation": "1.0" - }, - "require-dev": { - "infection/infection": "^0.31", - "lcobucci/coding-standard": "^11.2.0", - "phpstan/extension-installer": "^1.3.1", - "phpstan/phpstan": "^2.0.0", - "phpstan/phpstan-deprecation-rules": "^2.0.0", - "phpstan/phpstan-phpunit": "^2.0.0", - "phpstan/phpstan-strict-rules": "^2.0.0", - "phpunit/phpunit": "^12.0.0" - }, - "time": "2025-10-27T09:03:17+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Lcobucci\\Clock\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Luís Cobucci", - "email": "lcobucci@gmail.com" - } - ], - "description": "Yet another clock abstraction", - "support": { - "issues": "https://github.com/lcobucci/clock/issues", - "source": "https://github.com/lcobucci/clock/tree/3.5.0" - }, - "funding": [ - { - "url": "https://github.com/lcobucci", - "type": "github" - }, - { - "url": "https://www.patreon.com/lcobucci", - "type": "patreon" - } - ], - "install-path": "../lcobucci/clock" - }, { "name": "marc-mabe/php-enum", "version": "v4.7.1", @@ -3058,6 +2990,191 @@ }, "install-path": "../php-opencloud/openstack" }, + { + "name": "phpdocumentor/reflection-common", + "version": "2.2.0", + "version_normalized": "2.2.0.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "time": "2020-06-27T09:03:43+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-2.x": "2.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" + }, + "install-path": "../phpdocumentor/reflection-common" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "6.0.3", + "version_normalized": "6.0.3.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "7bae67520aa9f5ecc506d646810bd40d9da54582" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/7bae67520aa9f5ecc506d646810bd40d9da54582", + "reference": "7bae67520aa9f5ecc506d646810bd40d9da54582", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.1", + "ext-filter": "*", + "php": "^7.4 || ^8.0", + "phpdocumentor/reflection-common": "^2.2", + "phpdocumentor/type-resolver": "^2.0", + "phpstan/phpdoc-parser": "^2.0", + "webmozart/assert": "^1.9.1 || ^2" + }, + "require-dev": { + "mockery/mockery": "~1.3.5 || ~1.6.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-webmozart-assert": "^1.2", + "phpunit/phpunit": "^9.5", + "psalm/phar": "^5.26", + "shipmonk/dead-code-detector": "^0.5.1" + }, + "time": "2026-03-18T20:49:53+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/6.0.3" + }, + "install-path": "../phpdocumentor/reflection-docblock" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "2.0.0", + "version_normalized": "2.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "327a05bbee54120d4786a0dc67aad30226ad4cf9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/327a05bbee54120d4786a0dc67aad30226ad4cf9", + "reference": "327a05bbee54120d4786a0dc67aad30226ad4cf9", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.0", + "php": "^7.4 || ^8.0", + "phpdocumentor/reflection-common": "^2.0", + "phpstan/phpdoc-parser": "^2.0" + }, + "require-dev": { + "ext-tokenizer": "*", + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^9.5", + "psalm/phar": "^4" + }, + "time": "2026-01-06T21:53:42+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-1.x": "1.x-dev", + "dev-2.x": "2.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "support": { + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/2.0.0" + }, + "install-path": "../phpdocumentor/type-resolver" + }, { "name": "phpseclib/phpseclib", "version": "3.0.55", @@ -3171,6 +3288,56 @@ ], "install-path": "../phpseclib/phpseclib" }, + { + "name": "phpstan/phpdoc-parser", + "version": "2.3.3", + "version_normalized": "2.3.3.0", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "fb19eedd2bb67ff8cf7a5502ad329e701d6398a3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/fb19eedd2bb67ff8cf7a5502ad329e701d6398a3", + "reference": "fb19eedd2bb67ff8cf7a5502ad329e701d6398a3", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "doctrine/annotations": "^2.0", + "nikic/php-parser": "^5.3.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.6", + "symfony/process": "^5.2" + }, + "time": "2026-07-08T07:01:06+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPDoc parser with support for nullable, intersection and generic types", + "support": { + "issues": "https://github.com/phpstan/phpdoc-parser/issues", + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.3" + }, + "install-path": "../phpstan/phpdoc-parser" + }, { "name": "pimple/pimple", "version": "v3.6.0", @@ -4343,47 +4510,35 @@ }, { "name": "spomky-labs/cbor-php", - "version": "3.0.4", - "version_normalized": "3.0.4.0", + "version": "3.3.0", + "version_normalized": "3.3.0.0", "source": { "type": "git", "url": "https://github.com/Spomky-Labs/cbor-php.git", - "reference": "658ed12a85a6b31fa312b89cd92f3a4ce6df4c6b" + "reference": "013d13da69cf28b1ae501887daceccc850ca1c76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Spomky-Labs/cbor-php/zipball/658ed12a85a6b31fa312b89cd92f3a4ce6df4c6b", - "reference": "658ed12a85a6b31fa312b89cd92f3a4ce6df4c6b", + "url": "https://api.github.com/repos/Spomky-Labs/cbor-php/zipball/013d13da69cf28b1ae501887daceccc850ca1c76", + "reference": "013d13da69cf28b1ae501887daceccc850ca1c76", "shasum": "" }, "require": { - "brick/math": "^0.9|^0.10|^0.11|^0.12", + "brick/math": "^0.9|^0.10|^0.11|^0.12|^0.13|^0.14|^0.15|^0.16|^0.17|^0.18", "ext-mbstring": "*", "php": ">=8.0" }, "require-dev": { - "ekino/phpstan-banned-code": "^1.0", "ext-json": "*", - "infection/infection": "^0.27", - "php-parallel-lint/php-parallel-lint": "^1.3", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.0", - "phpstan/phpstan-beberlei-assert": "^1.0", - "phpstan/phpstan-deprecation-rules": "^1.0", - "phpstan/phpstan-phpunit": "^1.0", - "phpstan/phpstan-strict-rules": "^1.0", - "phpunit/phpunit": "^10.1", - "qossmic/deptrac-shim": "^1.0", - "rector/rector": "^0.19", "roave/security-advisories": "dev-latest", - "symfony/var-dumper": "^6.0|^7.0", - "symplify/easy-coding-standard": "^12.0" + "symfony/error-handler": "^6.4|^7.1|^8.0", + "symfony/var-dumper": "^6.4|^7.1|^8.0" }, "suggest": { "ext-bcmath": "GMP or BCMath extensions will drastically improve the library performance. BCMath extension needed to handle the Big Float and Decimal Fraction Tags", "ext-gmp": "GMP or BCMath extensions will drastically improve the library performance" }, - "time": "2024-01-29T20:33:48+00:00", + "time": "2026-07-15T18:56:27+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -4413,7 +4568,7 @@ ], "support": { "issues": "https://github.com/Spomky-Labs/cbor-php/issues", - "source": "https://github.com/Spomky-Labs/cbor-php/tree/3.0.4" + "source": "https://github.com/Spomky-Labs/cbor-php/tree/3.3.0" }, "funding": [ { @@ -4429,50 +4584,48 @@ }, { "name": "spomky-labs/pki-framework", - "version": "1.2.1", - "version_normalized": "1.2.1.0", + "version": "1.6.0", + "version_normalized": "1.6.0.0", "source": { "type": "git", "url": "https://github.com/Spomky-Labs/pki-framework.git", - "reference": "0b10c8b53366729417d6226ae89a665f9e2d61b6" + "reference": "80778a25426288acd2e3a7cde2def41a3d59cddf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Spomky-Labs/pki-framework/zipball/0b10c8b53366729417d6226ae89a665f9e2d61b6", - "reference": "0b10c8b53366729417d6226ae89a665f9e2d61b6", + "url": "https://api.github.com/repos/Spomky-Labs/pki-framework/zipball/80778a25426288acd2e3a7cde2def41a3d59cddf", + "reference": "80778a25426288acd2e3a7cde2def41a3d59cddf", "shasum": "" }, "require": { - "brick/math": "^0.10|^0.11|^0.12", + "brick/math": "^0.10|^0.11|^0.12|^0.13|^0.14|^0.15|^0.16|^0.17|^0.18|^0.19", "ext-mbstring": "*", "php": ">=8.1" }, "require-dev": { - "ekino/phpstan-banned-code": "^1.0", + "ekino/phpstan-banned-code": "^1.0|^2.0|^3.0", "ext-gmp": "*", "ext-openssl": "*", - "infection/infection": "^0.28", + "infection/infection": "^0.28|^0.29|^0.31", "php-parallel-lint/php-parallel-lint": "^1.3", - "phpstan/extension-installer": "^1.3", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-beberlei-assert": "^1.0", - "phpstan/phpstan-deprecation-rules": "^1.0", - "phpstan/phpstan-phpunit": "^1.1", - "phpstan/phpstan-strict-rules": "^1.3", - "phpunit/phpunit": "^10.1|^11.0", - "rector/rector": "^1.0", + "phpstan/extension-installer": "^1.3|^2.0", + "phpstan/phpstan": "^1.8|^2.0", + "phpstan/phpstan-deprecation-rules": "^1.0|^2.0", + "phpstan/phpstan-phpunit": "^1.1|^2.0", + "phpstan/phpstan-strict-rules": "^1.3|^2.0", + "phpunit/phpunit": "^10.1|^11.0|^12.0", + "rector/rector": "^1.0|^2.0", "roave/security-advisories": "dev-latest", - "symfony/phpunit-bridge": "^6.4|^7.0", - "symfony/string": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0", - "symplify/easy-coding-standard": "^12.0" + "symfony/string": "^6.4|^7.0|^8.0", + "symfony/var-dumper": "^6.4|^7.0|^8.0", + "symplify/easy-coding-standard": "^12.0 || ^13.0" }, "suggest": { "ext-bcmath": "For better performance (or GMP)", "ext-gmp": "For better performance (or BCMath)", "ext-openssl": "For OpenSSL based cyphering" }, - "time": "2024-03-30T18:03:49+00:00", + "time": "2026-08-06T16:21:11+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -4527,7 +4680,7 @@ ], "support": { "issues": "https://github.com/Spomky-Labs/pki-framework/issues", - "source": "https://github.com/Spomky-Labs/pki-framework/tree/1.2.1" + "source": "https://github.com/Spomky-Labs/pki-framework/tree/1.6.0" }, "funding": [ { @@ -4594,6 +4747,87 @@ }, "install-path": "../stecman/symfony-console-completion" }, + { + "name": "symfony/clock", + "version": "v7.4.8", + "version_normalized": "7.4.8.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/clock.git", + "reference": "674fa3b98e21531dd040e613479f5f6fa8f32111" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/clock/zipball/674fa3b98e21531dd040e613479f5f6fa8f32111", + "reference": "674fa3b98e21531dd040e613479f5f6fa8f32111", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/clock": "^1.0", + "symfony/polyfill-php83": "^1.28" + }, + "provide": { + "psr/clock-implementation": "1.0" + }, + "time": "2026-03-24T13:12:05+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "files": [ + "Resources/now.php" + ], + "psr-4": { + "Symfony\\Component\\Clock\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Decouples applications from the system clock", + "homepage": "https://symfony.com", + "keywords": [ + "clock", + "psr20", + "time" + ], + "support": { + "source": "https://github.com/symfony/clock/tree/v7.4.8" + }, + "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/clock" + }, { "name": "symfony/console", "version": "v7.4.15", @@ -5938,21 +6172,21 @@ }, { "name": "symfony/polyfill-uuid", - "version": "v1.29.0", - "version_normalized": "1.29.0.0", + "version": "v1.37.0", + "version_normalized": "1.37.0.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-uuid.git", - "reference": "3abdd21b0ceaa3000ee950097bc3cf9efc137853" + "reference": "26dfec253c4cf3e51b541b52ddf7e42cb0908e94" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/3abdd21b0ceaa3000ee950097bc3cf9efc137853", - "reference": "3abdd21b0ceaa3000ee950097bc3cf9efc137853", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/26dfec253c4cf3e51b541b52ddf7e42cb0908e94", + "reference": "26dfec253c4cf3e51b541b52ddf7e42cb0908e94", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-uuid": "*" @@ -5960,7 +6194,7 @@ "suggest": { "ext-uuid": "For best performance" }, - "time": "2024-01-29T20:11:03+00:00", + "time": "2026-04-10T16:19:22+00:00", "type": "library", "extra": { "thanks": { @@ -6000,7 +6234,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/polyfill-uuid/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.37.0" }, "funding": [ { @@ -6011,6 +6245,10 @@ "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" @@ -6086,6 +6324,183 @@ ], "install-path": "../symfony/process" }, + { + "name": "symfony/property-access", + "version": "v7.4.8", + "version_normalized": "7.4.8.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/property-access.git", + "reference": "b7dad9dae8b8a47ef7ecc76c8569e7d8c7d90cfc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/property-access/zipball/b7dad9dae8b8a47ef7ecc76c8569e7d8c7d90cfc", + "reference": "b7dad9dae8b8a47ef7ecc76c8569e7d8c7d90cfc", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/property-info": "^6.4.32|~7.3.10|^7.4.4|^8.0.4" + }, + "require-dev": { + "symfony/cache": "^6.4|^7.0|^8.0", + "symfony/var-exporter": "^6.4.1|^7.0.1|^8.0" + }, + "time": "2026-03-24T13:12:05+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\PropertyAccess\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides functions to read and write from/to an object or array using a simple string notation", + "homepage": "https://symfony.com", + "keywords": [ + "access", + "array", + "extraction", + "index", + "injection", + "object", + "property", + "property-path", + "reflection" + ], + "support": { + "source": "https://github.com/symfony/property-access/tree/v7.4.8" + }, + "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/property-access" + }, + { + "name": "symfony/property-info", + "version": "v7.4.15", + "version_normalized": "7.4.15.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/property-info.git", + "reference": "fce3f4d9cfeb4ddc674c357b5a4c3a23ccf408ad" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/property-info/zipball/fce3f4d9cfeb4ddc674c357b5a4c3a23ccf408ad", + "reference": "fce3f4d9cfeb4ddc674c357b5a4c3a23ccf408ad", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/string": "^6.4|^7.0|^8.0", + "symfony/type-info": "^7.4.7|^8.0.7" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "<5.2|>=7", + "phpdocumentor/type-resolver": "<1.5.1", + "symfony/cache": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/serializer": "<6.4" + }, + "require-dev": { + "phpdocumentor/reflection-docblock": "^5.2|^6.0", + "phpstan/phpdoc-parser": "^1.0|^2.0", + "symfony/cache": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/serializer": "^6.4|^7.0|^8.0" + }, + "time": "2026-07-28T07:09:44+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\PropertyInfo\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kévin Dunglas", + "email": "dunglas@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Extracts information about PHP class' properties using metadata of popular sources", + "homepage": "https://symfony.com", + "keywords": [ + "doctrine", + "phpdoc", + "property", + "symfony", + "type", + "validator" + ], + "support": { + "source": "https://github.com/symfony/property-info/tree/v7.4.15" + }, + "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/property-info" + }, { "name": "symfony/routing", "version": "v6.4.41", @@ -6176,6 +6591,113 @@ ], "install-path": "../symfony/routing" }, + { + "name": "symfony/serializer", + "version": "v7.4.15", + "version_normalized": "7.4.15.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/serializer.git", + "reference": "917f1575bec2853f45e012d8718f518365a9d258" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/serializer/zipball/917f1575bec2853f45e012d8718f518365a9d258", + "reference": "917f1575bec2853f45e012d8718f518365a9d258", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-php84": "^1.30" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "<5.2|>=7", + "phpdocumentor/type-resolver": "<1.5.1", + "symfony/dependency-injection": "<6.4", + "symfony/property-access": "<6.4.31|>=7.0,<7.4.2|>=8.0,<8.0.2", + "symfony/property-info": "<6.4.43", + "symfony/type-info": "<7.2.5", + "symfony/uid": "<6.4", + "symfony/validator": "<6.4", + "symfony/yaml": "<6.4" + }, + "require-dev": { + "phpdocumentor/reflection-docblock": "^5.2|^6.0", + "phpstan/phpdoc-parser": "^1.0|^2.0", + "seld/jsonlint": "^1.10", + "symfony/cache": "^6.4|^7.0|^8.0", + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^7.2|^8.0", + "symfony/error-handler": "^6.4|^7.0|^8.0", + "symfony/filesystem": "^6.4|^7.0|^8.0", + "symfony/form": "^6.4|^7.0|^8.0", + "symfony/http-foundation": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/messenger": "^6.4|^7.0|^8.0", + "symfony/mime": "^6.4|^7.0|^8.0", + "symfony/property-access": "^6.4.31|^7.4.2|^8.0.2", + "symfony/property-info": "^6.4.43|^7.4.15|^8.0.15", + "symfony/translation-contracts": "^2.5|^3", + "symfony/type-info": "^7.2.5|^8.0", + "symfony/uid": "^6.4|^7.0|^8.0", + "symfony/validator": "^6.4|^7.0|^8.0", + "symfony/var-dumper": "^6.4|^7.0|^8.0", + "symfony/var-exporter": "^6.4|^7.0|^8.0", + "symfony/yaml": "^6.4|^7.0|^8.0" + }, + "time": "2026-07-29T07:59:49+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Serializer\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/serializer/tree/v7.4.15" + }, + "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/serializer" + }, { "name": "symfony/service-contracts", "version": "v3.7.0", @@ -6543,29 +7065,115 @@ ], "install-path": "../symfony/translation-contracts" }, + { + "name": "symfony/type-info", + "version": "v7.4.9", + "version_normalized": "7.4.9.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/type-info.git", + "reference": "cafeedbf157b890e94ac5b83eaed85595106d5d6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/type-info/zipball/cafeedbf157b890e94ac5b83eaed85595106d5d6", + "reference": "cafeedbf157b890e94ac5b83eaed85595106d5d6", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "phpstan/phpdoc-parser": "<1.30" + }, + "require-dev": { + "phpstan/phpdoc-parser": "^1.30|^2.0" + }, + "time": "2026-04-22T15:21:55+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\TypeInfo\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mathias Arlaud", + "email": "mathias.arlaud@gmail.com" + }, + { + "name": "Baptiste LEDUC", + "email": "baptiste.leduc@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Extracts PHP types information.", + "homepage": "https://symfony.com", + "keywords": [ + "PHPStan", + "phpdoc", + "symfony", + "type" + ], + "support": { + "source": "https://github.com/symfony/type-info/tree/v7.4.9" + }, + "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/type-info" + }, { "name": "symfony/uid", - "version": "v6.4.32", - "version_normalized": "6.4.32.0", + "version": "v7.4.9", + "version_normalized": "7.4.9.0", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "6b973c385f00341b246f697d82dc01a09107acdd" + "reference": "2676b524340abcfe4d6151ec698463cebafee439" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/6b973c385f00341b246f697d82dc01a09107acdd", - "reference": "6b973c385f00341b246f697d82dc01a09107acdd", + "url": "https://api.github.com/repos/symfony/uid/zipball/2676b524340abcfe4d6151ec698463cebafee439", + "reference": "2676b524340abcfe4d6151ec698463cebafee439", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/polyfill-uuid": "^1.15" }, "require-dev": { - "symfony/console": "^5.4|^6.0|^7.0" + "symfony/console": "^6.4|^7.0|^8.0" }, - "time": "2025-12-23T15:07:59+00:00", + "time": "2026-04-30T15:19:22+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -6602,7 +7210,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v6.4.32" + "source": "https://github.com/symfony/uid/tree/v7.4.9" }, "funding": [ { @@ -6681,47 +7289,35 @@ }, { "name": "web-auth/cose-lib", - "version": "4.3.0", - "version_normalized": "4.3.0.0", + "version": "4.6.0", + "version_normalized": "4.6.0.0", "source": { "type": "git", "url": "https://github.com/web-auth/cose-lib.git", - "reference": "e5c417b3b90e06c84638a18d350e438d760cb955" + "reference": "3afe04df137baf97c5c3e28c5ee6f05536405148" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/web-auth/cose-lib/zipball/e5c417b3b90e06c84638a18d350e438d760cb955", - "reference": "e5c417b3b90e06c84638a18d350e438d760cb955", + "url": "https://api.github.com/repos/web-auth/cose-lib/zipball/3afe04df137baf97c5c3e28c5ee6f05536405148", + "reference": "3afe04df137baf97c5c3e28c5ee6f05536405148", "shasum": "" }, "require": { - "brick/math": "^0.9|^0.10|^0.11|^0.12", + "brick/math": "^0.9|^0.10|^0.11|^0.12|^0.13|^0.14|^0.15|^0.16|^0.17|^0.18", "ext-json": "*", - "ext-mbstring": "*", "ext-openssl": "*", "php": ">=8.1", "spomky-labs/pki-framework": "^1.0" }, "require-dev": { - "ekino/phpstan-banned-code": "^1.0", - "infection/infection": "^0.27", - "php-parallel-lint/php-parallel-lint": "^1.3", - "phpstan/extension-installer": "^1.3", - "phpstan/phpstan": "^1.7", - "phpstan/phpstan-deprecation-rules": "^1.0", - "phpstan/phpstan-phpunit": "^1.1", - "phpstan/phpstan-strict-rules": "^1.2", - "phpunit/phpunit": "^10.1", - "qossmic/deptrac-shim": "^1.0", - "rector/rector": "^0.19", - "symfony/phpunit-bridge": "^6.4|^7.0", - "symplify/easy-coding-standard": "^12.0" + "spomky-labs/cbor-php": "^3.2.2" }, "suggest": { "ext-bcmath": "For better performance, please install either GMP (recommended) or BCMath extension", - "ext-gmp": "For better performance, please install either GMP (recommended) or BCMath extension" + "ext-gmp": "For better performance, please install either GMP (recommended) or BCMath extension", + "spomky-labs/cbor-php": "For COSE Signature support" }, - "time": "2024-02-05T21:00:39+00:00", + "time": "2026-07-16T10:19:49+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -6751,7 +7347,7 @@ ], "support": { "issues": "https://github.com/web-auth/cose-lib/issues", - "source": "https://github.com/web-auth/cose-lib/tree/4.3.0" + "source": "https://github.com/web-auth/cose-lib/tree/4.6.0" }, "funding": [ { @@ -6767,48 +7363,44 @@ }, { "name": "web-auth/webauthn-lib", - "version": "4.9.3", - "version_normalized": "4.9.3.0", + "version": "5.3.5", + "version_normalized": "5.3.5.0", "source": { "type": "git", "url": "https://github.com/web-auth/webauthn-lib.git", - "reference": "129fbaccd22163429a39bf85e320fb9eddad035c" + "reference": "9e0986d999f4102e24ac8a598d3a80d98b56c19f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/web-auth/webauthn-lib/zipball/129fbaccd22163429a39bf85e320fb9eddad035c", - "reference": "129fbaccd22163429a39bf85e320fb9eddad035c", + "url": "https://api.github.com/repos/web-auth/webauthn-lib/zipball/9e0986d999f4102e24ac8a598d3a80d98b56c19f", + "reference": "9e0986d999f4102e24ac8a598d3a80d98b56c19f", "shasum": "" }, "require": { "ext-json": "*", - "ext-mbstring": "*", "ext-openssl": "*", - "lcobucci/clock": "^2.2|^3.0", "paragonie/constant_time_encoding": "^2.6|^3.0", - "php": ">=8.1", + "php": ">=8.2", + "phpdocumentor/reflection-docblock": "^5.3|^6.0", "psr/clock": "^1.0", "psr/event-dispatcher": "^1.0", - "psr/http-client": "^1.0", - "psr/http-factory": "^1.0", "psr/log": "^1.0|^2.0|^3.0", "spomky-labs/cbor-php": "^3.0", "spomky-labs/pki-framework": "^1.0", + "symfony/clock": "^6.4|^7.0|^8.0", "symfony/deprecation-contracts": "^3.2", - "symfony/uid": "^6.1|^7.0", + "symfony/property-access": "^6.4|^7.0|^8.0", + "symfony/property-info": "^6.4|^7.0|^8.0", + "symfony/serializer": "^6.4|^7.0|^8.0", + "symfony/uid": "^6.4|^7.0|^8.0", "web-auth/cose-lib": "^4.2.3" }, "suggest": { - "phpdocumentor/reflection-docblock": "As of 4.5.x, the phpdocumentor/reflection-docblock component will become mandatory for converting objects such as the Metadata Statement", - "psr/clock-implementation": "As of 4.5.x, the PSR Clock implementation will replace lcobucci/clock", "psr/log-implementation": "Recommended to receive logs from the library", "symfony/event-dispatcher": "Recommended to use dispatched events", - "symfony/property-access": "As of 4.5.x, the symfony/serializer component will become mandatory for converting objects such as the Metadata Statement", - "symfony/property-info": "As of 4.5.x, the symfony/serializer component will become mandatory for converting objects such as the Metadata Statement", - "symfony/serializer": "As of 4.5.x, the symfony/serializer component will become mandatory for converting objects such as the Metadata Statement", "web-token/jwt-library": "Mandatory for fetching Metadata Statement from distant sources" }, - "time": "2026-02-05T12:48:16+00:00", + "time": "2026-05-31T15:00:08+00:00", "type": "library", "extra": { "thanks": { @@ -6844,7 +7436,7 @@ "webauthn" ], "support": { - "source": "https://github.com/web-auth/webauthn-lib/tree/4.9.3" + "source": "https://github.com/web-auth/webauthn-lib/tree/5.3.5" }, "funding": [ { @@ -6857,6 +7449,75 @@ } ], "install-path": "../web-auth/webauthn-lib" + }, + { + "name": "webmozart/assert", + "version": "2.4.1", + "version_normalized": "2.4.1.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "2ccb7c2e821038c03a3e6e1700c570c158c55f70" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/2ccb7c2e821038c03a3e6e1700c570c158c55f70", + "reference": "2ccb7c2e821038c03a3e6e1700c570c158c55f70", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-date": "*", + "ext-filter": "*", + "php": "^8.2" + }, + "suggest": { + "ext-intl": "", + "ext-simplexml": "", + "ext-spl": "" + }, + "time": "2026-06-15T15:31:57+00:00", + "type": "library", + "extra": { + "psalm": { + "pluginClass": "Webmozart\\Assert\\PsalmPlugin" + }, + "branch-alias": { + "dev-master": "2.0-dev", + "dev-feature/2-0": "2.0-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" + }, + { + "name": "Woody Gilk", + "email": "woody.gilk@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/2.4.1" + }, + "install-path": "../webmozart/assert" } ], "dev": false, diff --git a/composer/installed.php b/composer/installed.php index c0b1a2807..1de451747 100644 --- a/composer/installed.php +++ b/composer/installed.php @@ -38,9 +38,9 @@ 'dev_requirement' => false, ), 'brick/math' => array( - 'pretty_version' => '0.12.1', - 'version' => '0.12.1.0', - 'reference' => 'f510c0a40911935b77b86859eb5223d58d660df1', + 'pretty_version' => '0.18.0', + 'version' => '0.18.0.0', + 'reference' => '82944324d1c1bdb2c2618e89978d4e2ad78d69ad', 'type' => 'library', 'install_path' => __DIR__ . '/../brick/math', 'aliases' => array(), @@ -244,15 +244,6 @@ 'aliases' => array(), 'dev_requirement' => false, ), - 'lcobucci/clock' => array( - 'pretty_version' => '3.5.0', - 'version' => '3.5.0.0', - 'reference' => 'a3139d9e97d47826f27e6a17bb63f13621f86058', - 'type' => 'library', - 'install_path' => __DIR__ . '/../lcobucci/clock', - 'aliases' => array(), - 'dev_requirement' => false, - ), 'marc-mabe/php-enum' => array( 'pretty_version' => 'v4.7.1', 'version' => '4.7.1.0', @@ -433,6 +424,33 @@ 'aliases' => array(), 'dev_requirement' => false, ), + 'phpdocumentor/reflection-common' => array( + 'pretty_version' => '2.2.0', + 'version' => '2.2.0.0', + 'reference' => '1d01c49d4ed62f25aa84a747ad35d5a16924662b', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpdocumentor/reflection-common', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'phpdocumentor/reflection-docblock' => array( + 'pretty_version' => '6.0.3', + 'version' => '6.0.3.0', + 'reference' => '7bae67520aa9f5ecc506d646810bd40d9da54582', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpdocumentor/reflection-docblock', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'phpdocumentor/type-resolver' => array( + 'pretty_version' => '2.0.0', + 'version' => '2.0.0.0', + 'reference' => '327a05bbee54120d4786a0dc67aad30226ad4cf9', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpdocumentor/type-resolver', + 'aliases' => array(), + 'dev_requirement' => false, + ), 'phpseclib/phpseclib' => array( 'pretty_version' => '3.0.55', 'version' => '3.0.55.0', @@ -442,6 +460,15 @@ 'aliases' => array(), 'dev_requirement' => false, ), + 'phpstan/phpdoc-parser' => array( + 'pretty_version' => '2.3.3', + 'version' => '2.3.3.0', + 'reference' => 'fb19eedd2bb67ff8cf7a5502ad329e701d6398a3', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpstan/phpdoc-parser', + 'aliases' => array(), + 'dev_requirement' => false, + ), 'pimple/pimple' => array( 'pretty_version' => 'v3.6.0', 'version' => '3.6.0.0', @@ -659,18 +686,18 @@ 'dev_requirement' => false, ), 'spomky-labs/cbor-php' => array( - 'pretty_version' => '3.0.4', - 'version' => '3.0.4.0', - 'reference' => '658ed12a85a6b31fa312b89cd92f3a4ce6df4c6b', + 'pretty_version' => '3.3.0', + 'version' => '3.3.0.0', + 'reference' => '013d13da69cf28b1ae501887daceccc850ca1c76', 'type' => 'library', 'install_path' => __DIR__ . '/../spomky-labs/cbor-php', 'aliases' => array(), 'dev_requirement' => false, ), 'spomky-labs/pki-framework' => array( - 'pretty_version' => '1.2.1', - 'version' => '1.2.1.0', - 'reference' => '0b10c8b53366729417d6226ae89a665f9e2d61b6', + 'pretty_version' => '1.6.0', + 'version' => '1.6.0.0', + 'reference' => '80778a25426288acd2e3a7cde2def41a3d59cddf', 'type' => 'library', 'install_path' => __DIR__ . '/../spomky-labs/pki-framework', 'aliases' => array(), @@ -685,6 +712,15 @@ 'aliases' => array(), 'dev_requirement' => false, ), + 'symfony/clock' => array( + 'pretty_version' => 'v7.4.8', + 'version' => '7.4.8.0', + 'reference' => '674fa3b98e21531dd040e613479f5f6fa8f32111', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/clock', + 'aliases' => array(), + 'dev_requirement' => false, + ), 'symfony/console' => array( 'pretty_version' => 'v7.4.15', 'version' => '7.4.15.0', @@ -872,9 +908,9 @@ 'dev_requirement' => false, ), 'symfony/polyfill-uuid' => array( - 'pretty_version' => 'v1.29.0', - 'version' => '1.29.0.0', - 'reference' => '3abdd21b0ceaa3000ee950097bc3cf9efc137853', + 'pretty_version' => 'v1.37.0', + 'version' => '1.37.0.0', + 'reference' => '26dfec253c4cf3e51b541b52ddf7e42cb0908e94', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-uuid', 'aliases' => array(), @@ -889,6 +925,24 @@ 'aliases' => array(), 'dev_requirement' => false, ), + 'symfony/property-access' => array( + 'pretty_version' => 'v7.4.8', + 'version' => '7.4.8.0', + 'reference' => 'b7dad9dae8b8a47ef7ecc76c8569e7d8c7d90cfc', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/property-access', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'symfony/property-info' => array( + 'pretty_version' => 'v7.4.15', + 'version' => '7.4.15.0', + 'reference' => 'fce3f4d9cfeb4ddc674c357b5a4c3a23ccf408ad', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/property-info', + 'aliases' => array(), + 'dev_requirement' => false, + ), 'symfony/routing' => array( 'pretty_version' => 'v6.4.41', 'version' => '6.4.41.0', @@ -898,6 +952,15 @@ 'aliases' => array(), 'dev_requirement' => false, ), + 'symfony/serializer' => array( + 'pretty_version' => 'v7.4.15', + 'version' => '7.4.15.0', + 'reference' => '917f1575bec2853f45e012d8718f518365a9d258', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/serializer', + 'aliases' => array(), + 'dev_requirement' => false, + ), 'symfony/service-contracts' => array( 'pretty_version' => 'v3.7.0', 'version' => '3.7.0.0', @@ -940,10 +1003,19 @@ 0 => '2.3|3.0', ), ), + 'symfony/type-info' => array( + 'pretty_version' => 'v7.4.9', + 'version' => '7.4.9.0', + 'reference' => 'cafeedbf157b890e94ac5b83eaed85595106d5d6', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/type-info', + 'aliases' => array(), + 'dev_requirement' => false, + ), 'symfony/uid' => array( - 'pretty_version' => 'v6.4.32', - 'version' => '6.4.32.0', - 'reference' => '6b973c385f00341b246f697d82dc01a09107acdd', + 'pretty_version' => 'v7.4.9', + 'version' => '7.4.9.0', + 'reference' => '2676b524340abcfe4d6151ec698463cebafee439', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/uid', 'aliases' => array(), @@ -959,22 +1031,31 @@ 'dev_requirement' => false, ), 'web-auth/cose-lib' => array( - 'pretty_version' => '4.3.0', - 'version' => '4.3.0.0', - 'reference' => 'e5c417b3b90e06c84638a18d350e438d760cb955', + 'pretty_version' => '4.6.0', + 'version' => '4.6.0.0', + 'reference' => '3afe04df137baf97c5c3e28c5ee6f05536405148', 'type' => 'library', 'install_path' => __DIR__ . '/../web-auth/cose-lib', 'aliases' => array(), 'dev_requirement' => false, ), 'web-auth/webauthn-lib' => array( - 'pretty_version' => '4.9.3', - 'version' => '4.9.3.0', - 'reference' => '129fbaccd22163429a39bf85e320fb9eddad035c', + 'pretty_version' => '5.3.5', + 'version' => '5.3.5.0', + 'reference' => '9e0986d999f4102e24ac8a598d3a80d98b56c19f', 'type' => 'library', 'install_path' => __DIR__ . '/../web-auth/webauthn-lib', 'aliases' => array(), 'dev_requirement' => false, ), + 'webmozart/assert' => array( + 'pretty_version' => '2.4.1', + 'version' => '2.4.1.0', + 'reference' => '2ccb7c2e821038c03a3e6e1700c570c158c55f70', + 'type' => 'library', + 'install_path' => __DIR__ . '/../webmozart/assert', + 'aliases' => array(), + 'dev_requirement' => false, + ), ), ); diff --git a/lcobucci/clock/src/Clock.php b/lcobucci/clock/src/Clock.php deleted file mode 100644 index 45a033b87..000000000 --- a/lcobucci/clock/src/Clock.php +++ /dev/null @@ -1,12 +0,0 @@ -now = $now; - } - - /** - * Adjusts the current time by a given modifier. - * - * @param non-empty-string $modifier @see https://www.php.net/manual/en/datetime.formats.php - * - * @throws DateMalformedStringException When an invalid date/time string is passed. - */ - public function adjustTime(string $modifier): void - { - $this->now = $this->now->modify($modifier); - } - - public function now(): DateTimeImmutable - { - return $this->now; - } -} diff --git a/lcobucci/clock/src/SystemClock.php b/lcobucci/clock/src/SystemClock.php deleted file mode 100644 index 36ccb774b..000000000 --- a/lcobucci/clock/src/SystemClock.php +++ /dev/null @@ -1,32 +0,0 @@ -timezone); - } -} diff --git a/lcobucci/clock/LICENSE b/phpdocumentor/reflection-common/LICENSE similarity index 94% rename from lcobucci/clock/LICENSE rename to phpdocumentor/reflection-common/LICENSE index 58ea9440e..ed6926c1e 100644 --- a/lcobucci/clock/LICENSE +++ b/phpdocumentor/reflection-common/LICENSE @@ -1,6 +1,6 @@ -MIT License +The MIT License (MIT) -Copyright (c) 2017 Luís Cobucci +Copyright (c) 2015 phpDocumentor Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -19,3 +19,4 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/phpdocumentor/reflection-common/src/Element.php b/phpdocumentor/reflection-common/src/Element.php new file mode 100644 index 000000000..8923e4fb0 --- /dev/null +++ b/phpdocumentor/reflection-common/src/Element.php @@ -0,0 +1,30 @@ +fqsen = $fqsen; + + if (isset($matches[2])) { + $this->name = $matches[2]; + } else { + $matches = explode('\\', $fqsen); + $name = end($matches); + assert(is_string($name)); + $this->name = trim($name, '()'); + } + } + + /** + * converts this class to string. + */ + public function __toString() : string + { + return $this->fqsen; + } + + /** + * Returns the name of the element without path. + */ + public function getName() : string + { + return $this->name; + } +} diff --git a/phpdocumentor/reflection-common/src/Location.php b/phpdocumentor/reflection-common/src/Location.php new file mode 100644 index 000000000..177deede6 --- /dev/null +++ b/phpdocumentor/reflection-common/src/Location.php @@ -0,0 +1,53 @@ +lineNumber = $lineNumber; + $this->columnNumber = $columnNumber; + } + + /** + * Returns the line number that is covered by this location. + */ + public function getLineNumber() : int + { + return $this->lineNumber; + } + + /** + * Returns the column number (character position on a line) for this location object. + */ + public function getColumnNumber() : int + { + return $this->columnNumber; + } +} diff --git a/phpdocumentor/reflection-common/src/Project.php b/phpdocumentor/reflection-common/src/Project.php new file mode 100644 index 000000000..57839fd14 --- /dev/null +++ b/phpdocumentor/reflection-common/src/Project.php @@ -0,0 +1,25 @@ +summary = $summary; + $this->description = $description ?: new DocBlock\Description(''); + foreach ($tags as $tag) { + $this->addTag($tag); + } + + $this->context = $context; + $this->location = $location; + + $this->isTemplateEnd = $isTemplateEnd; + $this->isTemplateStart = $isTemplateStart; + } + + public function getSummary(): string + { + return $this->summary; + } + + public function getDescription(): DocBlock\Description + { + return $this->description; + } + + /** + * Returns the current context. + */ + public function getContext(): ?Types\Context + { + return $this->context; + } + + /** + * Returns the current location. + */ + public function getLocation(): ?Location + { + return $this->location; + } + + /** + * Returns whether this DocBlock is the start of a Template section. + * + * A Docblock may serve as template for a series of subsequent DocBlocks. This is indicated by a special marker + * (`#@+`) that is appended directly after the opening `/**` of a DocBlock. + * + * An example of such an opening is: + * + * ``` + * /**#@+ + * * My DocBlock + * * / + * ``` + * + * The description and tags (not the summary!) are copied onto all subsequent DocBlocks and also applied to all + * elements that follow until another DocBlock is found that contains the closing marker (`#@-`). + * + * @see self::isTemplateEnd() for the check whether a closing marker was provided. + */ + public function isTemplateStart(): bool + { + return $this->isTemplateStart; + } + + /** + * Returns whether this DocBlock is the end of a Template section. + * + * @see self::isTemplateStart() for a more complete description of the Docblock Template functionality. + */ + public function isTemplateEnd(): bool + { + return $this->isTemplateEnd; + } + + /** + * Returns the tags for this DocBlock. + * + * @return Tag[] + */ + public function getTags(): array + { + return $this->tags; + } + + /** + * Returns an array of tags matching the given name. If no tags are found + * an empty array is returned. + * + * @param string $name String to search by. + * + * @return Tag[] + */ + public function getTagsByName(string $name): array + { + $result = []; + + foreach ($this->getTags() as $tag) { + if ($tag->getName() !== $name) { + continue; + } + + $result[] = $tag; + } + + return $result; + } + + /** + * Returns an array of tags with type matching the given name. If no tags are found + * an empty array is returned. + * + * @param string $name String to search by. + * + * @return TagWithType[] + */ + public function getTagsWithTypeByName(string $name): array + { + $result = []; + + foreach ($this->getTagsByName($name) as $tag) { + if (!$tag instanceof TagWithType) { + continue; + } + + $result[] = $tag; + } + + return $result; + } + + /** + * Checks if a tag of a certain type is present in this DocBlock. + * + * @param string $name Tag name to check for. + */ + public function hasTag(string $name): bool + { + foreach ($this->getTags() as $tag) { + if ($tag->getName() === $name) { + return true; + } + } + + return false; + } + + /** + * Remove a tag from this DocBlock. + * + * @param Tag $tagToRemove The tag to remove. + */ + public function removeTag(Tag $tagToRemove): void + { + foreach ($this->tags as $key => $tag) { + if ($tag === $tagToRemove) { + unset($this->tags[$key]); + break; + } + } + } + + /** + * Adds a tag to this DocBlock. + * + * @param Tag $tag The tag to add. + */ + private function addTag(Tag $tag): void + { + $this->tags[] = $tag; + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Description.php b/phpdocumentor/reflection-docblock/src/DocBlock/Description.php new file mode 100644 index 000000000..a188ae30f --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Description.php @@ -0,0 +1,118 @@ +create('This is a {@see Description}', $context); + * + * The description factory will interpret the given body and create a body template and list of tags from them, and pass + * that onto the constructor if this class. + * + * > The $context variable is a class of type {@see \phpDocumentor\Reflection\Types\Context} and contains the namespace + * > and the namespace aliases that apply to this DocBlock. These are used by the Factory to resolve and expand partial + * > type names and FQSENs. + * + * If you do not want to use the DescriptionFactory you can pass a body template and tag listing like this: + * + * $description = new Description( + * 'This is a %1$s', + * [ new See(new Fqsen('\phpDocumentor\Reflection\DocBlock\Description')) ] + * ); + * + * It is generally recommended to use the Factory as that will also apply escaping rules, while the Description object + * is mainly responsible for rendering. + * + * @see DescriptionFactory to create a new Description. + * @see Tags\Formatter for the formatting of the body and tags. + */ +class Description +{ + private string $bodyTemplate; + + /** @var Tag[] */ + private array $tags; + + /** + * Initializes a Description with its body (template) and a listing of the tags used in the body template. + * + * @param Tag[] $tags + */ + public function __construct(string $bodyTemplate, array $tags = []) + { + $this->bodyTemplate = $bodyTemplate; + $this->tags = $tags; + } + + /** + * Returns the body template. + */ + public function getBodyTemplate(): string + { + return $this->bodyTemplate; + } + + /** + * Returns the tags for this DocBlock. + * + * @return Tag[] + */ + public function getTags(): array + { + return $this->tags; + } + + /** + * Renders this description as a string where the provided formatter will format the tags in the expected string + * format. + */ + public function render(?Formatter $formatter = null): string + { + if ($this->tags === []) { + return vsprintf($this->bodyTemplate, []); + } + + if ($formatter === null) { + $formatter = new PassthroughFormatter(); + } + + $tags = []; + foreach ($this->tags as $tag) { + $tags[] = '{' . $formatter->format($tag) . '}'; + } + + return vsprintf($this->bodyTemplate, $tags); + } + + /** + * Returns a plain string representation of this description. + */ + public function __toString(): string + { + return $this->render(); + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/DescriptionFactory.php b/phpdocumentor/reflection-docblock/src/DocBlock/DescriptionFactory.php new file mode 100644 index 000000000..6915c16ff --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/DescriptionFactory.php @@ -0,0 +1,179 @@ +tagFactory = $tagFactory; + } + + /** + * Returns the parsed text of this description. + */ + public function create(string $contents, ?TypeContext $context = null): Description + { + $tokens = $this->lex($contents); + $count = count($tokens); + $tagCount = 0; + $tags = []; + + for ($i = 1; $i < $count; $i += 2) { + $tags[] = $this->tagFactory->create($tokens[$i], $context); + $tokens[$i] = '%' . ++$tagCount . '$s'; + } + + //In order to allow "literal" inline tags, the otherwise invalid + //sequence "{@}" is changed to "@", and "{}" is changed to "}". + //"%" is escaped to "%%" because of vsprintf. + //See unit tests for examples. + for ($i = 0; $i < $count; $i += 2) { + $tokens[$i] = str_replace(['{@}', '{}', '%'], ['@', '}', '%%'], $tokens[$i]); + } + + return new Description(implode('', $tokens), $tags); + } + + /** + * Strips the contents from superfluous whitespace and splits the description into a series of tokens. + * + * @return string[] A series of tokens of which the description text is composed. + */ + private function lex(string $contents): array + { + $contents = $this->removeSuperfluousStartingWhitespace($contents); + + // performance optimalization; if there is no inline tag, don't bother splitting it up. + if (strpos($contents, '{@') === false) { + return [$contents]; + } + + return Utils::pregSplit( + '/\{ + # "{@}" and "{@*}" are not a valid inline tags. This ensures that we do not treat them as one, but treat + # them literally. + (?!(?:@\}|@\*\}) ) + # We want to capture the whole tag line, but without the inline tag delimiters. + (\@ + # Match everything up to the next delimiter. + [^{}]* + # Nested inline tag content should not be captured, or it will appear in the result separately. + (?: + # Match nested inline tags. + (?: + # Because we did not catch the tag delimiters earlier, we must be explicit with them here. + # Notice that this also matches "{}", as a way to later introduce it as an escape sequence. + \{(?1)?\} + | + # Make sure we match hanging "{". + \{ + ) + # Match content after the nested inline tag. + [^{}]* + )* # If there are more inline tags, match them as well. We use "*" since there may not be any + # nested inline tags. + ) + \}/Sux', + $contents, + 0, + PREG_SPLIT_DELIM_CAPTURE + ); + } + + /** + * Removes the superfluous from a multi-line description. + * + * When a description has more than one line then it can happen that the second and subsequent lines have an + * additional indentation. This is commonly in use with tags like this: + * + * {@}since 1.1.0 This is an example + * description where we have an + * indentation in the second and + * subsequent lines. + * + * If we do not normalize the indentation then we have superfluous whitespace on the second and subsequent + * lines and this may cause rendering issues when, for example, using a Markdown converter. + */ + private function removeSuperfluousStartingWhitespace(string $contents): string + { + $lines = Utils::pregSplit("/\r\n?|\n/", $contents); + + // if there is only one line then we don't have lines with superfluous whitespace and + // can use the contents as-is + if (count($lines) <= 1) { + return $contents; + } + + // determine how many whitespace characters need to be stripped + $startingSpaceCount = 9999999; + for ($i = 1, $iMax = count($lines); $i < $iMax; ++$i) { + // lines with a no length do not count as they are not indented at all + if (trim($lines[$i]) === '') { + continue; + } + + // determine the number of prefixing spaces by checking the difference in line length before and after + // an ltrim + $startingSpaceCount = min($startingSpaceCount, strlen($lines[$i]) - strlen(ltrim($lines[$i]))); + } + + // strip the number of spaces from each line + if ($startingSpaceCount > 0) { + for ($i = 1, $iMax = count($lines); $i < $iMax; ++$i) { + $lines[$i] = substr($lines[$i], $startingSpaceCount); + } + } + + return implode("\n", $lines); + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/ExampleFinder.php b/phpdocumentor/reflection-docblock/src/DocBlock/ExampleFinder.php new file mode 100644 index 000000000..0fb24a68b --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/ExampleFinder.php @@ -0,0 +1,158 @@ +getFilePath(); + + $file = $this->getExampleFileContents($filename); + if ($file === null) { + return sprintf('** File not found : %s **', $filename); + } + + return implode('', array_slice($file, $example->getStartingLine() - 1, $example->getLineCount())); + } + + /** + * Registers the project's root directory where an 'examples' folder can be expected. + */ + public function setSourceDirectory(string $directory = ''): void + { + $this->sourceDirectory = $directory; + } + + /** + * Returns the project's root directory where an 'examples' folder can be expected. + */ + public function getSourceDirectory(): string + { + return $this->sourceDirectory; + } + + /** + * Registers a series of directories that may contain examples. + * + * @param string[] $directories + */ + public function setExampleDirectories(array $directories): void + { + $this->exampleDirectories = $directories; + } + + /** + * Returns a series of directories that may contain examples. + * + * @return string[] + */ + public function getExampleDirectories(): array + { + return $this->exampleDirectories; + } + + /** + * Attempts to find the requested example file and returns its contents or null if no file was found. + * + * This method will try several methods in search of the given example file, the first one it encounters is + * returned: + * + * 1. Iterates through all examples folders for the given filename + * 2. Checks the source folder for the given filename + * 3. Checks the 'examples' folder in the current working directory for examples + * 4. Checks the path relative to the current working directory for the given filename + * + * @return string[] all lines of the example file + */ + private function getExampleFileContents(string $filename): ?array + { + $normalizedPath = null; + + foreach ($this->exampleDirectories as $directory) { + $exampleFileFromConfig = $this->constructExamplePath($directory, $filename); + if (is_readable($exampleFileFromConfig)) { + $normalizedPath = $exampleFileFromConfig; + break; + } + } + + if ($normalizedPath === null) { + if (is_readable($this->getExamplePathFromSource($filename))) { + $normalizedPath = $this->getExamplePathFromSource($filename); + } elseif (is_readable($this->getExamplePathFromExampleDirectory($filename))) { + $normalizedPath = $this->getExamplePathFromExampleDirectory($filename); + } elseif (is_readable($filename)) { + $normalizedPath = $filename; + } + } + + $lines = $normalizedPath !== null && is_readable($normalizedPath) ? file($normalizedPath) : false; + + return $lines !== false ? $lines : null; + } + + /** + * Get example filepath based on the example directory inside your project. + */ + private function getExamplePathFromExampleDirectory(string $file): string + { + return getcwd() . DIRECTORY_SEPARATOR . 'examples' . DIRECTORY_SEPARATOR . $file; + } + + /** + * Returns a path to the example file in the given directory.. + */ + private function constructExamplePath(string $directory, string $file): string + { + return rtrim($directory, '\\/') . DIRECTORY_SEPARATOR . $file; + } + + /** + * Get example filepath based on sourcecode. + */ + private function getExamplePathFromSource(string $file): string + { + return sprintf( + '%s%s%s', + trim($this->getSourceDirectory(), '\\/'), + DIRECTORY_SEPARATOR, + trim($file, '"') + ); + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Serializer.php b/phpdocumentor/reflection-docblock/src/DocBlock/Serializer.php new file mode 100644 index 000000000..2c257dd50 --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Serializer.php @@ -0,0 +1,156 @@ +indent = $indent; + $this->indentString = $indentString; + $this->isFirstLineIndented = $indentFirstLine; + $this->lineLength = $lineLength; + $this->tagFormatter = $tagFormatter ?: new PassthroughFormatter(); + $this->lineEnding = $lineEnding; + } + + /** + * Generate a DocBlock comment. + * + * @param DocBlock $docblock The DocBlock to serialize. + * + * @return string The serialized doc block. + */ + public function getDocComment(DocBlock $docblock): string + { + $indent = str_repeat($this->indentString, $this->indent); + $firstIndent = $this->isFirstLineIndented ? $indent : ''; + // 3 === strlen(' * ') + $wrapLength = $this->lineLength !== null ? $this->lineLength - strlen($indent) - 3 : null; + + $text = $this->removeTrailingSpaces( + $indent, + $this->addAsterisksForEachLine( + $indent, + $this->getSummaryAndDescriptionTextBlock($docblock, $wrapLength) + ) + ); + + $comment = $firstIndent . "/**\n"; + if ($text) { + $comment .= $indent . ' * ' . $text . "\n"; + $comment .= $indent . " *\n"; + } + + $comment = $this->addTagBlock($docblock, $wrapLength, $indent, $comment); + + return str_replace("\n", $this->lineEnding, $comment . $indent . ' */'); + } + + private function removeTrailingSpaces(string $indent, string $text): string + { + return str_replace( + sprintf("\n%s * \n", $indent), + sprintf("\n%s *\n", $indent), + $text + ); + } + + private function addAsterisksForEachLine(string $indent, string $text): string + { + return str_replace( + "\n", + sprintf("\n%s * ", $indent), + $text + ); + } + + private function getSummaryAndDescriptionTextBlock(DocBlock $docblock, ?int $wrapLength): string + { + $text = $docblock->getSummary() . ((string) $docblock->getDescription() ? "\n\n" . $docblock->getDescription() + : ''); + if ($wrapLength !== null) { + $text = wordwrap($text, $wrapLength); + + return $text; + } + + return $text; + } + + private function addTagBlock(DocBlock $docblock, ?int $wrapLength, string $indent, string $comment): string + { + foreach ($docblock->getTags() as $tag) { + $tagText = $this->tagFormatter->format($tag); + if ($wrapLength !== null) { + $tagText = wordwrap($tagText, $wrapLength); + } + + $tagText = str_replace( + "\n", + sprintf("\n%s * ", $indent), + $tagText + ); + + $comment .= sprintf("%s * %s\n", $indent, $tagText); + } + + return $comment; + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/StandardTagFactory.php b/phpdocumentor/reflection-docblock/src/DocBlock/StandardTagFactory.php new file mode 100644 index 000000000..1d9e5fe36 --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/StandardTagFactory.php @@ -0,0 +1,392 @@ + Important: each parameter in addition to the body variable for the `create` method must default to null, otherwise + * > it violates the constraint with the interface; it is recommended to use the {@see Assert::notNull()} method to + * > verify that a dependency is actually passed. + * + * This Factory also features a Service Locator component that is used to pass the right dependencies to the + * `create` method of a tag; each dependency should be registered as a service or as a parameter. + * + * When you want to use a Tag of your own with custom handling you need to call the `registerTagHandler` method, pass + * the name of the tag and a Fully Qualified Class Name pointing to a class that implements the Tag interface. + */ +final class StandardTagFactory implements TagFactory +{ + /** PCRE regular expression matching a tag name. */ + public const REGEX_TAGNAME = '[\w\-\_\\\\:]+'; + + /** + * @var array|Tag|Factory> An array with a tag as a key, and an + * FQCN to a class that handles it as an array value. + */ + private array $tagHandlerMappings = [ + 'author' => Author::class, + 'covers' => Covers::class, + 'deprecated' => Deprecated::class, + 'link' => LinkTag::class, + 'see' => SeeTag::class, + 'since' => Since::class, + 'source' => Source::class, + 'uses' => Uses::class, + 'version' => Version::class, + ]; + + /** + * @var array> An array with an annotation as a key, and an + * FQCN to a class that handles it as an array value. + */ + private array $annotationMappings = []; + + /** + * @var ReflectionParameter[][] a lazy-loading cache containing parameters + * for each tagHandler that has been used. + */ + private array $tagHandlerParameterCache = []; + + private FqsenResolver $fqsenResolver; + + /** + * @var mixed[] an array representing a simple Service Locator where we can store parameters and + * services that can be inserted into the Factory Methods of Tag Handlers. + */ + private array $serviceLocator = []; + + private function __construct(FqsenResolver $fqsenResolver) + { + $this->fqsenResolver = $fqsenResolver; + + $this->addService($fqsenResolver, FqsenResolver::class); + } + + /** + * Initialize this tag factory with the means to resolve an FQSEN. + * + * @see self::registerTagHandler() to add a new tag handler to the existing default list. + */ + public static function createInstance(FqsenResolver $fqsenResolver): self + { + $tagFactory = new self($fqsenResolver); + $descriptionFactory = new DescriptionFactory($tagFactory); + + $typeResolver = new TypeResolver($fqsenResolver); + + $phpstanTagFactory = new AbstractPHPStanFactory( + new ParamFactory($typeResolver, $descriptionFactory), + new VarFactory($typeResolver, $descriptionFactory), + new ReturnFactory($typeResolver, $descriptionFactory), + new PropertyFactory($typeResolver, $descriptionFactory), + new PropertyReadFactory($typeResolver, $descriptionFactory), + new PropertyWriteFactory($typeResolver, $descriptionFactory), + new MethodFactory($typeResolver, $descriptionFactory), + new MixinFactory($typeResolver, $descriptionFactory), + new ImplementsFactory($typeResolver, $descriptionFactory), + new ExtendsFactory($typeResolver, $descriptionFactory), + new TemplateFactory($typeResolver, $descriptionFactory), + new TemplateCovariantFactory($typeResolver, $descriptionFactory), + new ThrowsFactory($typeResolver, $descriptionFactory), + ); + + $tagFactory->addService($descriptionFactory); + $tagFactory->addService($typeResolver); + $tagFactory->registerTagHandler('param', $phpstanTagFactory); + $tagFactory->registerTagHandler('var', $phpstanTagFactory); + $tagFactory->registerTagHandler('return', $phpstanTagFactory); + $tagFactory->registerTagHandler('property', $phpstanTagFactory); + $tagFactory->registerTagHandler('property-read', $phpstanTagFactory); + $tagFactory->registerTagHandler('property-write', $phpstanTagFactory); + $tagFactory->registerTagHandler('method', $phpstanTagFactory); + $tagFactory->registerTagHandler('mixin', $phpstanTagFactory); + $tagFactory->registerTagHandler('extends', $phpstanTagFactory); + $tagFactory->registerTagHandler('implements', $phpstanTagFactory); + $tagFactory->registerTagHandler('template', $phpstanTagFactory); + $tagFactory->registerTagHandler('template-covariant', $phpstanTagFactory); + $tagFactory->registerTagHandler('template-extends', $phpstanTagFactory); + $tagFactory->registerTagHandler('template-implements', $phpstanTagFactory); + $tagFactory->registerTagHandler('throws', $phpstanTagFactory); + + return $tagFactory; + } + + public function create(string $tagLine, ?TypeContext $context = null): Tag + { + if (!$context) { + $context = new TypeContext(''); + } + + [$tagName, $tagBody] = $this->extractTagParts($tagLine); + + return $this->createTag(trim($tagBody), $tagName, $context); + } + + /** + * @param mixed $value + */ + public function addParameter(string $name, $value): void + { + $this->serviceLocator[$name] = $value; + } + + public function addService(object $service, ?string $alias = null): void + { + $this->serviceLocator[$alias ?? get_class($service)] = $service; + } + + /** {@inheritDoc} */ + public function registerTagHandler(string $tagName, $handler): void + { + Assert::stringNotEmpty($tagName); + if (strpos($tagName, '\\') !== false && $tagName[0] !== '\\') { + throw new InvalidArgumentException( + 'A namespaced tag must have a leading backslash as it must be fully qualified' + ); + } + + if (is_object($handler)) { + Assert::isInstanceOf($handler, Factory::class); + $this->tagHandlerMappings[$tagName] = $handler; + + return; + } + + Assert::classExists($handler); + Assert::implementsInterface($handler, Tag::class); + $this->tagHandlerMappings[$tagName] = $handler; + } + + /** + * Extracts all components for a tag. + * + * @return string[] + */ + private function extractTagParts(string $tagLine): array + { + $matches = []; + if (!preg_match('/^@(' . self::REGEX_TAGNAME . ')((?:[\s\(\{])\s*([^\s].*)|$)/us', $tagLine, $matches)) { + throw new InvalidArgumentException( + 'The tag "' . $tagLine . '" does not seem to be wellformed, please check it for errors' + ); + } + + return array_slice($matches, 1); + } + + /** + * Creates a new tag object with the given name and body or returns null if the tag name was recognized but the + * body was invalid. + */ + private function createTag(string $body, string $name, TypeContext $context): Tag + { + $handlerClassName = $this->findHandlerClassName($name, $context); + $arguments = $this->getArgumentsForParametersFromWiring( + $this->fetchParametersForHandlerFactoryMethod($handlerClassName), + $this->getServiceLocatorWithDynamicParameters($context, $name, $body) + ); + + if (array_key_exists('tagLine', $arguments)) { + $arguments['tagLine'] = sprintf('@%s %s', $name, $body); + } + + try { + $callable = [$handlerClassName, 'create']; + Assert::isCallable($callable); + /** @phpstan-var callable(string): ?Tag $callable */ + $tag = call_user_func_array($callable, $arguments); + + return $tag ?? InvalidTag::create($body, $name); + } catch (InvalidArgumentException $e) { + return InvalidTag::create($body, $name)->withError($e); + } + } + + /** + * Determines the Fully Qualified Class Name of the Factory or Tag (containing a Factory Method `create`). + * + * @return class-string|Tag|Factory + */ + private function findHandlerClassName(string $tagName, TypeContext $context) + { + $handlerClassName = Generic::class; + if (isset($this->tagHandlerMappings[$tagName])) { + $handlerClassName = $this->tagHandlerMappings[$tagName]; + } elseif ($this->isAnnotation($tagName)) { + // TODO: Annotation support is planned for a later stage and as such is disabled for now + $tagName = (string) $this->fqsenResolver->resolve($tagName, $context); + if (isset($this->annotationMappings[$tagName])) { + $handlerClassName = $this->annotationMappings[$tagName]; + } + } + + return $handlerClassName; + } + + /** + * Retrieves the arguments that need to be passed to the Factory Method with the given Parameters. + * + * @param ReflectionParameter[] $parameters + * @param mixed[] $locator + * + * @return mixed[] A series of values that can be passed to the Factory Method of the tag whose parameters + * is provided with this method. + */ + private function getArgumentsForParametersFromWiring(array $parameters, array $locator): array + { + $arguments = []; + foreach ($parameters as $parameter) { + $type = $parameter->getType(); + $typeHint = null; + if ($type instanceof ReflectionNamedType) { + $typeHint = $type->getName(); + if ($typeHint === 'self') { + $declaringClass = $parameter->getDeclaringClass(); + if ($declaringClass !== null) { + $typeHint = $declaringClass->getName(); + } + } + } + + $parameterName = $parameter->getName(); + if (isset($locator[$typeHint ?? ''])) { + $arguments[$parameterName] = $locator[$typeHint ?? '']; + continue; + } + + if (isset($locator[$parameterName])) { + $arguments[$parameterName] = $locator[$parameterName]; + continue; + } + + $arguments[$parameterName] = null; + } + + return $arguments; + } + + /** + * Retrieves a series of ReflectionParameter objects for the static 'create' method of the given + * tag handler class name. + * + * @param class-string|Tag|Factory $handler + * + * @return ReflectionParameter[] + */ + private function fetchParametersForHandlerFactoryMethod($handler): array + { + $handlerClassName = is_object($handler) ? get_class($handler) : $handler; + + if (!isset($this->tagHandlerParameterCache[$handlerClassName])) { + $methodReflection = new ReflectionMethod($handlerClassName, 'create'); + $this->tagHandlerParameterCache[$handlerClassName] = $methodReflection->getParameters(); + } + + return $this->tagHandlerParameterCache[$handlerClassName]; + } + + /** + * Returns a copy of this class' Service Locator with added dynamic parameters, + * such as the tag's name, body and Context. + * + * @param TypeContext $context The Context (namespace and aliases) that may be + * passed and is used to resolve FQSENs. + * @param string $tagName The name of the tag that may be + * passed onto the factory method of the Tag class. + * @param string $tagBody The body of the tag that may be + * passed onto the factory method of the Tag class. + * + * @return mixed[] + */ + private function getServiceLocatorWithDynamicParameters( + TypeContext $context, + string $tagName, + string $tagBody + ): array { + return array_merge( + $this->serviceLocator, + [ + 'name' => $tagName, + 'body' => $tagBody, + TypeContext::class => $context, + ] + ); + } + + /** + * Returns whether the given tag belongs to an annotation. + * + * @todo this method should be populated once we implement Annotation notation support. + */ + private function isAnnotation(string $tagContent): bool + { + // 1. Contains a namespace separator + // 2. Contains parenthesis + // 3. Is present in a list of known annotations (make the algorithm smart by first checking is the last part + // of the annotation class name matches the found tag name + + return false; + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tag.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tag.php new file mode 100644 index 000000000..7cf07b4dd --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tag.php @@ -0,0 +1,31 @@ +|Factory $handler FQCN of handler. + * + * @throws InvalidArgumentException If the tag name is not a string. + * @throws InvalidArgumentException If the tag name is namespaced (contains backslashes) but + * does not start with a backslash. + * @throws InvalidArgumentException If the handler is not a string. + * @throws InvalidArgumentException If the handler is not an existing class. + * @throws InvalidArgumentException If the handler does not implement the {@see Tag} interface. + */ + public function registerTagHandler(string $tagName, $handler): void; +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Author.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Author.php new file mode 100644 index 000000000..e604ac8b0 --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Author.php @@ -0,0 +1,102 @@ +authorName = $authorName; + $this->authorEmail = $authorEmail; + } + + /** + * Gets the author's name. + * + * @return string The author's name. + */ + public function getAuthorName(): string + { + return $this->authorName; + } + + /** + * Returns the author's email. + * + * @return string The author's email. + */ + public function getEmail(): string + { + return $this->authorEmail; + } + + /** + * Returns this tag in string form. + */ + public function __toString(): string + { + if ($this->authorEmail) { + $authorEmail = '<' . $this->authorEmail . '>'; + } else { + $authorEmail = ''; + } + + $authorName = $this->authorName; + + return $authorName . ($authorEmail !== '' ? ($authorName !== '' ? ' ' : '') . $authorEmail : ''); + } + + /** + * Attempts to create a new Author object based on the tag body. + */ + public static function create(string $body): ?self + { + $splitTagContent = preg_match('/^([^\<]*)(?:\<([^\>]*)\>)?$/u', $body, $matches); + if (!$splitTagContent) { + return null; + } + + $authorName = trim($matches[1]); + $email = isset($matches[2]) ? trim($matches[2]) : ''; + + return new static($authorName, $email); + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/BaseTag.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/BaseTag.php new file mode 100644 index 000000000..98b0d881d --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/BaseTag.php @@ -0,0 +1,53 @@ +name; + } + + public function getDescription(): ?Description + { + return $this->description; + } + + public function render(?Formatter $formatter = null): string + { + if ($formatter === null) { + $formatter = new Formatter\PassthroughFormatter(); + } + + return $formatter->format($this); + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Covers.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Covers.php new file mode 100644 index 000000000..ba2384f8a --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Covers.php @@ -0,0 +1,99 @@ +refers = $refers; + $this->description = $description; + } + + public static function create( + string $body, + ?DescriptionFactory $descriptionFactory = null, + ?FqsenResolver $resolver = null, + ?TypeContext $context = null + ): self { + Assert::stringNotEmpty($body); + Assert::notNull($descriptionFactory); + Assert::notNull($resolver); + + $parts = Utils::pregSplit('/\s+/Su', $body, 2); + + return new static( + self::resolveFqsen($parts[0], $resolver, $context), + $descriptionFactory->create($parts[1] ?? '', $context) + ); + } + + private static function resolveFqsen(string $parts, ?FqsenResolver $fqsenResolver, ?TypeContext $context): Fqsen + { + Assert::notNull($fqsenResolver); + $fqsenParts = explode('::', $parts); + $resolved = $fqsenResolver->resolve($fqsenParts[0], $context); + + if (!array_key_exists(1, $fqsenParts)) { + return $resolved; + } + + return new Fqsen($resolved . '::' . $fqsenParts[1]); + } + + /** + * Returns the structural element this tag refers to. + */ + public function getReference(): Fqsen + { + return $this->refers; + } + + /** + * Returns a string representation of this tag. + */ + public function __toString(): string + { + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + + $refers = (string) $this->refers; + + return $refers . ($description !== '' ? ($refers !== '' ? ' ' : '') . $description : ''); + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Deprecated.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Deprecated.php new file mode 100644 index 000000000..8ae8322bd --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Deprecated.php @@ -0,0 +1,108 @@ +version = $version; + $this->description = $description; + } + + /** + * @return static + */ + public static function create( + ?string $body, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ): self { + if ($body === null || $body === '') { + return new static(); + } + + $matches = []; + if (!preg_match('/^(' . self::REGEX_VECTOR . ')\s*(.+)?$/sux', $body, $matches)) { + return new static( + null, + $descriptionFactory !== null ? $descriptionFactory->create($body, $context) : null + ); + } + + Assert::notNull($descriptionFactory); + + return new static( + $matches[1], + $descriptionFactory->create($matches[2] ?? '', $context) + ); + } + + /** + * Gets the version section of the tag. + */ + public function getVersion(): ?string + { + return $this->version; + } + + /** + * Returns a string representation for this tag. + */ + public function __toString(): string + { + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + + $version = (string) $this->version; + + return $version . ($description !== '' ? ($version !== '' ? ' ' : '') . $description : ''); + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Example.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Example.php new file mode 100644 index 000000000..06ecf8c10 --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Example.php @@ -0,0 +1,197 @@ +filePath = $filePath; + $this->startingLine = $startingLine; + $this->lineCount = $lineCount; + if ($content !== null) { + $this->content = trim($content); + } + + $this->isURI = $isURI; + } + + public function getContent(): string + { + if ($this->content === null || $this->content === '') { + $filePath = $this->filePath; + if ($this->isURI) { + $filePath = $this->isUriRelative($this->filePath) + ? str_replace('%2F', '/', rawurlencode($this->filePath)) + : $this->filePath; + } + + return trim($filePath); + } + + return $this->content; + } + + public function getDescription(): ?string + { + return $this->content; + } + + public static function create(string $body): ?Tag + { + // File component: File path in quotes or File URI / Source information + if (!preg_match('/^\s*(?:(\"[^\"]+\")|(\S+))(?:\s+(.*))?$/sux', $body, $matches)) { + return null; + } + + $filePath = null; + $fileUri = null; + if (array_key_exists(1, $matches) && $matches[1] !== '') { + $filePath = $matches[1]; + } else { + $fileUri = array_key_exists(2, $matches) ? $matches[2] : ''; + } + + $startingLine = 1; + $lineCount = 0; + $description = null; + + if (array_key_exists(3, $matches)) { + $description = $matches[3]; + + // Starting line / Number of lines / Description + if (preg_match('/^([1-9]\d*)(?:\s+((?1))\s*)?(.*)$/sux', $matches[3], $contentMatches)) { + $startingLine = (int) $contentMatches[1]; + if (isset($contentMatches[2])) { + $lineCount = (int) $contentMatches[2]; + } + + if (array_key_exists(3, $contentMatches)) { + $description = $contentMatches[3]; + } + } + } + + return new static( + $filePath ?? ($fileUri ?? ''), + $fileUri !== null, + $startingLine, + $lineCount, + $description + ); + } + + /** + * Returns the file path. + * + * @return string Path to a file to use as an example. + * May also be an absolute URI. + */ + public function getFilePath(): string + { + return trim($this->filePath, '"'); + } + + /** + * Returns a string representation for this tag. + */ + public function __toString(): string + { + $filePath = $this->filePath; + $isDefaultLine = $this->startingLine === 1 && $this->lineCount === 0; + $startingLine = !$isDefaultLine ? (string) $this->startingLine : ''; + $lineCount = !$isDefaultLine ? (string) $this->lineCount : ''; + $content = (string) $this->content; + + return $filePath + . ($startingLine !== '' + ? ($filePath !== '' ? ' ' : '') . $startingLine + : '') + . ($lineCount !== '' + ? ($filePath !== '' || $startingLine !== '' ? ' ' : '') . $lineCount + : '') + . ($content !== '' + ? ($filePath !== '' || $startingLine !== '' || $lineCount !== '' ? ' ' : '') . $content + : ''); + } + + /** + * Returns true if the provided URI is relative or contains a complete scheme (and thus is absolute). + */ + private function isUriRelative(string $uri): bool + { + return strpos($uri, ':') === false; + } + + public function getStartingLine(): int + { + return $this->startingLine; + } + + public function getLineCount(): int + { + return $this->lineCount; + } + + public function getName(): string + { + return 'example'; + } + + public function render(?Formatter $formatter = null): string + { + if ($formatter === null) { + $formatter = new Formatter\PassthroughFormatter(); + } + + return $formatter->format($this); + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Extends_.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Extends_.php new file mode 100644 index 000000000..583d791dc --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Extends_.php @@ -0,0 +1,30 @@ +name = 'extends'; + $this->type = $type; + $this->description = $description; + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/AbstractPHPStanFactory.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/AbstractPHPStanFactory.php new file mode 100644 index 000000000..770a09a3b --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/AbstractPHPStanFactory.php @@ -0,0 +1,130 @@ + true, 'lines' => true]); + $this->lexer = new Lexer($config); + $constParser = new ConstExprParser($config); + $this->parser = new PhpDocParser( + $config, + new TypeParser($config, $constParser), + $constParser + ); + + $this->factories = $factories; + } + + public function create(string $tagLine, ?TypeContext $context = null): Tag + { + try { + $tokens = $this->tokenizeLine($tagLine); + $ast = $this->parser->parseTag($tokens); + if (property_exists($ast->value, 'description') === true) { + $ast->value->setAttribute( + 'description', + rtrim($ast->value->description . $tokens->joinUntil(Lexer::TOKEN_END), "\n") + ); + } + } catch (ParserException $e) { + return InvalidTag::create($tagLine, '')->withError($e); + } + + if ($context === null) { + $context = new TypeContext(''); + } + + try { + foreach ($this->factories as $factory) { + if ($factory->supports($ast, $context)) { + return $factory->create($ast, $context); + } + } + } catch (RuntimeException $e) { + return InvalidTag::create((string) $ast->value, 'method')->withError($e); + } catch (ParserException $e) { + return InvalidTag::create((string) $ast->value, $ast->name)->withError($e); + } + + return InvalidTag::create( + (string) $ast->value, + $ast->name + ); + } + + /** + * Solve the issue with the lexer not tokenizing the line correctly + * + * This method is a workaround for the lexer that includes newline tokens with spaces. For + * phpstan this isn't an issue, as it doesn't do a lot of things with the indentation of descriptions. + * But for us is important to keep the indentation of the descriptions, so we need to fix the lexer output. + */ + private function tokenizeLine(string $tagLine): TokenIterator + { + // Prefix continuation lines with "* ", which is consumed by the phpstan parser as TOKEN_PHPDOC_EOL. + $tagLine = str_replace("\n", "\n* ", $tagLine); + $tokens = $this->lexer->tokenize($tagLine . "\n"); + $fixed = []; + foreach ($tokens as $token) { + if ($token[Lexer::TYPE_OFFSET] === Lexer::TOKEN_PHPDOC_EOL) { + // Strip "* " prefix (and other horizontal whitespace) again so it doesn't and up in the + // description when we joinUntil() in create(). + $fixed[] = [ + Lexer::VALUE_OFFSET => trim($token[Lexer::VALUE_OFFSET], "* \t"), + Lexer::TYPE_OFFSET => $token[Lexer::TYPE_OFFSET], + Lexer::LINE_OFFSET => $token[Lexer::LINE_OFFSET] ?? 0, + ]; + + continue; + } + + $fixed[] = $token; + } + + return new TokenIterator($fixed); + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ExtendsFactory.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ExtendsFactory.php new file mode 100644 index 000000000..9a5528de2 --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ExtendsFactory.php @@ -0,0 +1,52 @@ +descriptionFactory = $descriptionFactory; + $this->typeResolver = $typeResolver; + } + + public function supports(PhpDocTagNode $node, Context $context): bool + { + return $node->value instanceof ExtendsTagValueNode && $node->name === '@extends'; + } + + public function create(PhpDocTagNode $node, Context $context): Tag + { + $tagValue = $node->value; + Assert::isInstanceOf($tagValue, ExtendsTagValueNode::class); + + $description = $tagValue->getAttribute('description'); + if (is_string($description) === false) { + $description = $tagValue->description; + } + + return new Extends_( + $this->typeResolver->createType($tagValue->type, $context), + $this->descriptionFactory->create($description, $context) + ); + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/Factory.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/Factory.php new file mode 100644 index 000000000..190d3ff85 --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/Factory.php @@ -0,0 +1,41 @@ +descriptionFactory = $descriptionFactory; + $this->typeResolver = $typeResolver; + } + + public function supports(PhpDocTagNode $node, Context $context): bool + { + return $node->value instanceof ImplementsTagValueNode && $node->name === '@implements'; + } + + public function create(PhpDocTagNode $node, Context $context): Tag + { + $tagValue = $node->value; + Assert::isInstanceOf($tagValue, ImplementsTagValueNode::class); + + $description = $tagValue->getAttribute('description'); + if (is_string($description) === false) { + $description = $tagValue->description; + } + + return new Implements_( + $this->typeResolver->createType($tagValue->type, $context), + $this->descriptionFactory->create($description, $context) + ); + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/MethodFactory.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/MethodFactory.php new file mode 100644 index 000000000..845a2da62 --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/MethodFactory.php @@ -0,0 +1,82 @@ +descriptionFactory = $descriptionFactory; + $this->typeResolver = $typeResolver; + } + + public function create(PhpDocTagNode $node, Context $context): Tag + { + $tagValue = $node->value; + Assert::isInstanceOf($tagValue, MethodTagValueNode::class); + + return new Method( + $tagValue->methodName, + array_map( + function (MethodTagValueParameterNode $param) use ($context) { + return new MethodParameter( + trim($param->parameterName, '$'), + $param->type === null ? new Mixed_() : $this->typeResolver->createType( + $param->type, + $context + ), + $param->isReference, + $param->isVariadic, + $param->defaultValue === null ? + MethodParameter::NO_DEFAULT_VALUE : + (string) $param->defaultValue + ); + }, + $tagValue->parameters + ), + $this->createReturnType($tagValue, $context), + $tagValue->isStatic, + $this->descriptionFactory->create($tagValue->description, $context), + false, + ); + } + + public function supports(PhpDocTagNode $node, Context $context): bool + { + return $node->value instanceof MethodTagValueNode; + } + + private function createReturnType(MethodTagValueNode $tagValue, Context $context): Type + { + if ($tagValue->returnType === null) { + return new Void_(); + } + + return $this->typeResolver->createType($tagValue->returnType, $context); + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/MethodParameterFactory.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/MethodParameterFactory.php new file mode 100644 index 000000000..d98237cb9 --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/MethodParameterFactory.php @@ -0,0 +1,100 @@ +{$method}($defaultValue); + } + + return ''; + } + + private function formatDouble(float $defaultValue): string + { + return var_export($defaultValue, true); + } + + /** + * @param mixed $defaultValue + */ + private function formatNull($defaultValue): string + { + return 'null'; + } + + private function formatInteger(int $defaultValue): string + { + return var_export($defaultValue, true); + } + + private function formatString(string $defaultValue): string + { + return var_export($defaultValue, true); + } + + private function formatBoolean(bool $defaultValue): string + { + return var_export($defaultValue, true); + } + + /** + * @param array<(array|int|float|bool|string|object|null)> $defaultValue + */ + private function formatArray(array $defaultValue): string + { + $formatedValue = '['; + + foreach ($defaultValue as $key => $value) { + $method = 'format' . ucfirst(gettype($value)); + if (!method_exists($this, $method)) { + continue; + } + + $formatedValue .= $this->{$method}($value); + + if ($key === array_key_last($defaultValue)) { + continue; + } + + $formatedValue .= ','; + } + + return $formatedValue . ']'; + } + + private function formatObject(object $defaultValue): string + { + return 'new ' . get_class($defaultValue) . '()'; + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/MixinFactory.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/MixinFactory.php new file mode 100644 index 000000000..03e4421df --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/MixinFactory.php @@ -0,0 +1,52 @@ +descriptionFactory = $descriptionFactory; + $this->typeResolver = $typeResolver; + } + + public function create(PhpDocTagNode $node, Context $context): Tag + { + $tagValue = $node->value; + Assert::isInstanceOf($tagValue, MixinTagValueNode::class); + + $description = $tagValue->getAttribute('description'); + if (is_string($description) === false) { + $description = $tagValue->description; + } + + return new Mixin( + $this->typeResolver->createType($tagValue->type, $context), + $this->descriptionFactory->create($description, $context) + ); + } + + public function supports(PhpDocTagNode $node, Context $context): bool + { + return $node->value instanceof MixinTagValueNode; + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PHPStanFactory.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PHPStanFactory.php new file mode 100644 index 000000000..cf04a06e6 --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PHPStanFactory.php @@ -0,0 +1,16 @@ +descriptionFactory = $descriptionFactory; + $this->typeResolver = $typeResolver; + } + + public function create(PhpDocTagNode $node, Context $context): Tag + { + $tagValue = $node->value; + + if ($tagValue instanceof InvalidTagValueNode) { + return InvalidTag::create($tagValue->value, 'param')->withError( + ParserException::from($tagValue->exception) + ); + } + + Assert::isInstanceOfAny( + $tagValue, + [ + ParamTagValueNode::class, + TypelessParamTagValueNode::class, + ] + ); + + if (($tagValue->type ?? null) instanceof OffsetAccessTypeNode) { + return InvalidTag::create( + (string) $tagValue, + 'param' + ); + } + + $description = $tagValue->getAttribute('description'); + if (is_string($description) === false) { + $description = $tagValue->description; + } + + return new Param( + trim($tagValue->parameterName, '$'), + $this->typeResolver->createType($tagValue->type ?? new IdentifierTypeNode('mixed'), $context), + $tagValue->isVariadic, + $this->descriptionFactory->create($description, $context), + $tagValue->isReference + ); + } + + public function supports(PhpDocTagNode $node, Context $context): bool + { + return $node->value instanceof ParamTagValueNode + || $node->value instanceof TypelessParamTagValueNode + || $node->name === '@param'; + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyFactory.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyFactory.php new file mode 100644 index 000000000..b744ed08f --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyFactory.php @@ -0,0 +1,54 @@ +descriptionFactory = $descriptionFactory; + $this->typeResolver = $typeResolver; + } + + public function create(PhpDocTagNode $node, Context $context): Tag + { + $tagValue = $node->value; + Assert::isInstanceOf($tagValue, PropertyTagValueNode::class); + + $description = $tagValue->getAttribute('description'); + if (is_string($description) === false) { + $description = $tagValue->description; + } + + return new Property( + trim($tagValue->propertyName, '$'), + $this->typeResolver->createType($tagValue->type, $context), + $this->descriptionFactory->create($description, $context) + ); + } + + public function supports(PhpDocTagNode $node, Context $context): bool + { + return $node->value instanceof PropertyTagValueNode && $node->name === '@property'; + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyReadFactory.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyReadFactory.php new file mode 100644 index 000000000..b0898aa73 --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyReadFactory.php @@ -0,0 +1,54 @@ +typeResolver = $typeResolver; + $this->descriptionFactory = $descriptionFactory; + } + + public function create(PhpDocTagNode $node, Context $context): Tag + { + $tagValue = $node->value; + Assert::isInstanceOf($tagValue, PropertyTagValueNode::class); + + $description = $tagValue->getAttribute('description'); + if (is_string($description) === false) { + $description = $tagValue->description; + } + + return new PropertyRead( + trim($tagValue->propertyName, '$'), + $this->typeResolver->createType($tagValue->type, $context), + $this->descriptionFactory->create($description, $context) + ); + } + + public function supports(PhpDocTagNode $node, Context $context): bool + { + return $node->value instanceof PropertyTagValueNode && $node->name === '@property-read'; + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyWriteFactory.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyWriteFactory.php new file mode 100644 index 000000000..749b1eda9 --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyWriteFactory.php @@ -0,0 +1,54 @@ +descriptionFactory = $descriptionFactory; + $this->typeResolver = $typeResolver; + } + + public function create(PhpDocTagNode $node, Context $context): Tag + { + $tagValue = $node->value; + Assert::isInstanceOf($tagValue, PropertyTagValueNode::class); + + $description = $tagValue->getAttribute('description'); + if (is_string($description) === false) { + $description = $tagValue->description; + } + + return new PropertyWrite( + trim($tagValue->propertyName, '$'), + $this->typeResolver->createType($tagValue->type, $context), + $this->descriptionFactory->create($description, $context) + ); + } + + public function supports(PhpDocTagNode $node, Context $context): bool + { + return $node->value instanceof PropertyTagValueNode && $node->name === '@property-write'; + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ReturnFactory.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ReturnFactory.php new file mode 100644 index 000000000..4a17dc245 --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ReturnFactory.php @@ -0,0 +1,52 @@ +descriptionFactory = $descriptionFactory; + $this->typeResolver = $typeResolver; + } + + public function create(PhpDocTagNode $node, Context $context): Tag + { + $tagValue = $node->value; + Assert::isInstanceOf($tagValue, ReturnTagValueNode::class); + + $description = $tagValue->getAttribute('description'); + if (is_string($description) === false) { + $description = $tagValue->description; + } + + return new Return_( + $this->typeResolver->createType($tagValue->type, $context), + $this->descriptionFactory->create($description, $context) + ); + } + + public function supports(PhpDocTagNode $node, Context $context): bool + { + return $node->value instanceof ReturnTagValueNode; + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/TemplateCovariantFactory.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/TemplateCovariantFactory.php new file mode 100644 index 000000000..329a99790 --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/TemplateCovariantFactory.php @@ -0,0 +1,53 @@ +descriptionFactory = $descriptionFactory; + $this->typeResolver = $typeResolver; + } + + public function supports(PhpDocTagNode $node, Context $context): bool + { + return $node->value instanceof TemplateTagValueNode && $node->name === '@template-covariant'; + } + + public function create(PhpDocTagNode $node, Context $context): Tag + { + $tagValue = $node->value; + Assert::isInstanceOf($tagValue, TemplateTagValueNode::class); + + $description = $tagValue->getAttribute('description'); + if (is_string($description) === false) { + $description = $tagValue->description; + } + + return new TemplateCovariant( + $this->typeResolver->createType(new IdentifierTypeNode($tagValue->name), $context), + $this->descriptionFactory->create($description, $context) + ); + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/TemplateFactory.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/TemplateFactory.php new file mode 100644 index 000000000..9e4b3c896 --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/TemplateFactory.php @@ -0,0 +1,56 @@ +descriptionFactory = $descriptionFactory; + $this->typeResolver = $typeResolver; + } + + public function create(PhpDocTagNode $node, Context $context): Tag + { + $tagValue = $node->value; + + Assert::isInstanceOf($tagValue, TemplateTagValueNode::class); + $name = $tagValue->name; + + $description = $tagValue->getAttribute('description'); + if (is_string($description) === false) { + $description = $tagValue->description; + } + + return new Template( + $name, + $this->typeResolver->createType($tagValue->bound, $context), + $this->typeResolver->createType($tagValue->default, $context), + $this->descriptionFactory->create($description, $context) + ); + } + + public function supports(PhpDocTagNode $node, Context $context): bool + { + return $node->value instanceof TemplateTagValueNode && $node->name === '@template'; + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ThrowsFactory.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ThrowsFactory.php new file mode 100644 index 000000000..e547adc1e --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ThrowsFactory.php @@ -0,0 +1,52 @@ +descriptionFactory = $descriptionFactory; + $this->typeResolver = $typeResolver; + } + + public function create(PhpDocTagNode $node, Context $context): Tag + { + $tagValue = $node->value; + Assert::isInstanceOf($tagValue, ThrowsTagValueNode::class); + + $description = $tagValue->getAttribute('description'); + if (is_string($description) === false) { + $description = $tagValue->description; + } + + return new Throws( + $this->typeResolver->createType($tagValue->type, $context), + $this->descriptionFactory->create($description, $context) + ); + } + + public function supports(PhpDocTagNode $node, Context $context): bool + { + return $node->value instanceof ThrowsTagValueNode; + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/VarFactory.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/VarFactory.php new file mode 100644 index 000000000..479ceb27d --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/VarFactory.php @@ -0,0 +1,54 @@ +descriptionFactory = $descriptionFactory; + $this->typeResolver = $typeResolver; + } + + public function create(PhpDocTagNode $node, Context $context): Tag + { + $tagValue = $node->value; + Assert::isInstanceOf($tagValue, VarTagValueNode::class); + + $description = $tagValue->getAttribute('description'); + if (is_string($description) === false) { + $description = $tagValue->description; + } + + return new Var_( + trim($tagValue->variableName, '$'), + $this->typeResolver->createType($tagValue->type, $context), + $this->descriptionFactory->create($description, $context) + ); + } + + public function supports(PhpDocTagNode $node, Context $context): bool + { + return $node->value instanceof VarTagValueNode; + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter.php new file mode 100644 index 000000000..36b9983ea --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter.php @@ -0,0 +1,24 @@ +maxLen = max($this->maxLen, strlen($tag->getName())); + } + } + + /** + * Formats the given tag to return a simple plain text version. + */ + public function format(Tag $tag): string + { + return '@' . $tag->getName() . + str_repeat( + ' ', + $this->maxLen - strlen($tag->getName()) + 1 + ) . + $tag; + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/PassthroughFormatter.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/PassthroughFormatter.php new file mode 100644 index 000000000..2afdfe55d --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/PassthroughFormatter.php @@ -0,0 +1,30 @@ +getName() . ' ' . $tag); + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Generic.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Generic.php new file mode 100644 index 000000000..1445b16c3 --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Generic.php @@ -0,0 +1,89 @@ +validateTagName($name); + + $this->name = $name; + $this->description = $description; + } + + /** + * Creates a new tag that represents any unknown tag type. + * + * @return static + */ + public static function create( + string $body, + string $name = '', + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ): self { + Assert::stringNotEmpty($name); + Assert::notNull($descriptionFactory); + + $description = $body !== '' ? $descriptionFactory->create($body, $context) : null; + + return new static($name, $description); + } + + /** + * Returns the tag as a serialized string + */ + public function __toString(): string + { + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + + return $description; + } + + /** + * Validates if the tag name matches the expected format, otherwise throws an exception. + */ + private function validateTagName(string $name): void + { + if (!preg_match('/^' . StandardTagFactory::REGEX_TAGNAME . '$/u', $name)) { + throw new InvalidArgumentException( + 'The tag name "' . $name . '" is not wellformed. Tags may only consist of letters, underscores, ' + . 'hyphens and backslashes.' + ); + } + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Implements_.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Implements_.php new file mode 100644 index 000000000..4c8ce5e2d --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Implements_.php @@ -0,0 +1,30 @@ +name = 'implements'; + $this->type = $type; + $this->description = $description; + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/InvalidTag.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/InvalidTag.php new file mode 100644 index 000000000..848f34d7b --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/InvalidTag.php @@ -0,0 +1,150 @@ +name = $name; + $this->body = $body; + } + + public function getException(): ?Throwable + { + return $this->throwable; + } + + public function getName(): string + { + return $this->name; + } + + public static function create(string $body, string $name = ''): self + { + return new self($name, $body); + } + + public function withError(Throwable $exception): self + { + $this->flattenExceptionBacktrace($exception); + $tag = new self($this->name, $this->body); + $tag->throwable = $exception; + + return $tag; + } + + /** + * Removes all complex types from backtrace + * + * Not all objects are serializable. So we need to remove them from the + * stored exception to be sure that we do not break existing library usage. + */ + private function flattenExceptionBacktrace(Throwable $exception): void + { + $traceProperty = (new ReflectionClass(Exception::class))->getProperty('trace'); + if (PHP_VERSION_ID < 80100) { + $traceProperty->setAccessible(true); + } + + do { + $trace = $exception->getTrace(); + if (isset($trace[0]['args'])) { + $trace = array_map( + function (array $call): array { + $call['args'] = array_map([$this, 'flattenArguments'], $call['args'] ?? []); + + return $call; + }, + $trace + ); + } + + $traceProperty->setValue($exception, $trace); + $exception = $exception->getPrevious(); + } while ($exception !== null); + + if (PHP_VERSION_ID >= 80100) { + return; + } + + $traceProperty->setAccessible(false); + } + + /** + * @param mixed $value + * + * @return mixed + * + * @throws ReflectionException + */ + private function flattenArguments($value) + { + if ($value instanceof Closure) { + $closureReflection = new ReflectionFunction($value); + $value = sprintf( + '(Closure at %s:%s)', + $closureReflection->getFileName(), + $closureReflection->getStartLine() + ); + } elseif (is_object($value)) { + $value = sprintf('object(%s)', get_class($value)); + } elseif (is_resource($value)) { + $value = sprintf('resource(%s)', get_resource_type($value)); + } elseif (is_array($value)) { + $value = array_map([$this, 'flattenArguments'], $value); + } + + return $value; + } + + public function render(?Formatter $formatter = null): string + { + if ($formatter === null) { + $formatter = new Formatter\PassthroughFormatter(); + } + + return $formatter->format($this); + } + + public function __toString(): string + { + return $this->body; + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Link.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Link.php new file mode 100644 index 000000000..8ce615d9e --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Link.php @@ -0,0 +1,76 @@ +link = $link; + $this->description = $description; + } + + public static function create( + string $body, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ): self { + Assert::notNull($descriptionFactory); + + $parts = Utils::pregSplit('/\s+/Su', $body, 2); + $description = isset($parts[1]) ? $descriptionFactory->create($parts[1], $context) : null; + + return new static($parts[0], $description); + } + + /** + * Gets the link + */ + public function getLink(): string + { + return $this->link; + } + + /** + * Returns a string representation for this tag. + */ + public function __toString(): string + { + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + + $link = $this->link; + + return $link . ($description !== '' ? ($link !== '' ? ' ' : '') . $description : ''); + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Method.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Method.php new file mode 100644 index 000000000..66d116750 --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Method.php @@ -0,0 +1,135 @@ +methodName = $methodName; + $this->returnType = $returnType; + $this->isStatic = $static; + $this->description = $description; + $this->returnsReference = $returnsReference; + $this->parameters = $parameters; + } + + /** + * Retrieves the method name. + */ + public function getMethodName(): string + { + return $this->methodName; + } + + /** @return MethodParameter[] */ + public function getParameters(): array + { + return $this->parameters; + } + + /** + * Checks whether the method tag describes a static method or not. + * + * @return bool TRUE if the method declaration is for a static method, FALSE otherwise. + */ + public function isStatic(): bool + { + return $this->isStatic; + } + + public function getReturnType(): Type + { + return $this->returnType; + } + + public function returnsReference(): bool + { + return $this->returnsReference; + } + + public function __toString(): string + { + $arguments = []; + foreach ($this->parameters as $parameter) { + $arguments[] = (string) $parameter; + } + + $argumentStr = '(' . implode(', ', $arguments) . ')'; + + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + + $static = $this->isStatic ? 'static' : ''; + + $returnType = (string) $this->returnType; + + $methodName = $this->methodName; + + $reference = $this->returnsReference ? '&' : ''; + + return $static + . ($returnType !== '' ? ($static !== '' ? ' ' : '') . $returnType : '') + . ($methodName !== '' ? ($static !== '' || $returnType !== '' ? ' ' : '') . $reference . $methodName : '') + . $argumentStr + . ($description !== '' ? ' ' . $description : ''); + } + + public static function create(string $body): void + { + throw new CannotCreateTag('Method tag cannot be created'); + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/MethodParameter.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/MethodParameter.php new file mode 100644 index 000000000..68c7ca981 --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/MethodParameter.php @@ -0,0 +1,91 @@ +type = $type; + $this->isReference = $isReference; + $this->isVariadic = $isVariadic; + $this->name = $name; + $this->defaultValue = $defaultValue; + } + + public function getName(): string + { + return $this->name; + } + + public function getType(): Type + { + return $this->type; + } + + public function isReference(): bool + { + return $this->isReference; + } + + public function isVariadic(): bool + { + return $this->isVariadic; + } + + public function getDefaultValue(): ?string + { + if ($this->defaultValue === self::NO_DEFAULT_VALUE) { + return null; + } + + return (new MethodParameterFactory())->format($this->defaultValue); + } + + public function __toString(): string + { + return $this->getType() . ' ' . + ($this->isReference() ? '&' : '') . + ($this->isVariadic() ? '...' : '') . + '$' . $this->getName() . + ( + $this->defaultValue !== self::NO_DEFAULT_VALUE ? + ' = ' . (new MethodParameterFactory())->format($this->defaultValue) : + '' + ); + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Mixin.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Mixin.php new file mode 100644 index 000000000..2b0909c25 --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Mixin.php @@ -0,0 +1,30 @@ +name = 'mixin'; + $this->type = $type; + $this->description = $description; + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Param.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Param.php new file mode 100644 index 000000000..1653365d3 --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Param.php @@ -0,0 +1,94 @@ +name = 'param'; + $this->variableName = $variableName; + $this->type = $type; + $this->isVariadic = $isVariadic; + $this->description = $description; + $this->isReference = $isReference; + } + + /** + * Returns the variable's name. + */ + public function getVariableName(): ?string + { + return $this->variableName; + } + + /** + * Returns whether this tag is variadic. + */ + public function isVariadic(): bool + { + return $this->isVariadic; + } + + /** + * Returns whether this tag is passed by reference. + */ + public function isReference(): bool + { + return $this->isReference; + } + + /** + * Returns a string representation for this tag. + */ + public function __toString(): string + { + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + + $variableName = ''; + if ($this->variableName !== null && $this->variableName !== '') { + $variableName .= ($this->isReference ? '&' : '') . ($this->isVariadic ? '...' : ''); + $variableName .= '$' . $this->variableName; + } + + $type = (string) $this->type; + + return $type + . ($variableName !== '' ? ($type !== '' ? ' ' : '') . $variableName : '') + . ($description !== '' ? ($type !== '' || $variableName !== '' ? ' ' : '') . $description : ''); + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Property.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Property.php new file mode 100644 index 000000000..b7bd95899 --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Property.php @@ -0,0 +1,68 @@ +name = 'property'; + $this->variableName = $variableName; + $this->type = $type; + $this->description = $description; + } + + /** + * Returns the variable's name. + */ + public function getVariableName(): ?string + { + return $this->variableName; + } + + /** + * Returns a string representation for this tag. + */ + public function __toString(): string + { + if ($this->description !== null) { + $description = $this->description->render(); + } else { + $description = ''; + } + + if ($this->variableName !== null && $this->variableName !== '') { + $variableName = '$' . $this->variableName; + } else { + $variableName = ''; + } + + $type = (string) $this->type; + + return $type + . ($variableName !== '' ? ($type !== '' ? ' ' : '') . $variableName : '') + . ($description !== '' ? ($type !== '' || $variableName !== '' ? ' ' : '') . $description : ''); + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyRead.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyRead.php new file mode 100644 index 000000000..bcb0e0d8b --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyRead.php @@ -0,0 +1,68 @@ +name = 'property-read'; + $this->variableName = $variableName; + $this->type = $type; + $this->description = $description; + } + + /** + * Returns the variable's name. + */ + public function getVariableName(): ?string + { + return $this->variableName; + } + + /** + * Returns a string representation for this tag. + */ + public function __toString(): string + { + if ($this->description !== null) { + $description = $this->description->render(); + } else { + $description = ''; + } + + if ($this->variableName !== null && $this->variableName !== '') { + $variableName = '$' . $this->variableName; + } else { + $variableName = ''; + } + + $type = (string) $this->type; + + return $type + . ($variableName !== '' ? ($type !== '' ? ' ' : '') . $variableName : '') + . ($description !== '' ? ($type !== '' || $variableName !== '' ? ' ' : '') . $description : ''); + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyWrite.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyWrite.php new file mode 100644 index 000000000..a5ee9e9e0 --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyWrite.php @@ -0,0 +1,68 @@ +name = 'property-write'; + $this->variableName = $variableName; + $this->type = $type; + $this->description = $description; + } + + /** + * Returns the variable's name. + */ + public function getVariableName(): ?string + { + return $this->variableName; + } + + /** + * Returns a string representation for this tag. + */ + public function __toString(): string + { + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + + if ($this->variableName) { + $variableName = '$' . $this->variableName; + } else { + $variableName = ''; + } + + $type = (string) $this->type; + + return $type + . ($variableName !== '' ? ($type !== '' ? ' ' : '') . $variableName : '') + . ($description !== '' ? ($type !== '' || $variableName !== '' ? ' ' : '') . $description : ''); + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Fqsen.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Fqsen.php new file mode 100644 index 000000000..e4e7e31c6 --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Fqsen.php @@ -0,0 +1,37 @@ +fqsen = $fqsen; + } + + /** + * @return string string representation of the referenced fqsen + */ + public function __toString(): string + { + return (string) $this->fqsen; + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Reference.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Reference.php new file mode 100644 index 000000000..e7dea868d --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Reference.php @@ -0,0 +1,22 @@ +uri = $uri; + } + + public function __toString(): string + { + return $this->uri; + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Return_.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Return_.php new file mode 100644 index 000000000..bc93a7935 --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Return_.php @@ -0,0 +1,30 @@ +name = 'return'; + $this->type = $type; + $this->description = $description; + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/See.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/See.php new file mode 100644 index 000000000..f8242d47f --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/See.php @@ -0,0 +1,104 @@ +refers = $refers; + $this->description = $description; + } + + public static function create( + string $body, + ?FqsenResolver $typeResolver = null, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ): self { + Assert::notNull($descriptionFactory); + + $parts = Utils::pregSplit('/\s+/Su', $body, 2); + $description = isset($parts[1]) ? $descriptionFactory->create($parts[1], $context) : null; + + // https://tools.ietf.org/html/rfc2396#section-3 + if (preg_match('#\w://\w#', $parts[0])) { + return new static(new Url($parts[0]), $description); + } + + return new static(new FqsenRef(self::resolveFqsen($parts[0], $typeResolver, $context)), $description); + } + + private static function resolveFqsen(string $parts, ?FqsenResolver $fqsenResolver, ?TypeContext $context): Fqsen + { + Assert::notNull($fqsenResolver); + $fqsenParts = explode('::', $parts); + $resolved = $fqsenResolver->resolve($fqsenParts[0], $context); + + if (!array_key_exists(1, $fqsenParts)) { + return $resolved; + } + + return new Fqsen($resolved . '::' . $fqsenParts[1]); + } + + /** + * Returns the ref of this tag. + */ + public function getReference(): Reference + { + return $this->refers; + } + + /** + * Returns a string representation of this tag. + */ + public function __toString(): string + { + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + + $refers = (string) $this->refers; + + return $refers . ($description !== '' ? ($refers !== '' ? ' ' : '') . $description : ''); + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Since.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Since.php new file mode 100644 index 000000000..abfc75022 --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Since.php @@ -0,0 +1,102 @@ +version = $version; + $this->description = $description; + } + + public static function create( + ?string $body, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ): ?self { + if ($body === null || $body === '') { + return new static(); + } + + $matches = []; + if (!preg_match('/^(' . self::REGEX_VECTOR . ')\s*(.+)?$/sux', $body, $matches)) { + return null; + } + + Assert::notNull($descriptionFactory); + + return new static( + $matches[1], + $descriptionFactory->create($matches[2] ?? '', $context) + ); + } + + /** + * Gets the version section of the tag. + */ + public function getVersion(): ?string + { + return $this->version; + } + + /** + * Returns a string representation for this tag. + */ + public function __toString(): string + { + if ($this->description !== null) { + $description = $this->description->render(); + } else { + $description = ''; + } + + $version = (string) $this->version; + + return $version . ($description !== '' ? ($version !== '' ? ' ' : '') . $description : ''); + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Source.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Source.php new file mode 100644 index 000000000..71eefcda6 --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Source.php @@ -0,0 +1,115 @@ +startingLine = (int) $startingLine; + $this->lineCount = $lineCount !== null ? (int) $lineCount : null; + $this->description = $description; + } + + public static function create( + string $body, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ): self { + Assert::stringNotEmpty($body); + Assert::notNull($descriptionFactory); + + $startingLine = 1; + $lineCount = null; + $description = null; + + // Starting line / Number of lines / Description + if (preg_match('/^([1-9]\d*)\s*(?:((?1))\s+)?(.*)$/sux', $body, $matches)) { + $startingLine = (int) $matches[1]; + if (isset($matches[2]) && $matches[2] !== '') { + $lineCount = (int) $matches[2]; + } + + $description = $matches[3]; + } + + return new static($startingLine, $lineCount, $descriptionFactory->create($description ?? '', $context)); + } + + /** + * Gets the starting line. + * + * @return int The starting line, relative to the structural element's + * location. + */ + public function getStartingLine(): int + { + return $this->startingLine; + } + + /** + * Returns the number of lines. + * + * @return int|null The number of lines, relative to the starting line. NULL + * means "to the end". + */ + public function getLineCount(): ?int + { + return $this->lineCount; + } + + public function __toString(): string + { + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + + $startingLine = (string) $this->startingLine; + + $lineCount = $this->lineCount !== null ? ' ' . $this->lineCount : ''; + + return $startingLine + . $lineCount + . ($description !== '' + ? ' ' . $description + : ''); + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TagWithType.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TagWithType.php new file mode 100644 index 000000000..36f43be9b --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TagWithType.php @@ -0,0 +1,50 @@ +type; + } + + final public static function create(string $body): Tag + { + throw new CannotCreateTag('Typed tag cannot be created'); + } + + public function __toString(): string + { + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + + $type = (string) $this->type; + + return $type . ($description !== '' ? ($type !== '' ? ' ' : '') . $description : ''); + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Template.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Template.php new file mode 100644 index 000000000..5009879dd --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Template.php @@ -0,0 +1,85 @@ +name = 'template'; + $this->templateName = $templateName; + $this->bound = $bound; + $this->default = $default; + $this->description = $description; + } + + /** + * @deprecated Create using static factory is deprecated, + * this method should not be called directly by library consumers + */ + public static function create(string $body): ?Tag + { + throw new CannotCreateTag('Template tag cannot be created'); + } + + public function getTemplateName(): string + { + return $this->templateName; + } + + public function getBound(): ?Type + { + return $this->bound; + } + + public function getDefault(): ?Type + { + return $this->default; + } + + public function __toString(): string + { + $bound = $this->bound !== null ? ' of ' . $this->bound : ''; + $default = $this->default !== null ? ' = ' . $this->default : ''; + + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + + return $this->templateName . $bound . $default . ($description !== '' ? ' ' . $description : ''); + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateCovariant.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateCovariant.php new file mode 100644 index 000000000..4ce2a9464 --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateCovariant.php @@ -0,0 +1,30 @@ +name = 'template-covariant'; + $this->type = $type; + $this->description = $description; + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateExtends.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateExtends.php new file mode 100644 index 000000000..8de4681d8 --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateExtends.php @@ -0,0 +1,29 @@ +name = 'template-extends'; + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateImplements.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateImplements.php new file mode 100644 index 000000000..1fb073d99 --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateImplements.php @@ -0,0 +1,29 @@ +name = 'template-implements'; + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Throws.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Throws.php new file mode 100644 index 000000000..675b6f0d3 --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Throws.php @@ -0,0 +1,30 @@ +name = 'throws'; + $this->type = $type; + $this->description = $description; + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Uses.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Uses.php new file mode 100644 index 000000000..8a9849a0e --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Uses.php @@ -0,0 +1,98 @@ +refers = $refers; + $this->description = $description; + } + + public static function create( + string $body, + ?FqsenResolver $resolver = null, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ): self { + Assert::notNull($resolver); + Assert::notNull($descriptionFactory); + + $parts = Utils::pregSplit('/\s+/Su', $body, 2); + + return new static( + self::resolveFqsen($parts[0], $resolver, $context), + $descriptionFactory->create($parts[1] ?? '', $context) + ); + } + + private static function resolveFqsen(string $parts, ?FqsenResolver $fqsenResolver, ?TypeContext $context): Fqsen + { + Assert::notNull($fqsenResolver); + $fqsenParts = explode('::', $parts); + $resolved = $fqsenResolver->resolve($fqsenParts[0], $context); + + if (!array_key_exists(1, $fqsenParts)) { + return $resolved; + } + + return new Fqsen($resolved . '::' . $fqsenParts[1]); + } + + /** + * Returns the structural element this tag refers to. + */ + public function getReference(): Fqsen + { + return $this->refers; + } + + /** + * Returns a string representation of this tag. + */ + public function __toString(): string + { + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + + $refers = (string) $this->refers; + + return $refers . ($description !== '' ? ($refers !== '' ? ' ' : '') . $description : ''); + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Var_.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Var_.php new file mode 100644 index 000000000..495d16f2f --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Var_.php @@ -0,0 +1,68 @@ +name = 'var'; + $this->variableName = $variableName; + $this->type = $type; + $this->description = $description; + } + + /** + * Returns the variable's name. + */ + public function getVariableName(): ?string + { + return $this->variableName; + } + + /** + * Returns a string representation for this tag. + */ + public function __toString(): string + { + if ($this->description !== null) { + $description = $this->description->render(); + } else { + $description = ''; + } + + if ($this->variableName !== null && $this->variableName !== '') { + $variableName = '$' . $this->variableName; + } else { + $variableName = ''; + } + + $type = (string) $this->type; + + return $type + . ($variableName !== '' ? ($type !== '' ? ' ' : '') . $variableName : '') + . ($description !== '' ? ($type !== '' || $variableName !== '' ? ' ' : '') . $description : ''); + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Version.php b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Version.php new file mode 100644 index 000000000..951c8e531 --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Version.php @@ -0,0 +1,105 @@ +version = $version; + $this->description = $description; + } + + public static function create( + ?string $body, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ): ?self { + if ($body === null || $body === '') { + return new static(); + } + + $matches = []; + if (!preg_match('/^(' . self::REGEX_VECTOR . ')\s*(.+)?$/sux', $body, $matches)) { + return null; + } + + $description = null; + if ($descriptionFactory !== null) { + $description = $descriptionFactory->create($matches[2] ?? '', $context); + } + + return new static( + $matches[1], + $description + ); + } + + /** + * Gets the version section of the tag. + */ + public function getVersion(): ?string + { + return $this->version; + } + + /** + * Returns a string representation for this tag. + */ + public function __toString(): string + { + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + + $version = (string) $this->version; + + return $version . ($description !== '' ? ($version !== '' ? ' ' : '') . $description : ''); + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlockFactory.php b/phpdocumentor/reflection-docblock/src/DocBlockFactory.php new file mode 100644 index 000000000..bdd29d19f --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlockFactory.php @@ -0,0 +1,284 @@ +descriptionFactory = $descriptionFactory; + $this->tagFactory = $tagFactory; + } + + /** + * Factory method for easy instantiation. + * + * @param array|Factory> $additionalTags + */ + public static function createInstance(array $additionalTags = []): DocBlockFactoryInterface + { + $fqsenResolver = new FqsenResolver(); + $tagFactory = StandardTagFactory::createInstance($fqsenResolver); + $descriptionFactory = new DescriptionFactory($tagFactory); + + $docBlockFactory = new self($descriptionFactory, $tagFactory); + foreach ($additionalTags as $tagName => $tagHandler) { + $docBlockFactory->registerTagHandler($tagName, $tagHandler); + } + + return $docBlockFactory; + } + + /** + * @param object|string $docblock A string containing the DocBlock to parse or an object supporting the + * getDocComment method (such as a ReflectionClass object). + */ + public function create($docblock, ?Types\Context $context = null, ?Location $location = null): DocBlock + { + if (is_object($docblock)) { + if (!method_exists($docblock, 'getDocComment')) { + $exceptionMessage = 'Invalid object passed; the given object must support the getDocComment method'; + + throw new InvalidArgumentException($exceptionMessage); + } + + $docblock = $docblock->getDocComment(); + Assert::string($docblock); + } + + Assert::stringNotEmpty($docblock); + + if ($context === null) { + $context = new Types\Context(''); + } + + $parts = $this->splitDocBlock($this->stripDocComment($docblock)); + + [$templateMarker, $summary, $description, $tags] = $parts; + + return new DocBlock( + $summary, + $description ? $this->descriptionFactory->create($description, $context) : null, + $this->parseTagBlock($tags, $context), + $context, + $location, + $templateMarker === '#@+', + $templateMarker === '#@-' + ); + } + + /** + * @param class-string|Factory $handler + */ + public function registerTagHandler(string $tagName, $handler): void + { + $this->tagFactory->registerTagHandler($tagName, $handler); + } + + /** + * Strips the asterisks from the DocBlock comment. + * + * @param string $comment String containing the comment text. + */ + private function stripDocComment(string $comment): string + { + $comment = preg_replace('#[ \t]*(?:\/\*\*|\*\/|\*)?[ \t]?(.*)?#u', '$1', $comment); + Assert::string($comment); + $comment = trim($comment); + + // reg ex above is not able to remove */ from a single line docblock + if (substr($comment, -2) === '*/') { + $comment = trim(substr($comment, 0, -2)); + } + + return str_replace(["\r\n", "\r"], "\n", $comment); + } + + // phpcs:disable + + /** + * Splits the DocBlock into a template marker, summary, description and block of tags. + * + * @param string $comment Comment to split into the sub-parts. + * + * @return string[] containing the template marker (if any), summary, description and a string containing the tags. + * + * @author Mike van Riel for extending the regex with template marker support. + * + * @author Richard van Velzen (@_richardJ) Special thanks to Richard for the regex responsible for the split. + */ + private function splitDocBlock(string $comment): array + { + // phpcs:enable + // Performance improvement cheat: if the first character is an @ then only tags are in this DocBlock. This + // method does not split tags so we return this verbatim as the fourth result (tags). This saves us the + // performance impact of running a regular expression + if (strpos($comment, '@') === 0) { + return ['', '', '', $comment]; + } + + // clears all extra horizontal whitespace from the line endings to prevent parsing issues + $comment = preg_replace('/\h*$/Sum', '', $comment); + Assert::string($comment); + /* + * Splits the docblock into a template marker, summary, description and tags section. + * + * - The template marker is empty, #@+ or #@- if the DocBlock starts with either of those (a newline may + * occur after it and will be stripped). + * - The short description is started from the first character until a dot is encountered followed by a + * newline OR two consecutive newlines (horizontal whitespace is taken into account to consider spacing + * errors). This is optional. + * - The long description, any character until a new line is encountered followed by an @ and word + * characters (a tag). This is optional. + * - Tags; the remaining characters + * + * Big thanks to RichardJ for contributing this Regular Expression + */ + preg_match( + '/ + \A + # 1. Extract the template marker + (?:(\#\@\+|\#\@\-)\n?)? + + # 2. Extract the summary + (?: + (?! @\pL ) # The summary may not start with an @ + ( + [^\n.]+ + (?: + (?! \. \n | \n{2} ) # End summary upon a dot followed by newline or two newlines + [\n.]* (?! [ \t]* @\pL ) # End summary when an @ is found as first character on a new line + [^\n.]+ # Include anything else + )* + \.? + )? + ) + + # 3. Extract the description + (?: + \s* # Some form of whitespace _must_ precede a description because a summary must be there + (?! @\pL ) # The description may not start with an @ + ( + [^\n]+ + (?: \n+ + (?! [ \t]* @\pL ) # End description when an @ is found as first character on a new line + [^\n]+ # Include anything else + )* + ) + )? + + # 4. Extract the tags (anything that follows) + (\s+ [\s\S]*)? # everything that follows + /ux', + $comment, + $matches + ); + array_shift($matches); + + while (count($matches) < 4) { + $matches[] = ''; + } + + return $matches; + } + + /** + * Creates the tag objects. + * + * @param string $tags Tag block to parse. + * @param Types\Context $context Context of the parsed Tag + * + * @return DocBlock\Tag[] + */ + private function parseTagBlock(string $tags, Types\Context $context): array + { + $tags = $this->filterTagBlock($tags); + if ($tags === null) { + return []; + } + + $result = []; + $lines = $this->splitTagBlockIntoTagLines($tags); + foreach ($lines as $key => $tagLine) { + $result[$key] = $this->tagFactory->create(trim($tagLine), $context); + } + + return $result; + } + + /** + * @return string[] + */ + private function splitTagBlockIntoTagLines(string $tags): array + { + $result = []; + foreach (explode("\n", $tags) as $tagLine) { + if ($tagLine !== '' && strpos($tagLine, '@') === 0) { + $result[] = $tagLine; + } else { + $result[count($result) - 1] .= "\n" . $tagLine; + } + } + + return $result; + } + + private function filterTagBlock(string $tags): ?string + { + $tags = trim($tags); + if (!$tags) { + return null; + } + + if ($tags[0] !== '@') { + // @codeCoverageIgnoreStart + // Can't simulate this; this only happens if there is an error with the parsing of the DocBlock that + // we didn't foresee. + + throw new LogicException('A tag block started with text instead of an at-sign(@): ' . $tags); + + // @codeCoverageIgnoreEnd + } + + return $tags; + } +} diff --git a/phpdocumentor/reflection-docblock/src/DocBlockFactoryInterface.php b/phpdocumentor/reflection-docblock/src/DocBlockFactoryInterface.php new file mode 100644 index 000000000..cacc382e6 --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/DocBlockFactoryInterface.php @@ -0,0 +1,23 @@ +> $additionalTags + */ + public static function createInstance(array $additionalTags = []): self; + + /** + * @param string|object $docblock + */ + public function create($docblock, ?Types\Context $context = null, ?Location $location = null): DocBlock; +} diff --git a/phpdocumentor/reflection-docblock/src/Exception/CannotCreateTag.php b/phpdocumentor/reflection-docblock/src/Exception/CannotCreateTag.php new file mode 100644 index 000000000..a66884a57 --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/Exception/CannotCreateTag.php @@ -0,0 +1,11 @@ +getMessage(), + 0, + $exception + ); + } +} diff --git a/phpdocumentor/reflection-docblock/src/Exception/PcreException.php b/phpdocumentor/reflection-docblock/src/Exception/PcreException.php new file mode 100644 index 000000000..b8b6da8cf --- /dev/null +++ b/phpdocumentor/reflection-docblock/src/Exception/PcreException.php @@ -0,0 +1,44 @@ +resolve('string'); + echo get_class($type); // phpDocumentor\Reflection\Types\String_ + +The real power of this resolver is in its capability to expand partial class names into fully qualified class names; +but in order to do that we need an additional :php:class:`\phpDocumentor\Reflection\Types\Context` class that +will inform the resolver in which namespace the given expression occurs and which namespace aliases (or imports) apply. + +Read more about the Context class in the next section. diff --git a/phpdocumentor/type-resolver/docs/index.rst b/phpdocumentor/type-resolver/docs/index.rst new file mode 100644 index 000000000..151298316 --- /dev/null +++ b/phpdocumentor/type-resolver/docs/index.rst @@ -0,0 +1,19 @@ +============= +Type resolver +============= + +This project part of the phpDocumentor project. It is capable of creating an object structure of the type +specifications found in the PHPDoc blocks of a project. This can be useful for static analysis of a project +or other behavior that requires knowledge of the types used in a project like automatically build forms. + +This project aims to cover all types that are available in PHPDoc and PHP itself. And is open for extension by +third party developers. + +.. toctree:: + :maxdepth: 2 + :hidden: + + index + getting-started + generics + upgrade-v1-to-v2 diff --git a/phpdocumentor/type-resolver/docs/upgrade-v1-to-v2.rst b/phpdocumentor/type-resolver/docs/upgrade-v1-to-v2.rst new file mode 100644 index 000000000..4f63ad380 --- /dev/null +++ b/phpdocumentor/type-resolver/docs/upgrade-v1-to-v2.rst @@ -0,0 +1,40 @@ +==================== +Upgrade to Version 2 +==================== + +Version 2 of the Type Resolver introduces several breaking changes and new features. This guide will help you +upgrade your codebase to be compatible with the latest version. The usage of the TypeResolver remains the same. However, +some classes have been moved or replaced, and the minimum PHP version requirement has been raised. + +PHP Version +----------- + +Version 2 requires PHP 7.4 or higher. We have been supporting PHP 7.3 in version 1, but due to changing constraints +in our dependencies, we have had to raise the minimum PHP version. At the moment of writing this, PHP 7.3 is used by 2% +of all installations of this package according to Packagist. We believe this is a reasonable trade-off to ensure we +can continue to deliver new features and improvements. + +Moved classes +------------- + +- ``phpDocumentor\Reflection\Types\InterfaceString`` => :php:class:`phpDocumentor\Reflection\PseudoTypes\InterfaceString` +- ``phpDocumentor\Reflection\Types\ClassString`` => :php:class:`phpDocumentor\Reflection\PseudoTypes\ClassString` +- ``phpDocumentor\Reflection\Types\ArrayKey`` => :php:class:`phpDocumentor\Reflection\PseudoTypes\ArrayKey` +- ``phpDocumentor\Reflection\Types\True_`` => :php:class:`phpDocumentor\Reflection\PseudoTypes\True_` +- ``phpDocumentor\Reflection\Types\False_`` => :php:class:`phpDocumentor\Reflection\PseudoTypes\False_` + +Replaced classes +----------------- + +- ``phpDocumentor\Reflection\Types\Collection`` => :php:class:`phpDocumentor\Reflection\PseudoTypes\Generic` + +Since the introduction of generics in PHP this library was not capable of parsing them correctly. The old Collection +was blocking the use of generics. The new Generic type is a representation of generics like supported in the eco system. + +Changed implementations +----------------------- + +:php:class:`phpDocumentor\Reflection\PseudoTypes\InterfaceString`, :php:class:`phpDocumentor\Reflection\PseudoTypes\ClassString` and +:php:class:`phpDocumentor\Reflection\PseudoTypes\TraitString` are no longer returning a :php:class:`phpDocumentor\Reflection\Fqsen` since +support for generics these classes can have type arguments like any other generic. + diff --git a/phpdocumentor/type-resolver/phpdoc.dist.xml b/phpdocumentor/type-resolver/phpdoc.dist.xml new file mode 100644 index 000000000..6c9899114 --- /dev/null +++ b/phpdocumentor/type-resolver/phpdoc.dist.xml @@ -0,0 +1,46 @@ + + + Type Resolver + + build/docs + + + latest + + + src/ + + api + + + php + + + template + template-extends + template-implements + extends + implements + + phpDocumentor + + + + docs + + guides + + + +